From 2c26eb4e484fe6d7a8159a22f97b6db7ca6e9221 Mon Sep 17 00:00:00 2001 From: Rui Salvaterra Date: Wed, 23 Mar 2022 09:47:19 +0000 Subject: [PATCH 01/26] kernel: bump 5.10 to 5.10.108 Patches automatically rebased. Build system: x86_64 Build-tested: bcm2711/RPi4B, mt7622/RT3200 Run-tested: bcm2711/RPi4B, mt7622/RT3200 Tested-by: John Audia Build-tested: ath79/generic, ramips/mt76{20,21,x8}, ipq40xx, mvebu, realtek/rtl{838,930}x, x86/64 Run-tested: ramips/mt7621, mvebu Tested-by: Stijn Segers Signed-off-by: Daniel Golle Signed-off-by: Rui Salvaterra --- include/kernel-5.10 | 4 ++-- .../950-0006-smsx95xx-fix-crimes-against-truesize.patch | 4 ++-- ...95xx-Experimental-Enable-turbo_mode-and-packetsi.patch | 2 +- ...950-0008-Allow-mac-address-to-be-set-in-smsc95xx.patch | 4 ++-- ...31-bcmgenet-Better-coalescing-parameter-defaults.patch | 4 ++-- ...-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch | 2 +- .../950-0334-net-bcmgenet-Reset-RBUF-on-first-open.patch | 8 ++++---- .../generic/pending-5.10/630-packet_socket_type.patch | 6 +++--- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/kernel-5.10 b/include/kernel-5.10 index aa61efeb7b..954c35edac 100644 --- a/include/kernel-5.10 +++ b/include/kernel-5.10 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.10 = .107 -LINUX_KERNEL_HASH-5.10.107 = c467c3077946370fb26c9277313b601d6c48bb557abc889f4892caf627fcdfea +LINUX_VERSION-5.10 = .108 +LINUX_KERNEL_HASH-5.10.108 = bf6cc2d6e0918b8f34d1cde2fa39a6ad69c45025425048be1a1dac4a5b3641d8 diff --git a/target/linux/bcm27xx/patches-5.10/950-0006-smsx95xx-fix-crimes-against-truesize.patch b/target/linux/bcm27xx/patches-5.10/950-0006-smsx95xx-fix-crimes-against-truesize.patch index a12202d55e..1311400c2b 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0006-smsx95xx-fix-crimes-against-truesize.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0006-smsx95xx-fix-crimes-against-truesize.patch @@ -25,7 +25,7 @@ Signed-off-by: Steve Glendinning static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1830,7 +1834,8 @@ static int smsc95xx_rx_fixup(struct usbn +@@ -1839,7 +1843,8 @@ static int smsc95xx_rx_fixup(struct usbn if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ @@ -35,7 +35,7 @@ Signed-off-by: Steve Glendinning return 1; } -@@ -1848,7 +1853,8 @@ static int smsc95xx_rx_fixup(struct usbn +@@ -1857,7 +1862,8 @@ static int smsc95xx_rx_fixup(struct usbn if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ diff --git a/target/linux/bcm27xx/patches-5.10/950-0007-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch b/target/linux/bcm27xx/patches-5.10/950-0007-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch index 025b052333..0c010de8c8 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0007-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0007-smsc95xx-Experimental-Enable-turbo_mode-and-packetsi.patch @@ -22,7 +22,7 @@ See: http://forum.kodi.tv/showthread.php?tid=285288 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -905,13 +909,13 @@ static int smsc95xx_reset(struct usbnet +@@ -917,13 +921,13 @@ static int smsc95xx_reset(struct usbnet if (!turbo_mode) { burst_cap = 0; diff --git a/target/linux/bcm27xx/patches-5.10/950-0008-Allow-mac-address-to-be-set-in-smsc95xx.patch b/target/linux/bcm27xx/patches-5.10/950-0008-Allow-mac-address-to-be-set-in-smsc95xx.patch index 1cf4d21a57..32caf0cb84 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0008-Allow-mac-address-to-be-set-in-smsc95xx.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0008-Allow-mac-address-to-be-set-in-smsc95xx.patch @@ -29,7 +29,7 @@ Signed-off-by: popcornmix static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -761,6 +766,53 @@ static int smsc95xx_ioctl(struct net_dev +@@ -773,6 +778,53 @@ static int smsc95xx_ioctl(struct net_dev return phy_mii_ioctl(netdev->phydev, rq, cmd); } @@ -83,7 +83,7 @@ Signed-off-by: popcornmix static void smsc95xx_init_mac_address(struct usbnet *dev) { /* maybe the boot loader passed the MAC address in devicetree */ -@@ -783,6 +835,10 @@ static void smsc95xx_init_mac_address(st +@@ -795,6 +847,10 @@ static void smsc95xx_init_mac_address(st } } diff --git a/target/linux/bcm27xx/patches-5.10/950-0131-bcmgenet-Better-coalescing-parameter-defaults.patch b/target/linux/bcm27xx/patches-5.10/950-0131-bcmgenet-Better-coalescing-parameter-defaults.patch index 5a37f84e17..97fc9183fb 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0131-bcmgenet-Better-coalescing-parameter-defaults.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0131-bcmgenet-Better-coalescing-parameter-defaults.patch @@ -18,7 +18,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -2595,7 +2595,7 @@ static void bcmgenet_init_tx_ring(struct +@@ -2597,7 +2597,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX); bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX); @@ -27,7 +27,7 @@ Signed-off-by: Phil Elwell /* Disable rate control for now */ bcmgenet_tdma_ring_writel(priv, index, flow_period_val, TDMA_FLOW_PERIOD); -@@ -4060,9 +4060,12 @@ static int bcmgenet_probe(struct platfor +@@ -4062,9 +4062,12 @@ static int bcmgenet_probe(struct platfor netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1); /* Set default coalescing parameters */ diff --git a/target/linux/bcm27xx/patches-5.10/950-0153-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch b/target/linux/bcm27xx/patches-5.10/950-0153-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch index 5f446dcc2f..5dd12974fb 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0153-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0153-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch @@ -37,7 +37,7 @@ Signed-off-by: Phil Elwell static inline void bcmgenet_writel(u32 value, void __iomem *offset) { -@@ -2426,6 +2429,11 @@ static void reset_umac(struct bcmgenet_p +@@ -2428,6 +2431,11 @@ static void reset_umac(struct bcmgenet_p bcmgenet_rbuf_ctrl_set(priv, 0); udelay(10); diff --git a/target/linux/bcm27xx/patches-5.10/950-0334-net-bcmgenet-Reset-RBUF-on-first-open.patch b/target/linux/bcm27xx/patches-5.10/950-0334-net-bcmgenet-Reset-RBUF-on-first-open.patch index 78bbc10649..184804ad50 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0334-net-bcmgenet-Reset-RBUF-on-first-open.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0334-net-bcmgenet-Reset-RBUF-on-first-open.patch @@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -3244,7 +3244,7 @@ static void bcmgenet_get_hw_addr(struct +@@ -3246,7 +3246,7 @@ static void bcmgenet_get_hw_addr(struct } /* Returns a reusable dma control register value */ @@ -33,7 +33,7 @@ Signed-off-by: Phil Elwell { unsigned int i; u32 reg; -@@ -3269,6 +3269,14 @@ static u32 bcmgenet_dma_disable(struct b +@@ -3271,6 +3271,14 @@ static u32 bcmgenet_dma_disable(struct b udelay(10); bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); @@ -48,7 +48,7 @@ Signed-off-by: Phil Elwell return dma_ctrl; } -@@ -3332,8 +3340,8 @@ static int bcmgenet_open(struct net_devi +@@ -3334,8 +3342,8 @@ static int bcmgenet_open(struct net_devi bcmgenet_set_hw_addr(priv, dev->dev_addr); @@ -59,7 +59,7 @@ Signed-off-by: Phil Elwell /* Reinitialize TDMA and RDMA and SW housekeeping */ ret = bcmgenet_init_dma(priv); -@@ -4189,7 +4197,7 @@ static int bcmgenet_resume(struct device +@@ -4191,7 +4199,7 @@ static int bcmgenet_resume(struct device bcmgenet_hfb_create_rxnfc_filter(priv, rule); /* Disable RX/TX DMA and flush TX queues */ diff --git a/target/linux/generic/pending-5.10/630-packet_socket_type.patch b/target/linux/generic/pending-5.10/630-packet_socket_type.patch index bf319d4bac..5b396c3a8c 100644 --- a/target/linux/generic/pending-5.10/630-packet_socket_type.patch +++ b/target/linux/generic/pending-5.10/630-packet_socket_type.patch @@ -87,7 +87,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -3322,6 +3324,7 @@ static int packet_create(struct net *net +@@ -3325,6 +3327,7 @@ static int packet_create(struct net *net mutex_init(&po->pg_vec_lock); po->rollover = NULL; po->prot_hook.func = packet_rcv; @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau if (sock->type == SOCK_PACKET) po->prot_hook.func = packet_rcv_spkt; -@@ -3960,6 +3963,16 @@ packet_setsockopt(struct socket *sock, i +@@ -3969,6 +3972,16 @@ packet_setsockopt(struct socket *sock, i po->xmit = val ? packet_direct_xmit : dev_queue_xmit; return 0; } @@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau default: return -ENOPROTOOPT; } -@@ -4016,6 +4029,13 @@ static int packet_getsockopt(struct sock +@@ -4025,6 +4038,13 @@ static int packet_getsockopt(struct sock case PACKET_VNET_HDR: val = po->has_vnet_hdr; break; From 13960fb0e0babcd99530fcb234073af0c0a5e2f5 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 26 Mar 2022 22:51:21 +0000 Subject: [PATCH 02/26] generic: sync mtd rootfs hack with part_bits In commit ab143647ef ("kernel: generic: improve FIT partition parser") part_bits was bumped to 2 in order to allow up to 3 additional FIT sub-images mapped into sub-partitions. This change has to be reflected also in our local patch 420-mtd-set-rootfs-to-be-root-dev.patch which still assumed part_bits==1 for mtdblock devices in case of CONFIG_FIT_PARTITION=y. Fixes: #9557 Fixes: ab143647ef ("kernel: generic: improve FIT partition parser") Signed-off-by: Daniel Golle --- .../generic/hack-5.10/420-mtd-set-rootfs-to-be-root-dev.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/generic/hack-5.10/420-mtd-set-rootfs-to-be-root-dev.patch b/target/linux/generic/hack-5.10/420-mtd-set-rootfs-to-be-root-dev.patch index 91a91b36ca..b071ac61ec 100644 --- a/target/linux/generic/hack-5.10/420-mtd-set-rootfs-to-be-root-dev.patch +++ b/target/linux/generic/hack-5.10/420-mtd-set-rootfs-to-be-root-dev.patch @@ -32,7 +32,7 @@ Signed-off-by: Gabor Juhos + pr_notice("mtd: device %d (%s) set to be root filesystem\n", + mtd->index, mtd->name); +#ifdef CONFIG_FIT_PARTITION -+ index <<= 1; ++ index <<= 2; +#endif + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, index); + } From 9a038e7fd12eae3695875232962f96af8252f3ba Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 4 Nov 2021 21:52:43 +0100 Subject: [PATCH 03/26] generic: 5.15: copy config and patch from 5.10 Copy config and patches from kernel 5.10 to kernel 5.15 Signed-off-by: Ansuel Smith --- ...dcode-path-to-awk-in-scripts-ld-vers.patch | 30 + .../011-kbuild-export-SUBARCH.patch | 21 + ...station-poweroff-add-missing-put_dev.patch | 27 + ...-uasm-Enable-muhu-opcode-for-MIPS-R6.patch | 65 + ...rkaround-for-Loongson-2F-nop-CPU-err.patch | 31 + ...ips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch | 3078 +++++++ ...bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch | 1005 +++ ...f-Add-JIT-workarounds-for-CPU-errata.patch | 120 + ...0-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch | 61 + ...f-Remove-old-BPF-JIT-implementations.patch | 387 + ...a-neon-optimize-for-non-block-size-m.patch | 272 + ...a-neon-add-missing-counter-increment.patch | 38 + ...ut-frequently-used-members-above-cac.patch | 42 + ...to-define-reg_update_bits-for-no-bus.patch | 52 + ...CPU_MIPS64-for-remaining-MIPS64-CPUs.patch | 36 + ...boot-put-appended-dtb-into-a-section.patch | 36 + ...ow_offload-handle-netdevice-events-f.patch | 106 + ...convert-fixed-partitions-to-the-json.patch | 324 + ...move-partition-binding-to-its-own-fi.patch | 115 + ...d-add-binding-for-BCM4908-partitions.patch | 92 + ...art-support-BCM4908-fixed-partitions.patch | 654 ++ ...rt-limit-parsing-of-deprecated-DT-sy.patch | 69 + ...rt-make-symbol-bcm4908_partitions_qu.patch | 34 + ...em-cells-compatible-to-parse-mtd-as-.patch | 38 + ...ings-nvmem-drop-nodename-restriction.patch | 25 + ...Document-use-of-nvmem-cells-compatib.patch | 117 + ...add-binding-for-Linksys-Northstar-pa.patch | 98 + ...rt-support-Linksys-Northstar-partiti.patch | 156 + ...0002-Disable-buffered-writes-for-AMD.patch | 54 + ...ings-mtd-brcm-trx-Add-brcm-trx-magic.patch | 32 + ...Allow-to-specify-brcm-trx-magic-in-D.patch | 50 + ...Allow-to-use-TRX-parser-on-Mediatek-.patch | 25 + ...x-allow-to-use-on-MediaTek-MIPS-SoCs.patch | 33 + ...13-ubifs-default-to-zstd-compression.patch | 25 + ...pi-poll-functionality-to-__napi_poll.patch | 88 + ...threaded-able-napi-poll-loop-support.patch | 261 + ...tribute-to-control-napi-threaded-mod.patch | 177 + ...ween-napi-kthread-mode-and-busy-poll.patch | 93 + ...up-on-napi_disable-for-threaded-napi.patch | 53 + ...table-add-hash-offset-field-to-tuple.patch | 52 + ...ble-separate-replace-destroy-and-sta.patch | 98 + ...ack-Remove-unused-variable-declarati.patch | 22 + ...ble-consolidate-skb_try_make_writabl.patch | 291 + ...ble-move-skb_try_make_writable-befor.patch | 35 + ...ble-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch | 82 + ...wtable-fast-NAT-functions-never-fail.patch | 394 + ...ble-call-dst_check-to-fall-back-to-c.patch | 46 + ...ble-refresh-timeout-after-dst-and-wr.patch | 49 + ...es-update-table-flags-from-the-commi.patch | 103 + ...arding-path-from-virtual-netdevice-a.patch | 170 + ...lve-forwarding-path-for-vlan-devices.patch | 80 + ...ve-forwarding-path-for-bridge-device.patch | 62 + ...ve-forwarding-path-for-VLAN-tag-acti.patch | 207 + ...forwarding-path-for-bridge-pppoe-dev.patch | 113 + ...-forwarding-path-for-dsa-slave-ports.patch | 63 + ...filter-flowtable-add-xmit-path-types.patch | 147 + ...ble-use-dev_fill_forward_path-to-obt.patch | 191 + ...ble-use-dev_fill_forward_path-to-obt.patch | 374 + ...netfilter-flowtable-add-vlan-support.patch | 410 + ...ble-add-bridge-vlan-filtering-suppor.patch | 30 + ...etfilter-flowtable-add-pppoe-support.patch | 145 + ...-netfilter-flowtable-add-dsa-support.patch | 32 + ...ter-flowtable-bridge-and-vlan-suppor.patch | 107 + ...ble-add-offload-support-for-xmit-pat.patch | 310 + ...ow_offload-use-direct-xmit-if-hardwa.patch | 114 + ...ble-bridge-vlan-hardware-offload-and.patch | 123 + ...w_offload-add-FLOW_ACTION_PPPOE_PUSH.patch | 30 + ...ble-support-for-FLOW_ACTION_PPPOE_PU.patch | 35 + ...sa-slave-add-support-for-TC_SETUP_FT.patch | 53 + ...k_eth_soc-fix-parsing-packets-in-GDM.patch | 68 + ..._eth_soc-add-support-for-initializin.patch | 1308 +++ ..._eth_soc-add-flow-offloading-support.patch | 568 ++ ...e-update-documentation-with-enhancem.patch | 236 + ...rnet-mediatek-ppe-fix-busy-wait-loop.patch | 72 + ...iatek-fix-a-typo-bug-in-flow-offload.patch | 29 + ..._eth_soc-unmap-RX-data-before-callin.patch | 38 + ...et-mtk_eth_soc-fix-build_skb-cleanup.patch | 38 + ...net-mtk_eth_soc-use-napi_consume_skb.patch | 77 + ..._eth_soc-reduce-MDIO-bus-access-late.patch | 30 + ..._eth_soc-remove-unnecessary-TX-queue.patch | 54 + ..._eth_soc-use-larger-burst-size-for-Q.patch | 37 + ...-mtk_eth_soc-increase-DMA-ring-sizes.patch | 26 + ..._eth_soc-implement-dynamic-interrupt.patch | 313 + ..._eth_soc-cache-HW-pointer-of-last-fr.patch | 73 + ..._eth_soc-only-read-the-full-RX-descr.patch | 49 + ..._eth_soc-reduce-unnecessary-interrup.patch | 39 + ...et-mtk_eth_soc-rework-NAPI-callbacks.patch | 110 + ..._eth_soc-set-PPE-flow-hash-as-skb-ha.patch | 47 + ..._eth_soc-use-iopoll.h-macro-for-DMA-.patch | 71 + ...t-ethernet-mtk_eth_soc-missing-mutex.patch | 63 + ...t-mtk_eth_soc-handle-VLAN-pop-action.patch | 22 + ...ble-dst_check-from-garbage-collector.patch | 159 + ...ack-Introduce-tcp-offload-timeout-co.patch | 94 + ...ack-Introduce-udp-offload-timeout-co.patch | 92 + ...ble-Set-offload-timeouts-according-t.patch | 134 + ...thernet-mediatek-support-setting-MTU.patch | 138 + ...x-select-correct-page-on-config-init.patch | 108 + ...ix-probe-error-if-copper-page-is-sel.patch | 73 + ...10-v5.12-net-phy-Add-100-base-x-mode.patch | 56 + ...-sfp-add-support-for-100-base-x-SFPs.patch | 40 + ...phy-marvell-refactor-HWMON-OOP-style.patch | 549 ++ ...-marvell-add-SFP-support-for-88E1510.patch | 161 + ...cally-bring-up-DSA-master-when-openi.patch | 85 + ...y-switchdev-of-disappearance-of-old-.patch | 126 + ...r-when-a-non-legacy-FDB-operation-fa.patch | 52 + ...e-switchdev_notifier_fdb_info-in-dsa.patch | 226 + ...tchdev-event-implementation-under-th.patch | 85 + ...ly-in-dsa_slave_switchdev_event-if-w.patch | 42 + ...or-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch | 264 + ...setup-core-clock-even-in-TRGMII-mode.patch | 84 + ...-mt7530-MT7530-optional-GPIO-support.patch | 181 + ...-mt7530-Add-support-for-EEE-features.patch | 120 + ...the-dst-buffer-to-of_get_mac_address.patch | 1935 +++++ ..._addr_nvmem-for-non-platform-devices.patch | 77 + ...andle-deferred-probe-error-due-to-ma.patch | 42 + ...platform-handle-mac-address-deferral.patch | 36 + ...-0001-net-bgmac-improve-handling-PHY.patch | 84 + ...t-bgmac-support-MDIO-described-in-DT.patch | 54 + ...k-change-simple-print-to-dev-variant.patch | 35 + ...use-iopoll-macro-for-qca8k_busy_wait.patch | 61 + ...prove-qca8k-read-write-rmw-bus-acces.patch | 86 + ...a-qca8k-handle-qca8k_set_page-errors.patch | 101 + ...ndle-error-with-qca8k_read-operation.patch | 207 + ...ndle-error-with-qca8k_write-operatio.patch | 263 + ...andle-error-with-qca8k_rmw-operation.patch | 226 + ...8k-handle-error-from-qca8k_busy_wait.patch | 66 + ...qca8k-add-support-for-qca8327-switch.patch | 96 + ...sa-qca8k-Document-new-compatible-qca.patch | 26 + ...add-priority-tweak-to-qca8337-switch.patch | 130 + ...a-qca8k-limit-port5-delay-to-qca8337.patch | 31 + ...d-GLOBAL_FC-settings-needed-for-qca8.patch | 48 + ...dsa-qca8k-add-support-for-switch-rev.patch | 114 + ...d-ethernet-ports-fallback-to-setup_m.patch | 28 + ...-qca8k-make-rgmii-delay-configurable.patch | 188 + ...clear-MASTER_EN-after-phy-read-write.patch | 50 + ...a-qca8k-protect-MASTER-busy_wait-wit.patch | 128 + ...qca8k-enlarge-mdio-delay-and-timeout.patch | 39 + ...d-support-for-internal-phy-and-inter.patch | 267 + ...ngs-dsa-qca8k-Document-internal-mdio.patch | 93 + ...prove-internal-mdio-read-write-bus-a.patch | 95 + ...ss-switch_revision-info-to-phy-dev_f.patch | 48 + ...ort-for-qca8k-switch-internal-PHY-in.patch | 229 + ...issing-unlock-on-error-in-qca8k-vlan.patch | 64 + ...eck-return-value-of-read-functions-c.patch | 348 + ...d-missing-check-return-value-in-qca8.patch | 47 + ...x-an-endian-bug-in-qca8k-get-ethtool.patch | 47 + ...eck-the-correct-variable-in-qca8k-se.patch | 31 + ...ernel-panic-with-legacy-mdio-mapping.patch | 80 + ...-Add-debug-prints-in-b53_vlan_enable.patch | 65 + ...sa-b53-spi-allow-device-tree-probing.patch | 41 + ...3-net-dsa-b53-relax-is63xx-condition.patch | 31 + ...tag_brcm-add-support-for-legacy-tags.patch | 180 + ...0005-net-dsa-b53-support-legacy-tags.patch | 53 + ...dsa-b53-mmap-Add-device-tree-support.patch | 92 + ...-spi-add-missing-MODULE_DEVICE_TABLE.patch | 27 + ...Do-not-force-CPU-to-be-always-tagged.patch | 86 + ...3-remove-redundant-null-check-on-dev.patch | 30 + ...Create-default-VLAN-entry-explicitly.patch | 71 + ...dd-support-for-qca-8327-internal-phy.patch | 48 + ...3-Include-all-ports-in-enabled_ports.patch | 131 + ...-BCM5301x-workaround-for-a-wrong-CPU.patch | 42 + ...prove-flow-control-setup-on-BCM5301x.patch | 32 + ...t-dsa-b53-Drop-unused-cpu_port-field.patch | 205 + ...t-skb-offload_fwd_mark-when-not-offl.patch | 138 + ...x-add-support-for-qca-8327-A-variant.patch | 65 + ...dd-resume-suspend-function-to-qca83x.patch | 45 + ...ix-spacing-and-improve-name-for-83xx.patch | 95 + ...hy-at803x-fix-resume-for-QCA8327-phy.patch | 131 + ...x-add-DAC-amplitude-fix-for-8327-phy.patch | 91 + ...nable-prefer-master-for-83xx-interna.patch | 27 + ...hy-at803x-better-describe-debug-regs.patch | 127 + ...-dsa-qca8k-add-mac-power-sel-support.patch | 80 + ...dsa-qca8k-Add-SGMII-clock-phase-prop.patch | 30 + ...k-add-support-for-sgmii-falling-edge.patch | 127 + ...dsa-qca8k-Document-support-for-CPU-p.patch | 29 + ...dsa-qca8k-add-support-for-cpu-port-6.patch | 153 + ...work-rgmii-delay-logic-and-scan-for-.patch | 295 + ...dsa-qca8k-Document-qca-sgmii-enable-.patch | 33 + ...-qca8k-add-explicit-SGMII-PLL-enable.patch | 65 + ...dsa-qca8k-Document-qca-led-open-drai.patch | 37 + ...qca8k-add-support-for-pws-config-reg.patch | 92 + ...dsa-qca8k-document-support-for-qca83.patch | 32 + ...et-dsa-qca8k-add-support-for-QCA8328.patch | 78 + ...8k-set-internal-delay-also-for-sgmii.patch | 159 + ...move-port-config-to-dedicated-struct.patch | 124 + ...ipq8064-mdio-fix-warning-with-new-qc.patch | 26 + ...net-dsa-qca8k-convert-to-YAML-schema.patch | 631 ++ ...elay-applied-to-wrong-cpu-in-parse-p.patch | 28 + ...for-loop-in-setup-and-add-cpu-port-c.patch | 151 + ...sure-pad0-mac06-exchange-is-disabled.patch | 47 + ...ernal-delay-applied-to-the-wrong-PAD.patch | 48 + ...16-net-dsa-qca8k-fix-MTU-calculation.patch | 46 + ...redundant-check-in-parse_port_config.patch | 29 + ...vert-to-GENMASK_FIELD_PREP_FIELD_GET.patch | 508 ++ ...move-extra-mutex_init-in-qca8k_setup.patch | 25 + ...move-regmap-init-in-probe-and-set-it.patch | 46 + ...k-initial-conversion-to-regmap-heper.patch | 249 + ...ca8k-add-additional-MIB-counter-and-.patch | 120 + ...ca8k-add-support-for-port-fast-aging.patch | 53 + ...sa-qca8k-add-set_ageing_time-support.patch | 78 + ...sa-qca8k-add-support-for-mdb_add-del.patch | 142 + ...1-net-dsa-mt7530-support-setting-MTU.patch | 112 + ...-dsa-mt7530-enable-MTU-normalization.patch | 36 + ...a-mt7530-support-setting-ageing-time.patch | 99 + ...disable-learning-on-standalone-ports.patch | 65 + ...enable-assisted-learning-on-CPU-port.patch | 102 + ...se-independent-VLAN-learning-on-VLAN.patch | 262 + ...-mt7530-set-STP-state-on-filter-ID-1.patch | 40 + ...lways-install-FDB-entries-with-IVL-a.patch | 54 + ...et-dsa-mt7530-support-MDB-operations.patch | 171 + ...MediaTek-Gigabit-Ethernet-PHY-driver.patch | 159 + ...net-dsa-mt7530-add-interrupt-support.patch | 425 + ...N-filtering-syncing-out-of-dsa_switc.patch | 83 + ...cross-chip-syncing-of-VLAN-filtering.patch | 58 + ...5.15-1-igc-remove-_I_PHY_ID-checking.patch | 73 + ...v5.15-2-igc-remove-phy-type-checking.patch | 43 + ...ovide-missing-documentation-for-some.patch | 72 + ...x-a-couple-of-spelling-errors-in-fw_.patch | 34 + ...153_ecm-support-ECM-mode-for-RTL8153.patch | 320 + ...12-net-usb-r8152-use-new-tasklet-API.patch | 41 + ...veral-functions-about-phy-patch-requ.patch | 198 + ...t-the-flow-of-power-cut-for-RTL8153B.patch | 134 + ...152-enable-U1-U2-for-USB_SPEED_SUPER.patch | 47 + ...f-the-pointer-of-the-function-exists.patch | 51 + ...r8152-replace-netif_err-with-dev_err.patch | 36 + ...rtl_set_eee_plus-and-r8153b_green_en.patch | 89 + ...ter-fram-gap-time-depending-on-speed.patch | 75 + ...just-rtl8152_check_firmware-function.patch | 152 + ...8152-add-help-function-to-change-mtu.patch | 157 + .../793-v5.13-r8152-support-new-chips.patch | 2886 +++++++ ...port-PHY-firmware-for-RTL8156-series.patch | 691 ++ ...rch-the-configuration-of-vendor-mode.patch | 79 + ..._nvram-rename-finding-function-and-i.patch | 80 + ..._nvram-add-helper-checking-for-NVRAM.patch | 90 + ...7xx_nvram-extract-code-copying-NVRAM.patch | 80 + ..._nvram-look-for-NVRAM-with-for-inste.patch | 37 + ..._nvram-inline-code-checking-NVRAM-si.patch | 70 + ...rious-flag-to-disable-overcurrent-ch.patch | 88 + ...-platform-add-spurious_oc-DT-support.patch | 31 + ...-declare-its-reliance-on-msi-domains.patch | 34 + ...declar-their-reliance-on-msi-domains.patch | 44 + ...ertise-lack-of-built-in-msi-handling.patch | 59 + ...ialize-enable-GPIO-direction-to-outp.patch | 28 + ...mul-Add-description-for-class_revisi.patch | 44 + ...mul-Add-definitions-for-missing-capa.patch | 73 + ...-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch | 61 + ...PCI-aardvark-Clear-all-MSIs-at-setup.patch | 59 + ...ment-actions-in-driver-remove-method.patch | 34 + ...able-bus-mastering-when-unbinding-dr.patch | 41 + ...k-all-interrupts-when-unbinding-driv.patch | 48 + ...ark-Fix-memory-leak-in-driver-unbind.patch | 33 + ...k-Assert-PERST-when-unbinding-driver.patch | 33 + ...able-link-training-when-unbinding-dr.patch | 34 + ...able-common-PHY-when-unbinding-drive.patch | 30 + ...mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch | 67 + ...mvebu-a3700-comphy-Remove-unsupporte.patch | 40 + ...PS-ath79-drop-_machine_restart-again.patch | 49 + ...ext-hwmon-lm70-Add-ti-tmp125-support.patch | 71 + target/linux/generic/config-5.15 | 7179 +++++++++++++++++ .../generic/hack-5.15/204-module_strip.patch | 212 + .../generic/hack-5.15/205-kconfig-exit.patch | 11 + .../210-darwin_scripts_include.patch | 3053 +++++++ .../211-darwin-uuid-typedef-clash.patch | 22 + .../hack-5.15/212-tools_portability.patch | 110 + .../hack-5.15/214-spidev_h_portability.patch | 24 + .../hack-5.15/220-arm-gc_sections.patch | 123 + .../hack-5.15/221-module_exports.patch | 102 + .../hack-5.15/230-openwrt_lzma_options.patch | 34 + .../hack-5.15/249-udp-tunnel-selection.patch | 11 + .../hack-5.15/250-netfilter_depends.patch | 27 + .../linux/generic/hack-5.15/251-kconfig.patch | 199 + .../generic/hack-5.15/252-SATA_PMP.patch | 23 + .../generic/hack-5.15/253-ksmbd-config.patch | 22 + .../hack-5.15/259-regmap_dynamic.patch | 135 + .../260-crypto_test_dependencies.patch | 52 + .../hack-5.15/261-lib-arc4-unhide.patch | 15 + .../generic/hack-5.15/280-rfkill-stubs.patch | 84 + ...cache-use-more-efficient-cache-blast.patch | 64 + .../301-mips_image_cmdline_hack.patch | 38 + .../321-powerpc_crtsavres_prereq.patch | 38 + ...don-t-reply-on-mtdblock-device-minor.patch | 85 + ...rans-call-add-disks-after-mtd-device.patch | 98 + .../410-block-fit-partition-parser.patch | 224 + .../420-mtd-set-rootfs-to-be-root-dev.patch | 42 + ...ers-add-nvmem-support-to-cmdlinepart.patch | 120 + .../hack-5.15/430-mtk-bmt-support.patch | 23 + .../generic/hack-5.15/531-debloat_lzma.patch | 1040 +++ .../hack-5.15/600-bridge_offload.patch | 817 ++ ...lter-connmark-introduce-set-dscpmark.patch | 212 + ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 819 ++ .../hack-5.15/651-wireless_mesh_header.patch | 24 + .../hack-5.15/660-fq_codel_defaults.patch | 27 + .../700-swconfig_switch_drivers.patch | 129 + .../710-net-dsa-mv88e6xxx-default-VID-1.patch | 18 + ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 12 + .../hack-5.15/720-net-phy-add-aqr-phys.patch | 142 + .../721-net-add-packet-mangeling.patch | 167 + ...hy-aquantia-enable-AQR112-and-AQR412.patch | 154 + ...aquantia-fix-system-side-protocol-mi.patch | 34 + ...y-aquantia-Add-AQR113-driver-support.patch | 43 + ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 63 + ...-r8152-add-LED-configuration-from-OF.patch | 74 + ...et-add-RTL8152-binding-documentation.patch | 54 + .../hack-5.15/773-bgmac-add-srab-switch.patch | 98 + .../780-usb-net-MeigLink_modem_support.patch | 33 + .../800-GPIO-add-named-gpio-exports.patch | 162 + .../hack-5.15/901-debloat_sock_diag.patch | 162 + .../generic/hack-5.15/902-debloat_proc.patch | 408 + .../hack-5.15/904-debloat_dma_buf.patch | 92 + .../hack-5.15/910-kobject_uevent.patch | 32 + .../911-kobject_add_broadcast_uevent.patch | 76 + .../hack-5.15/920-device_tree_cmdline.patch | 12 + ...terrupt-provider-address-cells-check.patch | 28 + ...include-asm-rwonce.h-for-kernel-code.patch | 29 + ...-Use-stddefs.h-instead-of-compiler.h.patch | 11 + ...s-negative-stack-offsets-on-stack-tr.patch | 57 + ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 82 + ...0-add-linux-spidev-compatible-si3210.patch | 18 + ...ame2-and-add-RENAME_WHITEOUT-support.patch | 78 + ...41-jffs2-add-RENAME_EXCHANGE-support.patch | 73 + .../142-jffs2-add-splice-ops.patch | 20 + ...ge_allow_receiption_on_disabled_port.patch | 45 + ...-rs5c372-support_alarms_up_to_1_week.patch | 94 + ...he_alarm_to_be_used_as_wakeup_source.patch | 70 + .../pending-5.15/201-extra_optimization.patch | 31 + .../203-kallsyms_uncompressed.patch | 119 + .../205-backtrace_module_info.patch | 41 + ...e-filenames-from-deps_initramfs-list.patch | 30 + ...able_wilink_platform_without_drivers.patch | 20 + .../270-platform-mikrotik-build-bits.patch | 31 + .../300-mips_expose_boot_raw.patch | 40 + .../302-mips_no_branch_likely.patch | 22 + .../pending-5.15/305-mips_module_reloc.patch | 371 + .../307-mips_highmem_offset.patch | 19 + .../pending-5.15/308-mips32r2_tune.patch | 22 + ...CPU-option-reporting-to-proc-cpuinfo.patch | 140 + .../310-arm_module_unresolved_weak_sym.patch | 22 + ...t-command-line-parameters-from-users.patch | 281 + .../332-arc-add-OWRTDTB-section.patch | 84 + ...able-unaligned-access-in-kernel-mode.patch | 24 + ...ernel-XZ-compression-option-on-PPC_8.patch | 25 + .../400-mtd-mtdsplit-support.patch | 313 + ...support-for-minor-aligned-partitions.patch | 389 + ...ers-ofpart-fix-parsing-subpartitions.patch | 76 + ...t-add-of_match_table-with-DT-binding.patch | 22 + .../pending-5.15/420-mtd-redboot_space.patch | 41 + ...30-mtd-add-myloader-partition-parser.patch | 229 + ...check-for-bad-blocks-when-calculatin.patch | 68 + ...bcm47xxpart-detect-T_Meter-partition.patch | 37 + ...mtd-add-routerbootpart-parser-config.patch | 38 + ...mtd-cfi_cmdset_0002-no-erase_suspend.patch | 25 + ...et_0002-add-buffer-write-cmd-timeout.patch | 17 + ...25p80-mx-disable-software-protection.patch | 18 + ...ort-limiting-4K-sectors-support-base.patch | 71 + .../476-mtd-spi-nor-add-eon-en25q128.patch | 18 + .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 79 + ...r-add-support-for-Gigadevice-GD25D05.patch | 22 + .../483-mtd-spi-nor-add-gd25q512.patch | 12 + ...spinand-add-support-for-xtx-xt26g0xa.patch | 178 + .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 11 + .../485-mtd-spi-nor-add-xmc-xm25qh128c.patch | 11 + ...mtd-device-named-ubi-or-data-on-boot.patch | 97 + ...to-create-ubiblock-device-for-rootfs.patch | 69 + ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 53 + ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 34 + .../494-mtd-ubi-add-EOF-marker-support.patch | 60 + ...-mtd-core-add-get_mtd_device_by_node.patch | 75 + ...-add-bindings-for-mtd-concat-devices.patch | 52 + ...cat-add-dt-driver-for-concat-devices.patch | 216 + ...i-nor-locking-support-for-MX25L6405D.patch | 34 + ...i-nor-disable-16-bit-sr-for-macronix.patch | 30 + .../500-fs_cdrom_dependencies.patch | 40 + .../530-jffs2_make_lzma_available.patch | 5180 ++++++++++++ .../pending-5.15/532-jffs2_eofdetect.patch | 65 + .../600-netfilter_conntrack_flush.patch | 88 + ...etfilter_match_bypass_default_checks.patch | 110 + ...netfilter_match_bypass_default_table.patch | 106 + ...netfilter_match_reduce_memory_access.patch | 22 + ...-netfilter_optional_tcp_window_check.patch | 73 + ...del-do-not-defer-queue-length-update.patch | 86 + .../pending-5.15/630-packet_socket_type.patch | 138 + .../pending-5.15/655-increase_skb_pad.patch | 20 + ...Add-support-for-MAP-E-FMRs-mesh-mode.patch | 511 ++ ...ng-with-source-address-failed-policy.patch | 263 + ...nes-for-_POLICY_FAILED-until-all-cod.patch | 50 + ...T-skip-GRO-for-foreign-MAC-addresses.patch | 149 + ...et-add-mac-address-increment-support.patch | 89 + ...83-of_net-add-mac-address-to-of-tree.patch | 38 + ..._eth_soc-avoid-creating-duplicate-of.patch | 26 + ...soc-add-ipv6-flow-offloading-support.patch | 65 + ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 41 + ...detach-callback-to-struct-phy_driver.patch | 38 + ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 177 + ...net-phy-at803x-fix-feature-detection.patch | 66 + ...760-net-dsa-mv88e6xxx-fix-vlan-setup.patch | 27 + ...hdev-Refactor-br_switchdev_fdb_notif.patch | 77 + ...hdev-Include-local-flag-in-FDB-notif.patch | 42 + ...hdev-Send-FDB-notifications-for-host.patch | 96 + ...local-addresses-in-assisted-CPU-port.patch | 36 + ...bridge-addresses-in-assisted-CPU-por.patch | 30 + ...tic-FDB-entries-on-foreign-interface.patch | 56 + ...equest-assisted-learning-on-CPU-port.patch | 27 + ...-missing-linux-if_ether.h-for-ETH_AL.patch | 61 + ...ice-struct-copy-its-DMA-params-to-th.patch | 64 + ...pio-cascade-add-generic-GPIO-cascade.patch | 222 + .../810-pci_disable_common_quirks.patch | 62 + .../811-pci_disable_usb_common_quirks.patch | 115 + ...problem-with-platfom-data-in-w1-gpio.patch | 26 + .../pending-5.15/834-ledtrig-libata.patch | 149 + ...40-hwrng-bcm2835-set-quality-to-1000.patch | 26 + ..._wwan-add-ZTE-MF286D-modem-19d2-1485.patch | 59 + ...lace-custom-PCIE_CORE_INT_-macros-wi.patch | 40 + ...ark-Fix-reading-MSI-interrupt-number.patch | 57 + ...dvark-Fix-support-for-MSI-interrupts.patch | 72 + ...rite-IRQ-code-to-chained-IRQ-handler.patch | 125 + ...ck-return-value-of-generic_handle_do.patch | 31 + ...e-MSI-irq_chip-structures-static-dri.patch | 93 + ...e-msi_domain_info-structure-a-static.patch | 64 + ...-dev_fwnode-instead-of-of_node_to_fw.patch | 40 + ...actor-unmasking-summary-MSI-interrup.patch | 44 + ...d-support-for-masking-MSI-interrupts.patch | 117 + ...PCI-aardvark-Fix-setting-MSI-address.patch | 91 + ...12-PCI-aardvark-Enable-MSI-X-support.patch | 38 + ...-support-for-ERR-interrupt-on-emulat.patch | 100 + ...-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch | 44 + ...imize-writing-PCI_EXP_RTCTL_PMEIE-an.patch | 52 + ...dvark-Add-support-for-PME-interrupts.patch | 47 + ...-support-for-PME-requester-on-emulat.patch | 173 + ...-separate-INTA-interrupt-for-emulate.patch | 161 + ...ove-irq_mask_ack-callback-for-INTx-i.patch | 29 + ...aardvark-Don-t-mask-irq-when-mapping.patch | 27 + ...p-__maybe_unused-from-advk_pcie_disa.patch | 28 + ...ate-comment-about-link-going-down-af.patch | 35 + ...e-main-irq_chip-structure-a-static-d.patch | 102 + ...mvebu-a3700-comphy-Remove-port-from-.patch | 217 + ...mvebu-a3700-comphy-Add-native-kernel.patch | 1564 ++++ ...l-armada-37xx-Add-xtal-clock-to-comp.patch | 31 + ...mvebu-Make-SATA-PHY-optional-for-Arm.patch | 61 + ...xhci-mvebu-make-USB-3.0-PHY-optional.patch | 163 + ...ark-Fix-initialization-with-old-Marv.patch | 36 + .../pending-5.15/920-mangle_bootargs.patch | 71 + 441 files changed, 71106 insertions(+) create mode 100644 target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch create mode 100644 target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch create mode 100644 target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch create mode 100644 target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch create mode 100644 target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch create mode 100644 target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch create mode 100644 target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch create mode 100644 target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch create mode 100644 target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch create mode 100644 target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch create mode 100644 target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch create mode 100644 target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch create mode 100644 target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch create mode 100644 target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch create mode 100644 target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch create mode 100644 target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch create mode 100644 target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch create mode 100644 target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch create mode 100644 target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch create mode 100644 target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch create mode 100644 target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch create mode 100644 target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch create mode 100644 target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch create mode 100644 target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch create mode 100644 target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch create mode 100644 target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch create mode 100644 target/linux/generic/backport-5.15/410-mtd-next-mtd-parsers-trx-allow-to-use-on-MediaTek-MIPS-SoCs.patch create mode 100644 target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch create mode 100644 target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch create mode 100644 target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch create mode 100644 target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch create mode 100644 target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch create mode 100644 target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch create mode 100644 target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch create mode 100644 target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch create mode 100644 target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch create mode 100644 target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch create mode 100644 target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch create mode 100644 target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch create mode 100644 target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch create mode 100644 target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch create mode 100644 target/linux/generic/backport-5.15/719-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch create mode 100644 target/linux/generic/backport-5.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch create mode 100644 target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch create mode 100644 target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch create mode 100644 target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch create mode 100644 target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch create mode 100644 target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch create mode 100644 target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch create mode 100644 target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch create mode 100644 target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch create mode 100644 target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch create mode 100644 target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch create mode 100644 target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch create mode 100644 target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch create mode 100644 target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch create mode 100644 target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch create mode 100644 target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch create mode 100644 target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch create mode 100644 target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch create mode 100644 target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch create mode 100644 target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch create mode 100644 target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch create mode 100644 target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch create mode 100644 target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch create mode 100644 target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch create mode 100644 target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch create mode 100644 target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch create mode 100644 target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch create mode 100644 target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch create mode 100644 target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch create mode 100644 target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch create mode 100644 target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch create mode 100644 target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch create mode 100644 target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch create mode 100644 target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch create mode 100644 target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch create mode 100644 target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch create mode 100644 target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch create mode 100644 target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch create mode 100644 target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch create mode 100644 target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch create mode 100644 target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch create mode 100644 target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch create mode 100644 target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch create mode 100644 target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch create mode 100644 target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch create mode 100644 target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch create mode 100644 target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch create mode 100644 target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch create mode 100644 target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch create mode 100644 target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch create mode 100644 target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch create mode 100644 target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch create mode 100644 target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch create mode 100644 target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch create mode 100644 target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch create mode 100644 target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch create mode 100644 target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch create mode 100644 target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch create mode 100644 target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch create mode 100644 target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch create mode 100644 target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch create mode 100644 target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch create mode 100644 target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch create mode 100644 target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch create mode 100644 target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch create mode 100644 target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch create mode 100644 target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch create mode 100644 target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch create mode 100644 target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch create mode 100644 target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch create mode 100644 target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch create mode 100644 target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch create mode 100644 target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch create mode 100644 target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch create mode 100644 target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch create mode 100644 target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch create mode 100644 target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch create mode 100644 target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch create mode 100644 target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch create mode 100644 target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch create mode 100644 target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch create mode 100644 target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch create mode 100644 target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch create mode 100644 target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch create mode 100644 target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch create mode 100644 target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch create mode 100644 target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch create mode 100644 target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch create mode 100644 target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch create mode 100644 target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch create mode 100644 target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch create mode 100644 target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch create mode 100644 target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch create mode 100644 target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch create mode 100644 target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch create mode 100644 target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0001-PCI-pci-bridge-emul-Add-description-for-class_revisi.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0002-PCI-pci-bridge-emul-Add-definitions-for-missing-capa.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch create mode 100644 target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch create mode 100644 target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch create mode 100644 target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch create mode 100644 target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch create mode 100644 target/linux/generic/backport-5.15/870-hwmon-next-hwmon-lm70-Add-ti-tmp125-support.patch create mode 100644 target/linux/generic/config-5.15 create mode 100644 target/linux/generic/hack-5.15/204-module_strip.patch create mode 100644 target/linux/generic/hack-5.15/205-kconfig-exit.patch create mode 100644 target/linux/generic/hack-5.15/210-darwin_scripts_include.patch create mode 100644 target/linux/generic/hack-5.15/211-darwin-uuid-typedef-clash.patch create mode 100644 target/linux/generic/hack-5.15/212-tools_portability.patch create mode 100644 target/linux/generic/hack-5.15/214-spidev_h_portability.patch create mode 100644 target/linux/generic/hack-5.15/220-arm-gc_sections.patch create mode 100644 target/linux/generic/hack-5.15/221-module_exports.patch create mode 100644 target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch create mode 100644 target/linux/generic/hack-5.15/249-udp-tunnel-selection.patch create mode 100644 target/linux/generic/hack-5.15/250-netfilter_depends.patch create mode 100644 target/linux/generic/hack-5.15/251-kconfig.patch create mode 100644 target/linux/generic/hack-5.15/252-SATA_PMP.patch create mode 100644 target/linux/generic/hack-5.15/253-ksmbd-config.patch create mode 100644 target/linux/generic/hack-5.15/259-regmap_dynamic.patch create mode 100644 target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch create mode 100644 target/linux/generic/hack-5.15/261-lib-arc4-unhide.patch create mode 100644 target/linux/generic/hack-5.15/280-rfkill-stubs.patch create mode 100644 target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch create mode 100644 target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch create mode 100644 target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch create mode 100644 target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch create mode 100644 target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch create mode 100644 target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch create mode 100644 target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch create mode 100644 target/linux/generic/hack-5.15/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch create mode 100644 target/linux/generic/hack-5.15/430-mtk-bmt-support.patch create mode 100644 target/linux/generic/hack-5.15/531-debloat_lzma.patch create mode 100644 target/linux/generic/hack-5.15/600-bridge_offload.patch create mode 100644 target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch create mode 100644 target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch create mode 100644 target/linux/generic/hack-5.15/651-wireless_mesh_header.patch create mode 100644 target/linux/generic/hack-5.15/660-fq_codel_defaults.patch create mode 100644 target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch create mode 100644 target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch create mode 100644 target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch create mode 100644 target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch create mode 100644 target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch create mode 100644 target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch create mode 100644 target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch create mode 100644 target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch create mode 100644 target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch create mode 100644 target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch create mode 100644 target/linux/generic/hack-5.15/761-dt-bindings-net-add-RTL8152-binding-documentation.patch create mode 100644 target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch create mode 100644 target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch create mode 100644 target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch create mode 100644 target/linux/generic/hack-5.15/901-debloat_sock_diag.patch create mode 100644 target/linux/generic/hack-5.15/902-debloat_proc.patch create mode 100644 target/linux/generic/hack-5.15/904-debloat_dma_buf.patch create mode 100644 target/linux/generic/hack-5.15/910-kobject_uevent.patch create mode 100644 target/linux/generic/hack-5.15/911-kobject_add_broadcast_uevent.patch create mode 100644 target/linux/generic/hack-5.15/920-device_tree_cmdline.patch create mode 100644 target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch create mode 100644 target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch create mode 100644 target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch create mode 100644 target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch create mode 100644 target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch create mode 100644 target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch create mode 100644 target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch create mode 100644 target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch create mode 100644 target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch create mode 100644 target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch create mode 100644 target/linux/generic/pending-5.15/190-rtc-rs5c372-support_alarms_up_to_1_week.patch create mode 100644 target/linux/generic/pending-5.15/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch create mode 100644 target/linux/generic/pending-5.15/201-extra_optimization.patch create mode 100644 target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch create mode 100644 target/linux/generic/pending-5.15/205-backtrace_module_info.patch create mode 100644 target/linux/generic/pending-5.15/240-remove-unsane-filenames-from-deps_initramfs-list.patch create mode 100644 target/linux/generic/pending-5.15/261-enable_wilink_platform_without_drivers.patch create mode 100644 target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch create mode 100644 target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch create mode 100644 target/linux/generic/pending-5.15/302-mips_no_branch_likely.patch create mode 100644 target/linux/generic/pending-5.15/305-mips_module_reloc.patch create mode 100644 target/linux/generic/pending-5.15/307-mips_highmem_offset.patch create mode 100644 target/linux/generic/pending-5.15/308-mips32r2_tune.patch create mode 100644 target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch create mode 100644 target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch create mode 100644 target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch create mode 100644 target/linux/generic/pending-5.15/332-arc-add-OWRTDTB-section.patch create mode 100644 target/linux/generic/pending-5.15/333-arc-enable-unaligned-access-in-kernel-mode.patch create mode 100644 target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch create mode 100644 target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch create mode 100644 target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch create mode 100644 target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch create mode 100644 target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch create mode 100644 target/linux/generic/pending-5.15/420-mtd-redboot_space.patch create mode 100644 target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch create mode 100644 target/linux/generic/pending-5.15/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch create mode 100644 target/linux/generic/pending-5.15/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch create mode 100644 target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch create mode 100644 target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch create mode 100644 target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch create mode 100644 target/linux/generic/pending-5.15/465-m25p80-mx-disable-software-protection.patch create mode 100644 target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch create mode 100644 target/linux/generic/pending-5.15/476-mtd-spi-nor-add-eon-en25q128.patch create mode 100644 target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch create mode 100644 target/linux/generic/pending-5.15/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch create mode 100644 target/linux/generic/pending-5.15/483-mtd-spi-nor-add-gd25q512.patch create mode 100644 target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch create mode 100644 target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch create mode 100644 target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch create mode 100644 target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch create mode 100644 target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch create mode 100644 target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch create mode 100644 target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch create mode 100644 target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch create mode 100644 target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch create mode 100644 target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch create mode 100644 target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch create mode 100644 target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch create mode 100644 target/linux/generic/pending-5.15/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch create mode 100644 target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch create mode 100644 target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch create mode 100644 target/linux/generic/pending-5.15/532-jffs2_eofdetect.patch create mode 100644 target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch create mode 100644 target/linux/generic/pending-5.15/610-netfilter_match_bypass_default_checks.patch create mode 100644 target/linux/generic/pending-5.15/611-netfilter_match_bypass_default_table.patch create mode 100644 target/linux/generic/pending-5.15/612-netfilter_match_reduce_memory_access.patch create mode 100644 target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch create mode 100644 target/linux/generic/pending-5.15/620-net_sched-codel-do-not-defer-queue-length-update.patch create mode 100644 target/linux/generic/pending-5.15/630-packet_socket_type.patch create mode 100644 target/linux/generic/pending-5.15/655-increase_skb_pad.patch create mode 100644 target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch create mode 100644 target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch create mode 100644 target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch create mode 100644 target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch create mode 100644 target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch create mode 100644 target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch create mode 100644 target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch create mode 100644 target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch create mode 100644 target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch create mode 100644 target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch create mode 100644 target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch create mode 100644 target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch create mode 100644 target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch create mode 100644 target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch create mode 100644 target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch create mode 100644 target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch create mode 100644 target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch create mode 100644 target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch create mode 100644 target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch create mode 100644 target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch create mode 100644 target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch create mode 100644 target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch create mode 100644 target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch create mode 100644 target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch create mode 100644 target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch create mode 100644 target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch create mode 100644 target/linux/generic/pending-5.15/834-ledtrig-libata.patch create mode 100644 target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch create mode 100644 target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch create mode 100644 target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch create mode 100644 target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch create mode 100644 target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch create mode 100644 target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch create mode 100644 target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch create mode 100644 target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch create mode 100644 target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch create mode 100644 target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch create mode 100644 target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch create mode 100644 target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch create mode 100644 target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch create mode 100644 target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch create mode 100644 target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch create mode 100644 target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch create mode 100644 target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch create mode 100644 target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch create mode 100644 target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch create mode 100644 target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch create mode 100644 target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch create mode 100644 target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch create mode 100644 target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch create mode 100644 target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch create mode 100644 target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch create mode 100644 target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch create mode 100644 target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch create mode 100644 target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch create mode 100644 target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch create mode 100644 target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch create mode 100644 target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch create mode 100644 target/linux/generic/pending-5.15/920-mangle_bootargs.patch diff --git a/target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch b/target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch new file mode 100644 index 0000000000..7ac4f9d240 --- /dev/null +++ b/target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch @@ -0,0 +1,30 @@ +From 13b1ecc3401653a355798eb1dee10cc1608202f4 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 18 Jan 2016 12:27:49 +0100 +Subject: [PATCH 33/34] Kbuild: don't hardcode path to awk in + scripts/ld-version.sh + +On some systems /usr/bin/awk does not exist, or is broken. Find it via +$PATH instead. + +Signed-off-by: Felix Fietkau +--- + scripts/ld-version.sh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/scripts/ld-version.sh ++++ b/scripts/ld-version.sh +@@ -1,6 +1,7 @@ +-#!/usr/bin/awk -f ++#!/bin/sh + # SPDX-License-Identifier: GPL-2.0 + # extract linker version number from stdin and turn into single number ++exec awk ' + { + gsub(".*\\)", ""); + gsub(".*version ", ""); +@@ -9,3 +10,4 @@ + print a[1]*100000000 + a[2]*1000000 + a[3]*10000; + exit + } ++' diff --git a/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch b/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch new file mode 100644 index 0000000000..bb99e4ddbf --- /dev/null +++ b/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch @@ -0,0 +1,21 @@ +From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 9 Jul 2017 00:26:53 +0200 +Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86 + +Signed-off-by: Felix Fietkau +--- + Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -507,7 +507,7 @@ KBUILD_LDFLAGS_MODULE := + KBUILD_LDFLAGS := + CLANG_FLAGS := + +-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC ++export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC + export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL + export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX + export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD diff --git a/target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch b/target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch new file mode 100644 index 0000000000..66e75bf514 --- /dev/null +++ b/target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch @@ -0,0 +1,27 @@ +From 1027a42c25cbf8cfc4ade6503c5110aae04866af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez=20Cabanelas?= +Date: Fri, 16 Oct 2020 20:22:37 +0200 +Subject: [PATCH] power: reset: linkstation-poweroff: add missing put_device() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The of_mdio_find_bus() takes a reference to the underlying device +structure, we should release that reference using a put_device() call. + +Signed-off-by: Daniel González Cabanelas +Signed-off-by: Sebastian Reichel +--- + drivers/power/reset/linkstation-poweroff.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/power/reset/linkstation-poweroff.c ++++ b/drivers/power/reset/linkstation-poweroff.c +@@ -113,6 +113,7 @@ static int __init linkstation_poweroff_i + return -EPROBE_DEFER; + + phydev = phy_find_first(bus); ++ put_device(&bus->dev); + if (!phydev) + return -EPROBE_DEFER; + diff --git a/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch b/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch new file mode 100644 index 0000000000..82feb7421d --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-00-MIPS-uasm-Enable-muhu-opcode-for-MIPS-R6.patch @@ -0,0 +1,65 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:02 +0200 +Subject: [PATCH] MIPS: uasm: Enable muhu opcode for MIPS R6 + +Enable the 'muhu' instruction, complementing the existing 'mulu', needed +to implement a MIPS32 BPF JIT. + +Also fix a typo in the existing definition of 'dmulu'. + +Signed-off-by: Tony Ambardar + +This patch is a dependency for my 32-bit MIPS eBPF JIT. + +Signed-off-by: Johan Almbladh +--- + +--- a/arch/mips/include/asm/uasm.h ++++ b/arch/mips/include/asm/uasm.h +@@ -145,6 +145,7 @@ Ip_u1(_mtlo); + Ip_u3u1u2(_mul); + Ip_u1u2(_multu); + Ip_u3u1u2(_mulu); ++Ip_u3u1u2(_muhu); + Ip_u3u1u2(_nor); + Ip_u3u1u2(_or); + Ip_u2u1u3(_ori); +--- a/arch/mips/mm/uasm-mips.c ++++ b/arch/mips/mm/uasm-mips.c +@@ -90,7 +90,7 @@ static const struct insn insn_table[insn + RS | RT | RD}, + [insn_dmtc0] = {M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, + [insn_dmultu] = {M(spec_op, 0, 0, 0, 0, dmultu_op), RS | RT}, +- [insn_dmulu] = {M(spec_op, 0, 0, 0, dmult_dmul_op, dmultu_op), ++ [insn_dmulu] = {M(spec_op, 0, 0, 0, dmultu_dmulu_op, dmultu_op), + RS | RT | RD}, + [insn_drotr] = {M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE}, + [insn_drotr32] = {M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE}, +@@ -150,6 +150,8 @@ static const struct insn insn_table[insn + [insn_mtlo] = {M(spec_op, 0, 0, 0, 0, mtlo_op), RS}, + [insn_mulu] = {M(spec_op, 0, 0, 0, multu_mulu_op, multu_op), + RS | RT | RD}, ++ [insn_muhu] = {M(spec_op, 0, 0, 0, multu_muhu_op, multu_op), ++ RS | RT | RD}, + #ifndef CONFIG_CPU_MIPSR6 + [insn_mul] = {M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD}, + #else +--- a/arch/mips/mm/uasm.c ++++ b/arch/mips/mm/uasm.c +@@ -59,7 +59,7 @@ enum opcode { + insn_lddir, insn_ldpte, insn_ldx, insn_lh, insn_lhu, insn_ll, insn_lld, + insn_lui, insn_lw, insn_lwu, insn_lwx, insn_mfc0, insn_mfhc0, insn_mfhi, + insn_mflo, insn_modu, insn_movn, insn_movz, insn_mtc0, insn_mthc0, +- insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_nor, ++ insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_muhu, insn_nor, + insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, insn_sc, + insn_scd, insn_seleqz, insn_selnez, insn_sd, insn_sh, insn_sll, + insn_sllv, insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra, +@@ -344,6 +344,7 @@ I_u1(_mtlo) + I_u3u1u2(_mul) + I_u1u2(_multu) + I_u3u1u2(_mulu) ++I_u3u1u2(_muhu) + I_u3u1u2(_nor) + I_u3u1u2(_or) + I_u2u1u3(_ori) diff --git a/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch b/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch new file mode 100644 index 0000000000..3a4d573f80 --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-01-mips-uasm-Add-workaround-for-Loongson-2F-nop-CPU-err.patch @@ -0,0 +1,31 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:03 +0200 +Subject: [PATCH] mips: uasm: Add workaround for Loongson-2F nop CPU errata + +This patch implements a workaround for the Loongson-2F nop in generated, +code, if the existing option CONFIG_CPU_NOP_WORKAROUND is set. Before, +the binutils option -mfix-loongson2f-nop was enabled, but no workaround +was done when emitting MIPS code. Now, the nop pseudo instruction is +emitted as "or ax,ax,zero" instead of the default "sll zero,zero,0". This +is consistent with the workaround implemented by binutils. + +Link: https://sourceware.org/legacy-ml/binutils/2009-11/msg00387.html + +Signed-off-by: Johan Almbladh +Reviewed-by: Jiaxun Yang +--- + +--- a/arch/mips/include/asm/uasm.h ++++ b/arch/mips/include/asm/uasm.h +@@ -249,7 +249,11 @@ static inline void uasm_l##lb(struct uas + #define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off) + #define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3) + #define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b) ++#ifdef CONFIG_CPU_NOP_WORKAROUNDS ++#define uasm_i_nop(buf) uasm_i_or(buf, 1, 1, 0) ++#else + #define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0) ++#endif + #define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1) + + static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, diff --git a/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch b/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch new file mode 100644 index 0000000000..7980659961 --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-02-mips-bpf-Add-eBPF-JIT-for-32-bit-MIPS.patch @@ -0,0 +1,3078 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:04 +0200 +Subject: [PATCH] mips: bpf: Add eBPF JIT for 32-bit MIPS + +This is an implementation of an eBPF JIT for 32-bit MIPS I-V and MIPS32. +The implementation supports all 32-bit and 64-bit ALU and JMP operations, +including the recently-added atomics. 64-bit div/mod and 64-bit atomics +are implemented using function calls to math64 and atomic64 functions, +respectively. All 32-bit operations are implemented natively by the JIT, +except if the CPU lacks ll/sc instructions. + +Register mapping +================ +All 64-bit eBPF registers are mapped to native 32-bit MIPS register pairs, +and does not use any stack scratch space for register swapping. This means +that all eBPF register data is kept in CPU registers all the time, and +this simplifies the register management a lot. It also reduces the JIT's +pressure on temporary registers since we do not have to move data around. + +Native register pairs are ordered according to CPU endiannes, following +the O32 calling convention for passing 64-bit arguments and return values. +The eBPF return value, arguments and callee-saved registers are mapped to +their native MIPS equivalents. + +Since the 32 highest bits in the eBPF FP (frame pointer) register are +always zero, only one general-purpose register is actually needed for the +mapping. The MIPS fp register is used for this purpose. The high bits are +mapped to MIPS register r0. This saves us one CPU register, which is much +needed for temporaries, while still allowing us to treat the R10 (FP) +register just like any other eBPF register in the JIT. + +The MIPS gp (global pointer) and at (assembler temporary) registers are +used as internal temporary registers for constant blinding. CPU registers +t6-t9 are used internally by the JIT when constructing more complex 64-bit +operations. This is precisely what is needed - two registers to store an +operand value, and two more as scratch registers when performing the +operation. + +The register mapping is shown below. + + R0 - $v1, $v0 return value + R1 - $a1, $a0 argument 1, passed in registers + R2 - $a3, $a2 argument 2, passed in registers + R3 - $t1, $t0 argument 3, passed on stack + R4 - $t3, $t2 argument 4, passed on stack + R5 - $t4, $t3 argument 5, passed on stack + R6 - $s1, $s0 callee-saved + R7 - $s3, $s2 callee-saved + R8 - $s5, $s4 callee-saved + R9 - $s7, $s6 callee-saved + FP - $r0, $fp 32-bit frame pointer + AX - $gp, $at constant-blinding + $t6 - $t9 unallocated, JIT temporaries + +Jump offsets +============ +The JIT tries to map all conditional JMP operations to MIPS conditional +PC-relative branches. The MIPS branch offset field is 18 bits, in bytes, +which is equivalent to the eBPF 16-bit instruction offset. However, since +the JIT may emit more than one CPU instruction per eBPF instruction, the +field width may overflow. If that happens, the JIT converts the long +conditional jump to a short PC-relative branch with the condition +inverted, jumping over a long unconditional absolute jmp (j). + +This conversion will change the instruction offset mapping used for jumps, +and may in turn result in more branch offset overflows. The JIT therefore +dry-runs the translation until no more branches are converted and the +offsets do not change anymore. There is an upper bound on this of course, +and if the JIT hits that limit, the last two iterations are run with all +branches being converted. + +Tail call count +=============== +The current tail call count is stored in the 16-byte area of the caller's +stack frame that is reserved for the callee in the o32 ABI. The value is +initialized in the prologue, and propagated to the tail-callee by skipping +the initialization instructions when emitting the tail call. + +Signed-off-by: Johan Almbladh +--- + create mode 100644 arch/mips/net/bpf_jit_comp.c + create mode 100644 arch/mips/net/bpf_jit_comp.h + create mode 100644 arch/mips/net/bpf_jit_comp32.c + +--- a/arch/mips/net/Makefile ++++ b/arch/mips/net/Makefile +@@ -2,4 +2,9 @@ + # MIPS networking code + + obj-$(CONFIG_MIPS_CBPF_JIT) += bpf_jit.o bpf_jit_asm.o +-obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o ++ ++ifeq ($(CONFIG_32BIT),y) ++ obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp.o bpf_jit_comp32.o ++else ++ obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o ++endif +--- /dev/null ++++ b/arch/mips/net/bpf_jit_comp.c +@@ -0,0 +1,1020 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Just-In-Time compiler for eBPF bytecode on MIPS. ++ * Implementation of JIT functions common to 32-bit and 64-bit CPUs. ++ * ++ * Copyright (c) 2021 Anyfi Networks AB. ++ * Author: Johan Almbladh ++ * ++ * Based on code and ideas from ++ * Copyright (c) 2017 Cavium, Inc. ++ * Copyright (c) 2017 Shubham Bansal ++ * Copyright (c) 2011 Mircea Gherzan ++ */ ++ ++/* ++ * Code overview ++ * ============= ++ * ++ * - bpf_jit_comp.h ++ * Common definitions and utilities. ++ * ++ * - bpf_jit_comp.c ++ * Implementation of JIT top-level logic and exported JIT API functions. ++ * Implementation of internal operations shared by 32-bit and 64-bit code. ++ * JMP and ALU JIT control code, register control code, shared ALU and ++ * JMP/JMP32 JIT operations. ++ * ++ * - bpf_jit_comp32.c ++ * Implementation of functions to JIT prologue, epilogue and a single eBPF ++ * instruction for 32-bit MIPS CPUs. The functions use shared operations ++ * where possible, and implement the rest for 32-bit MIPS such as ALU64 ++ * operations. ++ * ++ * - bpf_jit_comp64.c ++ * Ditto, for 64-bit MIPS CPUs. ++ * ++ * Zero and sign extension ++ * ======================== ++ * 32-bit MIPS instructions on 64-bit MIPS registers use sign extension, ++ * but the eBPF instruction set mandates zero extension. We let the verifier ++ * insert explicit zero-extensions after 32-bit ALU operations, both for ++ * 32-bit and 64-bit MIPS JITs. Conditional JMP32 operations on 64-bit MIPs ++ * are JITed with sign extensions inserted when so expected. ++ * ++ * ALU operations ++ * ============== ++ * ALU operations on 32/64-bit MIPS and ALU64 operations on 64-bit MIPS are ++ * JITed in the following steps. ALU64 operations on 32-bit MIPS are more ++ * complicated and therefore only processed by special implementations in ++ * step (3). ++ * ++ * 1) valid_alu_i: ++ * Determine if an immediate operation can be emitted as such, or if ++ * we must fall back to the register version. ++ * ++ * 2) rewrite_alu_i: ++ * Convert BPF operation and immediate value to a canonical form for ++ * JITing. In some degenerate cases this form may be a no-op. ++ * ++ * 3) emit_alu_{i,i64,r,64}: ++ * Emit instructions for an ALU or ALU64 immediate or register operation. ++ * ++ * JMP operations ++ * ============== ++ * JMP and JMP32 operations require an JIT instruction offset table for ++ * translating the jump offset. This table is computed by dry-running the ++ * JIT without actually emitting anything. However, the computed PC-relative ++ * offset may overflow the 18-bit offset field width of the native MIPS ++ * branch instruction. In such cases, the long jump is converted into the ++ * following sequence. ++ * ++ * ! +2 Inverted PC-relative branch ++ * nop Delay slot ++ * j Unconditional absolute long jump ++ * nop Delay slot ++ * ++ * Since this converted sequence alters the offset table, all offsets must ++ * be re-calculated. This may in turn trigger new branch conversions, so ++ * the process is repeated until no further changes are made. Normally it ++ * completes in 1-2 iterations. If JIT_MAX_ITERATIONS should reached, we ++ * fall back to converting every remaining jump operation. The branch ++ * conversion is independent of how the JMP or JMP32 condition is JITed. ++ * ++ * JMP32 and JMP operations are JITed as follows. ++ * ++ * 1) setup_jmp_{i,r}: ++ * Convert jump conditional and offset into a form that can be JITed. ++ * This form may be a no-op, a canonical form, or an inverted PC-relative ++ * jump if branch conversion is necessary. ++ * ++ * 2) valid_jmp_i: ++ * Determine if an immediate operations can be emitted as such, or if ++ * we must fall back to the register version. Applies to JMP32 for 32-bit ++ * MIPS, and both JMP and JMP32 for 64-bit MIPS. ++ * ++ * 3) emit_jmp_{i,i64,r,r64}: ++ * Emit instructions for an JMP or JMP32 immediate or register operation. ++ * ++ * 4) finish_jmp_{i,r}: ++ * Emit any instructions needed to finish the jump. This includes a nop ++ * for the delay slot if a branch was emitted, and a long absolute jump ++ * if the branch was converted. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bpf_jit_comp.h" ++ ++/* Convenience macros for descriptor access */ ++#define CONVERTED(desc) ((desc) & JIT_DESC_CONVERT) ++#define INDEX(desc) ((desc) & ~JIT_DESC_CONVERT) ++ ++/* ++ * Push registers on the stack, starting at a given depth from the stack ++ * pointer and increasing. The next depth to be written is returned. ++ */ ++int push_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth) ++{ ++ int reg; ++ ++ for (reg = 0; reg < BITS_PER_BYTE * sizeof(mask); reg++) ++ if (mask & BIT(reg)) { ++ if ((excl & BIT(reg)) == 0) { ++ if (sizeof(long) == 4) ++ emit(ctx, sw, reg, depth, MIPS_R_SP); ++ else /* sizeof(long) == 8 */ ++ emit(ctx, sd, reg, depth, MIPS_R_SP); ++ } ++ depth += sizeof(long); ++ } ++ ++ ctx->stack_used = max((int)ctx->stack_used, depth); ++ return depth; ++} ++ ++/* ++ * Pop registers from the stack, starting at a given depth from the stack ++ * pointer and increasing. The next depth to be read is returned. ++ */ ++int pop_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth) ++{ ++ int reg; ++ ++ for (reg = 0; reg < BITS_PER_BYTE * sizeof(mask); reg++) ++ if (mask & BIT(reg)) { ++ if ((excl & BIT(reg)) == 0) { ++ if (sizeof(long) == 4) ++ emit(ctx, lw, reg, depth, MIPS_R_SP); ++ else /* sizeof(long) == 8 */ ++ emit(ctx, ld, reg, depth, MIPS_R_SP); ++ } ++ depth += sizeof(long); ++ } ++ ++ return depth; ++} ++ ++/* Compute the 28-bit jump target address from a BPF program location */ ++int get_target(struct jit_context *ctx, u32 loc) ++{ ++ u32 index = INDEX(ctx->descriptors[loc]); ++ unsigned long pc = (unsigned long)&ctx->target[ctx->jit_index]; ++ unsigned long addr = (unsigned long)&ctx->target[index]; ++ ++ if (!ctx->target) ++ return 0; ++ ++ if ((addr ^ pc) & ~MIPS_JMP_MASK) ++ return -1; ++ ++ return addr & MIPS_JMP_MASK; ++} ++ ++/* Compute the PC-relative offset to relative BPF program offset */ ++int get_offset(const struct jit_context *ctx, int off) ++{ ++ return (INDEX(ctx->descriptors[ctx->bpf_index + off]) - ++ ctx->jit_index - 1) * sizeof(u32); ++} ++ ++/* dst = imm (register width) */ ++void emit_mov_i(struct jit_context *ctx, u8 dst, s32 imm) ++{ ++ if (imm >= -0x8000 && imm <= 0x7fff) { ++ emit(ctx, addiu, dst, MIPS_R_ZERO, imm); ++ } else { ++ emit(ctx, lui, dst, (s16)((u32)imm >> 16)); ++ emit(ctx, ori, dst, dst, (u16)(imm & 0xffff)); ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* dst = src (register width) */ ++void emit_mov_r(struct jit_context *ctx, u8 dst, u8 src) ++{ ++ emit(ctx, ori, dst, src, 0); ++ clobber_reg(ctx, dst); ++} ++ ++/* Validate ALU immediate range */ ++bool valid_alu_i(u8 op, s32 imm) ++{ ++ switch (BPF_OP(op)) { ++ case BPF_NEG: ++ case BPF_LSH: ++ case BPF_RSH: ++ case BPF_ARSH: ++ /* All legal eBPF values are valid */ ++ return true; ++ case BPF_ADD: ++ /* imm must be 16 bits */ ++ return imm >= -0x8000 && imm <= 0x7fff; ++ case BPF_SUB: ++ /* -imm must be 16 bits */ ++ return imm >= -0x7fff && imm <= 0x8000; ++ case BPF_AND: ++ case BPF_OR: ++ case BPF_XOR: ++ /* imm must be 16 bits unsigned */ ++ return imm >= 0 && imm <= 0xffff; ++ case BPF_MUL: ++ /* imm must be zero or a positive power of two */ ++ return imm == 0 || (imm > 0 && is_power_of_2(imm)); ++ case BPF_DIV: ++ case BPF_MOD: ++ /* imm must be an 17-bit power of two */ ++ return (u32)imm <= 0x10000 && is_power_of_2((u32)imm); ++ } ++ return false; ++} ++ ++/* Rewrite ALU immediate operation */ ++bool rewrite_alu_i(u8 op, s32 imm, u8 *alu, s32 *val) ++{ ++ bool act = true; ++ ++ switch (BPF_OP(op)) { ++ case BPF_LSH: ++ case BPF_RSH: ++ case BPF_ARSH: ++ case BPF_ADD: ++ case BPF_SUB: ++ case BPF_OR: ++ case BPF_XOR: ++ /* imm == 0 is a no-op */ ++ act = imm != 0; ++ break; ++ case BPF_MUL: ++ if (imm == 1) { ++ /* dst * 1 is a no-op */ ++ act = false; ++ } else if (imm == 0) { ++ /* dst * 0 is dst & 0 */ ++ op = BPF_AND; ++ } else { ++ /* dst * (1 << n) is dst << n */ ++ op = BPF_LSH; ++ imm = ilog2(abs(imm)); ++ } ++ break; ++ case BPF_DIV: ++ if (imm == 1) { ++ /* dst / 1 is a no-op */ ++ act = false; ++ } else { ++ /* dst / (1 << n) is dst >> n */ ++ op = BPF_RSH; ++ imm = ilog2(imm); ++ } ++ break; ++ case BPF_MOD: ++ /* dst % (1 << n) is dst & ((1 << n) - 1) */ ++ op = BPF_AND; ++ imm--; ++ break; ++ } ++ ++ *alu = op; ++ *val = imm; ++ return act; ++} ++ ++/* ALU immediate operation (32-bit) */ ++void emit_alu_i(struct jit_context *ctx, u8 dst, s32 imm, u8 op) ++{ ++ switch (BPF_OP(op)) { ++ /* dst = -dst */ ++ case BPF_NEG: ++ emit(ctx, subu, dst, MIPS_R_ZERO, dst); ++ break; ++ /* dst = dst & imm */ ++ case BPF_AND: ++ emit(ctx, andi, dst, dst, (u16)imm); ++ break; ++ /* dst = dst | imm */ ++ case BPF_OR: ++ emit(ctx, ori, dst, dst, (u16)imm); ++ break; ++ /* dst = dst ^ imm */ ++ case BPF_XOR: ++ emit(ctx, xori, dst, dst, (u16)imm); ++ break; ++ /* dst = dst << imm */ ++ case BPF_LSH: ++ emit(ctx, sll, dst, dst, imm); ++ break; ++ /* dst = dst >> imm */ ++ case BPF_RSH: ++ emit(ctx, srl, dst, dst, imm); ++ break; ++ /* dst = dst >> imm (arithmetic) */ ++ case BPF_ARSH: ++ emit(ctx, sra, dst, dst, imm); ++ break; ++ /* dst = dst + imm */ ++ case BPF_ADD: ++ emit(ctx, addiu, dst, dst, imm); ++ break; ++ /* dst = dst - imm */ ++ case BPF_SUB: ++ emit(ctx, addiu, dst, dst, -imm); ++ break; ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* ALU register operation (32-bit) */ ++void emit_alu_r(struct jit_context *ctx, u8 dst, u8 src, u8 op) ++{ ++ switch (BPF_OP(op)) { ++ /* dst = dst & src */ ++ case BPF_AND: ++ emit(ctx, and, dst, dst, src); ++ break; ++ /* dst = dst | src */ ++ case BPF_OR: ++ emit(ctx, or, dst, dst, src); ++ break; ++ /* dst = dst ^ src */ ++ case BPF_XOR: ++ emit(ctx, xor, dst, dst, src); ++ break; ++ /* dst = dst << src */ ++ case BPF_LSH: ++ emit(ctx, sllv, dst, dst, src); ++ break; ++ /* dst = dst >> src */ ++ case BPF_RSH: ++ emit(ctx, srlv, dst, dst, src); ++ break; ++ /* dst = dst >> src (arithmetic) */ ++ case BPF_ARSH: ++ emit(ctx, srav, dst, dst, src); ++ break; ++ /* dst = dst + src */ ++ case BPF_ADD: ++ emit(ctx, addu, dst, dst, src); ++ break; ++ /* dst = dst - src */ ++ case BPF_SUB: ++ emit(ctx, subu, dst, dst, src); ++ break; ++ /* dst = dst * src */ ++ case BPF_MUL: ++ if (cpu_has_mips32r1 || cpu_has_mips32r6) { ++ emit(ctx, mul, dst, dst, src); ++ } else { ++ emit(ctx, multu, dst, src); ++ emit(ctx, mflo, dst); ++ } ++ break; ++ /* dst = dst / src */ ++ case BPF_DIV: ++ if (cpu_has_mips32r6) { ++ emit(ctx, divu_r6, dst, dst, src); ++ } else { ++ emit(ctx, divu, dst, src); ++ emit(ctx, mflo, dst); ++ } ++ break; ++ /* dst = dst % src */ ++ case BPF_MOD: ++ if (cpu_has_mips32r6) { ++ emit(ctx, modu, dst, dst, src); ++ } else { ++ emit(ctx, divu, dst, src); ++ emit(ctx, mfhi, dst); ++ } ++ break; ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Atomic read-modify-write (32-bit) */ ++void emit_atomic_r(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 code) ++{ ++ emit(ctx, ll, MIPS_R_T9, off, dst); ++ switch (code) { ++ case BPF_ADD: ++ emit(ctx, addu, MIPS_R_T8, MIPS_R_T9, src); ++ break; ++ case BPF_AND: ++ emit(ctx, and, MIPS_R_T8, MIPS_R_T9, src); ++ break; ++ case BPF_OR: ++ emit(ctx, or, MIPS_R_T8, MIPS_R_T9, src); ++ break; ++ case BPF_XOR: ++ emit(ctx, xor, MIPS_R_T8, MIPS_R_T9, src); ++ break; ++ } ++ emit(ctx, sc, MIPS_R_T8, off, dst); ++ emit(ctx, beqz, MIPS_R_T8, -16); ++ emit(ctx, nop); /* Delay slot */ ++} ++ ++/* Atomic compare-and-exchange (32-bit) */ ++void emit_cmpxchg_r(struct jit_context *ctx, u8 dst, u8 src, u8 res, s16 off) ++{ ++ emit(ctx, ll, MIPS_R_T9, off, dst); ++ emit(ctx, bne, MIPS_R_T9, res, 12); ++ emit(ctx, move, MIPS_R_T8, src); /* Delay slot */ ++ emit(ctx, sc, MIPS_R_T8, off, dst); ++ emit(ctx, beqz, MIPS_R_T8, -20); ++ emit(ctx, move, res, MIPS_R_T9); /* Delay slot */ ++ clobber_reg(ctx, res); ++} ++ ++/* Swap bytes and truncate a register word or half word */ ++void emit_bswap_r(struct jit_context *ctx, u8 dst, u32 width) ++{ ++ u8 tmp = MIPS_R_T8; ++ u8 msk = MIPS_R_T9; ++ ++ switch (width) { ++ /* Swap bytes in a word */ ++ case 32: ++ if (cpu_has_mips32r2 || cpu_has_mips32r6) { ++ emit(ctx, wsbh, dst, dst); ++ emit(ctx, rotr, dst, dst, 16); ++ } else { ++ emit(ctx, sll, tmp, dst, 16); /* tmp = dst << 16 */ ++ emit(ctx, srl, dst, dst, 16); /* dst = dst >> 16 */ ++ emit(ctx, or, dst, dst, tmp); /* dst = dst | tmp */ ++ ++ emit(ctx, lui, msk, 0xff); /* msk = 0x00ff0000 */ ++ emit(ctx, ori, msk, msk, 0xff); /* msk = msk | 0xff */ ++ ++ emit(ctx, and, tmp, dst, msk); /* tmp = dst & msk */ ++ emit(ctx, sll, tmp, tmp, 8); /* tmp = tmp << 8 */ ++ emit(ctx, srl, dst, dst, 8); /* dst = dst >> 8 */ ++ emit(ctx, and, dst, dst, msk); /* dst = dst & msk */ ++ emit(ctx, or, dst, dst, tmp); /* reg = dst | tmp */ ++ } ++ break; ++ /* Swap bytes in a half word */ ++ case 16: ++ if (cpu_has_mips32r2 || cpu_has_mips32r6) { ++ emit(ctx, wsbh, dst, dst); ++ emit(ctx, andi, dst, dst, 0xffff); ++ } else { ++ emit(ctx, andi, tmp, dst, 0xff00); /* t = d & 0xff00 */ ++ emit(ctx, srl, tmp, tmp, 8); /* t = t >> 8 */ ++ emit(ctx, andi, dst, dst, 0x00ff); /* d = d & 0x00ff */ ++ emit(ctx, sll, dst, dst, 8); /* d = d << 8 */ ++ emit(ctx, or, dst, dst, tmp); /* d = d | t */ ++ } ++ break; ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Validate jump immediate range */ ++bool valid_jmp_i(u8 op, s32 imm) ++{ ++ switch (op) { ++ case JIT_JNOP: ++ /* Immediate value not used */ ++ return true; ++ case BPF_JEQ: ++ case BPF_JNE: ++ /* No immediate operation */ ++ return false; ++ case BPF_JSET: ++ case JIT_JNSET: ++ /* imm must be 16 bits unsigned */ ++ return imm >= 0 && imm <= 0xffff; ++ case BPF_JGE: ++ case BPF_JLT: ++ case BPF_JSGE: ++ case BPF_JSLT: ++ /* imm must be 16 bits */ ++ return imm >= -0x8000 && imm <= 0x7fff; ++ case BPF_JGT: ++ case BPF_JLE: ++ case BPF_JSGT: ++ case BPF_JSLE: ++ /* imm + 1 must be 16 bits */ ++ return imm >= -0x8001 && imm <= 0x7ffe; ++ } ++ return false; ++} ++ ++/* Invert a conditional jump operation */ ++static u8 invert_jmp(u8 op) ++{ ++ switch (op) { ++ case BPF_JA: return JIT_JNOP; ++ case BPF_JEQ: return BPF_JNE; ++ case BPF_JNE: return BPF_JEQ; ++ case BPF_JSET: return JIT_JNSET; ++ case BPF_JGT: return BPF_JLE; ++ case BPF_JGE: return BPF_JLT; ++ case BPF_JLT: return BPF_JGE; ++ case BPF_JLE: return BPF_JGT; ++ case BPF_JSGT: return BPF_JSLE; ++ case BPF_JSGE: return BPF_JSLT; ++ case BPF_JSLT: return BPF_JSGE; ++ case BPF_JSLE: return BPF_JSGT; ++ } ++ return 0; ++} ++ ++/* Prepare a PC-relative jump operation */ ++static void setup_jmp(struct jit_context *ctx, u8 bpf_op, ++ s16 bpf_off, u8 *jit_op, s32 *jit_off) ++{ ++ u32 *descp = &ctx->descriptors[ctx->bpf_index]; ++ int op = bpf_op; ++ int offset = 0; ++ ++ /* Do not compute offsets on the first pass */ ++ if (INDEX(*descp) == 0) ++ goto done; ++ ++ /* Skip jumps never taken */ ++ if (bpf_op == JIT_JNOP) ++ goto done; ++ ++ /* Convert jumps always taken */ ++ if (bpf_op == BPF_JA) ++ *descp |= JIT_DESC_CONVERT; ++ ++ /* ++ * Current ctx->jit_index points to the start of the branch preamble. ++ * Since the preamble differs among different branch conditionals, ++ * the current index cannot be used to compute the branch offset. ++ * Instead, we use the offset table value for the next instruction, ++ * which gives the index immediately after the branch delay slot. ++ */ ++ if (!CONVERTED(*descp)) { ++ int target = ctx->bpf_index + bpf_off + 1; ++ int origin = ctx->bpf_index + 1; ++ ++ offset = (INDEX(ctx->descriptors[target]) - ++ INDEX(ctx->descriptors[origin]) + 1) * sizeof(u32); ++ } ++ ++ /* ++ * The PC-relative branch offset field on MIPS is 18 bits signed, ++ * so if the computed offset is larger than this we generate a an ++ * absolute jump that we skip with an inverted conditional branch. ++ */ ++ if (CONVERTED(*descp) || offset < -0x20000 || offset > 0x1ffff) { ++ offset = 3 * sizeof(u32); ++ op = invert_jmp(bpf_op); ++ ctx->changes += !CONVERTED(*descp); ++ *descp |= JIT_DESC_CONVERT; ++ } ++ ++done: ++ *jit_off = offset; ++ *jit_op = op; ++} ++ ++/* Prepare a PC-relative jump operation with immediate conditional */ ++void setup_jmp_i(struct jit_context *ctx, s32 imm, u8 width, ++ u8 bpf_op, s16 bpf_off, u8 *jit_op, s32 *jit_off) ++{ ++ bool always = false; ++ bool never = false; ++ ++ switch (bpf_op) { ++ case BPF_JEQ: ++ case BPF_JNE: ++ break; ++ case BPF_JSET: ++ case BPF_JLT: ++ never = imm == 0; ++ break; ++ case BPF_JGE: ++ always = imm == 0; ++ break; ++ case BPF_JGT: ++ never = (u32)imm == U32_MAX; ++ break; ++ case BPF_JLE: ++ always = (u32)imm == U32_MAX; ++ break; ++ case BPF_JSGT: ++ never = imm == S32_MAX && width == 32; ++ break; ++ case BPF_JSGE: ++ always = imm == S32_MIN && width == 32; ++ break; ++ case BPF_JSLT: ++ never = imm == S32_MIN && width == 32; ++ break; ++ case BPF_JSLE: ++ always = imm == S32_MAX && width == 32; ++ break; ++ } ++ ++ if (never) ++ bpf_op = JIT_JNOP; ++ if (always) ++ bpf_op = BPF_JA; ++ setup_jmp(ctx, bpf_op, bpf_off, jit_op, jit_off); ++} ++ ++/* Prepare a PC-relative jump operation with register conditional */ ++void setup_jmp_r(struct jit_context *ctx, bool same_reg, ++ u8 bpf_op, s16 bpf_off, u8 *jit_op, s32 *jit_off) ++{ ++ switch (bpf_op) { ++ case BPF_JSET: ++ break; ++ case BPF_JEQ: ++ case BPF_JGE: ++ case BPF_JLE: ++ case BPF_JSGE: ++ case BPF_JSLE: ++ if (same_reg) ++ bpf_op = BPF_JA; ++ break; ++ case BPF_JNE: ++ case BPF_JLT: ++ case BPF_JGT: ++ case BPF_JSGT: ++ case BPF_JSLT: ++ if (same_reg) ++ bpf_op = JIT_JNOP; ++ break; ++ } ++ setup_jmp(ctx, bpf_op, bpf_off, jit_op, jit_off); ++} ++ ++/* Finish a PC-relative jump operation */ ++int finish_jmp(struct jit_context *ctx, u8 jit_op, s16 bpf_off) ++{ ++ /* Emit conditional branch delay slot */ ++ if (jit_op != JIT_JNOP) ++ emit(ctx, nop); ++ /* ++ * Emit an absolute long jump with delay slot, ++ * if the PC-relative branch was converted. ++ */ ++ if (CONVERTED(ctx->descriptors[ctx->bpf_index])) { ++ int target = get_target(ctx, ctx->bpf_index + bpf_off + 1); ++ ++ if (target < 0) ++ return -1; ++ emit(ctx, j, target); ++ emit(ctx, nop); ++ } ++ return 0; ++} ++ ++/* Jump immediate (32-bit) */ ++void emit_jmp_i(struct jit_context *ctx, u8 dst, s32 imm, s32 off, u8 op) ++{ ++ switch (op) { ++ /* No-op, used internally for branch optimization */ ++ case JIT_JNOP: ++ break; ++ /* PC += off if dst & imm */ ++ case BPF_JSET: ++ emit(ctx, andi, MIPS_R_T9, dst, (u16)imm); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if (dst & imm) == 0 (not in BPF, used for long jumps) */ ++ case JIT_JNSET: ++ emit(ctx, andi, MIPS_R_T9, dst, (u16)imm); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst > imm */ ++ case BPF_JGT: ++ emit(ctx, sltiu, MIPS_R_T9, dst, imm + 1); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst >= imm */ ++ case BPF_JGE: ++ emit(ctx, sltiu, MIPS_R_T9, dst, imm); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst < imm */ ++ case BPF_JLT: ++ emit(ctx, sltiu, MIPS_R_T9, dst, imm); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst <= imm */ ++ case BPF_JLE: ++ emit(ctx, sltiu, MIPS_R_T9, dst, imm + 1); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst > imm (signed) */ ++ case BPF_JSGT: ++ emit(ctx, slti, MIPS_R_T9, dst, imm + 1); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst >= imm (signed) */ ++ case BPF_JSGE: ++ emit(ctx, slti, MIPS_R_T9, dst, imm); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst < imm (signed) */ ++ case BPF_JSLT: ++ emit(ctx, slti, MIPS_R_T9, dst, imm); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst <= imm (signed) */ ++ case BPF_JSLE: ++ emit(ctx, slti, MIPS_R_T9, dst, imm + 1); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ } ++} ++ ++/* Jump register (32-bit) */ ++void emit_jmp_r(struct jit_context *ctx, u8 dst, u8 src, s32 off, u8 op) ++{ ++ switch (op) { ++ /* No-op, used internally for branch optimization */ ++ case JIT_JNOP: ++ break; ++ /* PC += off if dst == src */ ++ case BPF_JEQ: ++ emit(ctx, beq, dst, src, off); ++ break; ++ /* PC += off if dst != src */ ++ case BPF_JNE: ++ emit(ctx, bne, dst, src, off); ++ break; ++ /* PC += off if dst & src */ ++ case BPF_JSET: ++ emit(ctx, and, MIPS_R_T9, dst, src); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if (dst & imm) == 0 (not in BPF, used for long jumps) */ ++ case JIT_JNSET: ++ emit(ctx, and, MIPS_R_T9, dst, src); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst > src */ ++ case BPF_JGT: ++ emit(ctx, sltu, MIPS_R_T9, src, dst); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst >= src */ ++ case BPF_JGE: ++ emit(ctx, sltu, MIPS_R_T9, dst, src); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst < src */ ++ case BPF_JLT: ++ emit(ctx, sltu, MIPS_R_T9, dst, src); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst <= src */ ++ case BPF_JLE: ++ emit(ctx, sltu, MIPS_R_T9, src, dst); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst > src (signed) */ ++ case BPF_JSGT: ++ emit(ctx, slt, MIPS_R_T9, src, dst); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst >= src (signed) */ ++ case BPF_JSGE: ++ emit(ctx, slt, MIPS_R_T9, dst, src); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst < src (signed) */ ++ case BPF_JSLT: ++ emit(ctx, slt, MIPS_R_T9, dst, src); ++ emit(ctx, bnez, MIPS_R_T9, off); ++ break; ++ /* PC += off if dst <= src (signed) */ ++ case BPF_JSLE: ++ emit(ctx, slt, MIPS_R_T9, src, dst); ++ emit(ctx, beqz, MIPS_R_T9, off); ++ break; ++ } ++} ++ ++/* Jump always */ ++int emit_ja(struct jit_context *ctx, s16 off) ++{ ++ int target = get_target(ctx, ctx->bpf_index + off + 1); ++ ++ if (target < 0) ++ return -1; ++ emit(ctx, j, target); ++ emit(ctx, nop); ++ return 0; ++} ++ ++/* Jump to epilogue */ ++int emit_exit(struct jit_context *ctx) ++{ ++ int target = get_target(ctx, ctx->program->len); ++ ++ if (target < 0) ++ return -1; ++ emit(ctx, j, target); ++ emit(ctx, nop); ++ return 0; ++} ++ ++/* Build the program body from eBPF bytecode */ ++static int build_body(struct jit_context *ctx) ++{ ++ const struct bpf_prog *prog = ctx->program; ++ unsigned int i; ++ ++ ctx->stack_used = 0; ++ for (i = 0; i < prog->len; i++) { ++ const struct bpf_insn *insn = &prog->insnsi[i]; ++ u32 *descp = &ctx->descriptors[i]; ++ int ret; ++ ++ access_reg(ctx, insn->src_reg); ++ access_reg(ctx, insn->dst_reg); ++ ++ ctx->bpf_index = i; ++ if (ctx->target == NULL) { ++ ctx->changes += INDEX(*descp) != ctx->jit_index; ++ *descp &= JIT_DESC_CONVERT; ++ *descp |= ctx->jit_index; ++ } ++ ++ ret = build_insn(insn, ctx); ++ if (ret < 0) ++ return ret; ++ ++ if (ret > 0) { ++ i++; ++ if (ctx->target == NULL) ++ descp[1] = ctx->jit_index; ++ } ++ } ++ ++ /* Store the end offset, where the epilogue begins */ ++ ctx->descriptors[prog->len] = ctx->jit_index; ++ return 0; ++} ++ ++/* Set the branch conversion flag on all instructions */ ++static void set_convert_flag(struct jit_context *ctx, bool enable) ++{ ++ const struct bpf_prog *prog = ctx->program; ++ u32 flag = enable ? JIT_DESC_CONVERT : 0; ++ unsigned int i; ++ ++ for (i = 0; i <= prog->len; i++) ++ ctx->descriptors[i] = INDEX(ctx->descriptors[i]) | flag; ++} ++ ++static void jit_fill_hole(void *area, unsigned int size) ++{ ++ u32 *p; ++ ++ /* We are guaranteed to have aligned memory. */ ++ for (p = area; size >= sizeof(u32); size -= sizeof(u32)) ++ uasm_i_break(&p, BRK_BUG); /* Increments p */ ++} ++ ++bool bpf_jit_needs_zext(void) ++{ ++ return true; ++} ++ ++struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) ++{ ++ struct bpf_prog *tmp, *orig_prog = prog; ++ struct bpf_binary_header *header = NULL; ++ struct jit_context ctx; ++ bool tmp_blinded = false; ++ unsigned int tmp_idx; ++ unsigned int image_size; ++ u8 *image_ptr; ++ int tries; ++ ++ /* ++ * If BPF JIT was not enabled then we must fall back to ++ * the interpreter. ++ */ ++ if (!prog->jit_requested) ++ return orig_prog; ++ /* ++ * If constant blinding was enabled and we failed during blinding ++ * then we must fall back to the interpreter. Otherwise, we save ++ * the new JITed code. ++ */ ++ tmp = bpf_jit_blind_constants(prog); ++ if (IS_ERR(tmp)) ++ return orig_prog; ++ if (tmp != prog) { ++ tmp_blinded = true; ++ prog = tmp; ++ } ++ ++ memset(&ctx, 0, sizeof(ctx)); ++ ctx.program = prog; ++ ++ /* ++ * Not able to allocate memory for descriptors[], then ++ * we must fall back to the interpreter ++ */ ++ ctx.descriptors = kcalloc(prog->len + 1, sizeof(*ctx.descriptors), ++ GFP_KERNEL); ++ if (ctx.descriptors == NULL) ++ goto out_err; ++ ++ /* First pass discovers used resources */ ++ if (build_body(&ctx) < 0) ++ goto out_err; ++ /* ++ * Second pass computes instruction offsets. ++ * If any PC-relative branches are out of range, a sequence of ++ * a PC-relative branch + a jump is generated, and we have to ++ * try again from the beginning to generate the new offsets. ++ * This is done until no additional conversions are necessary. ++ * The last two iterations are done with all branches being ++ * converted, to guarantee offset table convergence within a ++ * fixed number of iterations. ++ */ ++ ctx.jit_index = 0; ++ build_prologue(&ctx); ++ tmp_idx = ctx.jit_index; ++ ++ tries = JIT_MAX_ITERATIONS; ++ do { ++ ctx.jit_index = tmp_idx; ++ ctx.changes = 0; ++ if (tries == 2) ++ set_convert_flag(&ctx, true); ++ if (build_body(&ctx) < 0) ++ goto out_err; ++ } while (ctx.changes > 0 && --tries > 0); ++ ++ if (WARN_ONCE(ctx.changes > 0, "JIT offsets failed to converge")) ++ goto out_err; ++ ++ build_epilogue(&ctx, MIPS_R_RA); ++ ++ /* Now we know the size of the structure to make */ ++ image_size = sizeof(u32) * ctx.jit_index; ++ header = bpf_jit_binary_alloc(image_size, &image_ptr, ++ sizeof(u32), jit_fill_hole); ++ /* ++ * Not able to allocate memory for the structure then ++ * we must fall back to the interpretation ++ */ ++ if (header == NULL) ++ goto out_err; ++ ++ /* Actual pass to generate final JIT code */ ++ ctx.target = (u32 *)image_ptr; ++ ctx.jit_index = 0; ++ ++ /* ++ * If building the JITed code fails somehow, ++ * we fall back to the interpretation. ++ */ ++ build_prologue(&ctx); ++ if (build_body(&ctx) < 0) ++ goto out_err; ++ build_epilogue(&ctx, MIPS_R_RA); ++ ++ /* Populate line info meta data */ ++ set_convert_flag(&ctx, false); ++ bpf_prog_fill_jited_linfo(prog, &ctx.descriptors[1]); ++ ++ /* Set as read-only exec and flush instruction cache */ ++ bpf_jit_binary_lock_ro(header); ++ flush_icache_range((unsigned long)header, ++ (unsigned long)&ctx.target[ctx.jit_index]); ++ ++ if (bpf_jit_enable > 1) ++ bpf_jit_dump(prog->len, image_size, 2, ctx.target); ++ ++ prog->bpf_func = (void *)ctx.target; ++ prog->jited = 1; ++ prog->jited_len = image_size; ++ ++out: ++ if (tmp_blinded) ++ bpf_jit_prog_release_other(prog, prog == orig_prog ? ++ tmp : orig_prog); ++ kfree(ctx.descriptors); ++ return prog; ++ ++out_err: ++ prog = orig_prog; ++ if (header) ++ bpf_jit_binary_free(header); ++ goto out; ++} +--- /dev/null ++++ b/arch/mips/net/bpf_jit_comp.h +@@ -0,0 +1,211 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Just-In-Time compiler for eBPF bytecode on 32-bit and 64-bit MIPS. ++ * ++ * Copyright (c) 2021 Anyfi Networks AB. ++ * Author: Johan Almbladh ++ * ++ * Based on code and ideas from ++ * Copyright (c) 2017 Cavium, Inc. ++ * Copyright (c) 2017 Shubham Bansal ++ * Copyright (c) 2011 Mircea Gherzan ++ */ ++ ++#ifndef _BPF_JIT_COMP_H ++#define _BPF_JIT_COMP_H ++ ++/* MIPS registers */ ++#define MIPS_R_ZERO 0 /* Const zero */ ++#define MIPS_R_AT 1 /* Asm temp */ ++#define MIPS_R_V0 2 /* Result */ ++#define MIPS_R_V1 3 /* Result */ ++#define MIPS_R_A0 4 /* Argument */ ++#define MIPS_R_A1 5 /* Argument */ ++#define MIPS_R_A2 6 /* Argument */ ++#define MIPS_R_A3 7 /* Argument */ ++#define MIPS_R_A4 8 /* Arg (n64) */ ++#define MIPS_R_A5 9 /* Arg (n64) */ ++#define MIPS_R_A6 10 /* Arg (n64) */ ++#define MIPS_R_A7 11 /* Arg (n64) */ ++#define MIPS_R_T0 8 /* Temp (o32) */ ++#define MIPS_R_T1 9 /* Temp (o32) */ ++#define MIPS_R_T2 10 /* Temp (o32) */ ++#define MIPS_R_T3 11 /* Temp (o32) */ ++#define MIPS_R_T4 12 /* Temporary */ ++#define MIPS_R_T5 13 /* Temporary */ ++#define MIPS_R_T6 14 /* Temporary */ ++#define MIPS_R_T7 15 /* Temporary */ ++#define MIPS_R_S0 16 /* Saved */ ++#define MIPS_R_S1 17 /* Saved */ ++#define MIPS_R_S2 18 /* Saved */ ++#define MIPS_R_S3 19 /* Saved */ ++#define MIPS_R_S4 20 /* Saved */ ++#define MIPS_R_S5 21 /* Saved */ ++#define MIPS_R_S6 22 /* Saved */ ++#define MIPS_R_S7 23 /* Saved */ ++#define MIPS_R_T8 24 /* Temporary */ ++#define MIPS_R_T9 25 /* Temporary */ ++/* MIPS_R_K0 26 Reserved */ ++/* MIPS_R_K1 27 Reserved */ ++#define MIPS_R_GP 28 /* Global ptr */ ++#define MIPS_R_SP 29 /* Stack ptr */ ++#define MIPS_R_FP 30 /* Frame ptr */ ++#define MIPS_R_RA 31 /* Return */ ++ ++/* ++ * Jump address mask for immediate jumps. The four most significant bits ++ * must be equal to PC. ++ */ ++#define MIPS_JMP_MASK 0x0fffffffUL ++ ++/* Maximum number of iterations in offset table computation */ ++#define JIT_MAX_ITERATIONS 8 ++ ++/* ++ * Jump pseudo-instructions used internally ++ * for branch conversion and branch optimization. ++ */ ++#define JIT_JNSET 0xe0 ++#define JIT_JNOP 0xf0 ++ ++/* Descriptor flag for PC-relative branch conversion */ ++#define JIT_DESC_CONVERT BIT(31) ++ ++/* JIT context for an eBPF program */ ++struct jit_context { ++ struct bpf_prog *program; /* The eBPF program being JITed */ ++ u32 *descriptors; /* eBPF to JITed CPU insn descriptors */ ++ u32 *target; /* JITed code buffer */ ++ u32 bpf_index; /* Index of current BPF program insn */ ++ u32 jit_index; /* Index of current JIT target insn */ ++ u32 changes; /* Number of PC-relative branch conv */ ++ u32 accessed; /* Bit mask of read eBPF registers */ ++ u32 clobbered; /* Bit mask of modified CPU registers */ ++ u32 stack_size; /* Total allocated stack size in bytes */ ++ u32 saved_size; /* Size of callee-saved registers */ ++ u32 stack_used; /* Stack size used for function calls */ ++}; ++ ++/* Emit the instruction if the JIT memory space has been allocated */ ++#define emit(ctx, func, ...) \ ++do { \ ++ if ((ctx)->target != NULL) { \ ++ u32 *p = &(ctx)->target[ctx->jit_index]; \ ++ uasm_i_##func(&p, ##__VA_ARGS__); \ ++ } \ ++ (ctx)->jit_index++; \ ++} while (0) ++ ++/* ++ * Mark a BPF register as accessed, it needs to be ++ * initialized by the program if expected, e.g. FP. ++ */ ++static inline void access_reg(struct jit_context *ctx, u8 reg) ++{ ++ ctx->accessed |= BIT(reg); ++} ++ ++/* ++ * Mark a CPU register as clobbered, it needs to be ++ * saved/restored by the program if callee-saved. ++ */ ++static inline void clobber_reg(struct jit_context *ctx, u8 reg) ++{ ++ ctx->clobbered |= BIT(reg); ++} ++ ++/* ++ * Push registers on the stack, starting at a given depth from the stack ++ * pointer and increasing. The next depth to be written is returned. ++ */ ++int push_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth); ++ ++/* ++ * Pop registers from the stack, starting at a given depth from the stack ++ * pointer and increasing. The next depth to be read is returned. ++ */ ++int pop_regs(struct jit_context *ctx, u32 mask, u32 excl, int depth); ++ ++/* Compute the 28-bit jump target address from a BPF program location */ ++int get_target(struct jit_context *ctx, u32 loc); ++ ++/* Compute the PC-relative offset to relative BPF program offset */ ++int get_offset(const struct jit_context *ctx, int off); ++ ++/* dst = imm (32-bit) */ ++void emit_mov_i(struct jit_context *ctx, u8 dst, s32 imm); ++ ++/* dst = src (32-bit) */ ++void emit_mov_r(struct jit_context *ctx, u8 dst, u8 src); ++ ++/* Validate ALU/ALU64 immediate range */ ++bool valid_alu_i(u8 op, s32 imm); ++ ++/* Rewrite ALU/ALU64 immediate operation */ ++bool rewrite_alu_i(u8 op, s32 imm, u8 *alu, s32 *val); ++ ++/* ALU immediate operation (32-bit) */ ++void emit_alu_i(struct jit_context *ctx, u8 dst, s32 imm, u8 op); ++ ++/* ALU register operation (32-bit) */ ++void emit_alu_r(struct jit_context *ctx, u8 dst, u8 src, u8 op); ++ ++/* Atomic read-modify-write (32-bit) */ ++void emit_atomic_r(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 code); ++ ++/* Atomic compare-and-exchange (32-bit) */ ++void emit_cmpxchg_r(struct jit_context *ctx, u8 dst, u8 src, u8 res, s16 off); ++ ++/* Swap bytes and truncate a register word or half word */ ++void emit_bswap_r(struct jit_context *ctx, u8 dst, u32 width); ++ ++/* Validate JMP/JMP32 immediate range */ ++bool valid_jmp_i(u8 op, s32 imm); ++ ++/* Prepare a PC-relative jump operation with immediate conditional */ ++void setup_jmp_i(struct jit_context *ctx, s32 imm, u8 width, ++ u8 bpf_op, s16 bpf_off, u8 *jit_op, s32 *jit_off); ++ ++/* Prepare a PC-relative jump operation with register conditional */ ++void setup_jmp_r(struct jit_context *ctx, bool same_reg, ++ u8 bpf_op, s16 bpf_off, u8 *jit_op, s32 *jit_off); ++ ++/* Finish a PC-relative jump operation */ ++int finish_jmp(struct jit_context *ctx, u8 jit_op, s16 bpf_off); ++ ++/* Conditional JMP/JMP32 immediate */ ++void emit_jmp_i(struct jit_context *ctx, u8 dst, s32 imm, s32 off, u8 op); ++ ++/* Conditional JMP/JMP32 register */ ++void emit_jmp_r(struct jit_context *ctx, u8 dst, u8 src, s32 off, u8 op); ++ ++/* Jump always */ ++int emit_ja(struct jit_context *ctx, s16 off); ++ ++/* Jump to epilogue */ ++int emit_exit(struct jit_context *ctx); ++ ++/* ++ * Build program prologue to set up the stack and registers. ++ * This function is implemented separately for 32-bit and 64-bit JITs. ++ */ ++void build_prologue(struct jit_context *ctx); ++ ++/* ++ * Build the program epilogue to restore the stack and registers. ++ * This function is implemented separately for 32-bit and 64-bit JITs. ++ */ ++void build_epilogue(struct jit_context *ctx, int dest_reg); ++ ++/* ++ * Convert an eBPF instruction to native instruction, i.e ++ * JITs an eBPF instruction. ++ * Returns : ++ * 0 - Successfully JITed an 8-byte eBPF instruction ++ * >0 - Successfully JITed a 16-byte eBPF instruction ++ * <0 - Failed to JIT. ++ * This function is implemented separately for 32-bit and 64-bit JITs. ++ */ ++int build_insn(const struct bpf_insn *insn, struct jit_context *ctx); ++ ++#endif /* _BPF_JIT_COMP_H */ +--- /dev/null ++++ b/arch/mips/net/bpf_jit_comp32.c +@@ -0,0 +1,1741 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Just-In-Time compiler for eBPF bytecode on MIPS. ++ * Implementation of JIT functions for 32-bit CPUs. ++ * ++ * Copyright (c) 2021 Anyfi Networks AB. ++ * Author: Johan Almbladh ++ * ++ * Based on code and ideas from ++ * Copyright (c) 2017 Cavium, Inc. ++ * Copyright (c) 2017 Shubham Bansal ++ * Copyright (c) 2011 Mircea Gherzan ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bpf_jit_comp.h" ++ ++/* MIPS a4-a7 are not available in the o32 ABI */ ++#undef MIPS_R_A4 ++#undef MIPS_R_A5 ++#undef MIPS_R_A6 ++#undef MIPS_R_A7 ++ ++/* Stack is 8-byte aligned in o32 ABI */ ++#define MIPS_STACK_ALIGNMENT 8 ++ ++/* ++ * The top 16 bytes of a stack frame is reserved for the callee in O32 ABI. ++ * This corresponds to stack space for register arguments a0-a3. ++ */ ++#define JIT_RESERVED_STACK 16 ++ ++/* Temporary 64-bit register used by JIT */ ++#define JIT_REG_TMP MAX_BPF_JIT_REG ++ ++/* ++ * Number of prologue bytes to skip when doing a tail call. ++ * Tail call count (TCC) initialization (8 bytes) always, plus ++ * R0-to-v0 assignment (4 bytes) if big endian. ++ */ ++#ifdef __BIG_ENDIAN ++#define JIT_TCALL_SKIP 12 ++#else ++#define JIT_TCALL_SKIP 8 ++#endif ++ ++/* CPU registers holding the callee return value */ ++#define JIT_RETURN_REGS \ ++ (BIT(MIPS_R_V0) | \ ++ BIT(MIPS_R_V1)) ++ ++/* CPU registers arguments passed to callee directly */ ++#define JIT_ARG_REGS \ ++ (BIT(MIPS_R_A0) | \ ++ BIT(MIPS_R_A1) | \ ++ BIT(MIPS_R_A2) | \ ++ BIT(MIPS_R_A3)) ++ ++/* CPU register arguments passed to callee on stack */ ++#define JIT_STACK_REGS \ ++ (BIT(MIPS_R_T0) | \ ++ BIT(MIPS_R_T1) | \ ++ BIT(MIPS_R_T2) | \ ++ BIT(MIPS_R_T3) | \ ++ BIT(MIPS_R_T4) | \ ++ BIT(MIPS_R_T5)) ++ ++/* Caller-saved CPU registers */ ++#define JIT_CALLER_REGS \ ++ (JIT_RETURN_REGS | \ ++ JIT_ARG_REGS | \ ++ JIT_STACK_REGS) ++ ++/* Callee-saved CPU registers */ ++#define JIT_CALLEE_REGS \ ++ (BIT(MIPS_R_S0) | \ ++ BIT(MIPS_R_S1) | \ ++ BIT(MIPS_R_S2) | \ ++ BIT(MIPS_R_S3) | \ ++ BIT(MIPS_R_S4) | \ ++ BIT(MIPS_R_S5) | \ ++ BIT(MIPS_R_S6) | \ ++ BIT(MIPS_R_S7) | \ ++ BIT(MIPS_R_GP) | \ ++ BIT(MIPS_R_FP) | \ ++ BIT(MIPS_R_RA)) ++ ++/* ++ * Mapping of 64-bit eBPF registers to 32-bit native MIPS registers. ++ * ++ * 1) Native register pairs are ordered according to CPU endiannes, following ++ * the MIPS convention for passing 64-bit arguments and return values. ++ * 2) The eBPF return value, arguments and callee-saved registers are mapped ++ * to their native MIPS equivalents. ++ * 3) Since the 32 highest bits in the eBPF FP register are always zero, ++ * only one general-purpose register is actually needed for the mapping. ++ * We use the fp register for this purpose, and map the highest bits to ++ * the MIPS register r0 (zero). ++ * 4) We use the MIPS gp and at registers as internal temporary registers ++ * for constant blinding. The gp register is callee-saved. ++ * 5) One 64-bit temporary register is mapped for use when sign-extending ++ * immediate operands. MIPS registers t6-t9 are available to the JIT ++ * for as temporaries when implementing complex 64-bit operations. ++ * ++ * With this scheme all eBPF registers are being mapped to native MIPS ++ * registers without having to use any stack scratch space. The direct ++ * register mapping (2) simplifies the handling of function calls. ++ */ ++static const u8 bpf2mips32[][2] = { ++ /* Return value from in-kernel function, and exit value from eBPF */ ++ [BPF_REG_0] = {MIPS_R_V1, MIPS_R_V0}, ++ /* Arguments from eBPF program to in-kernel function */ ++ [BPF_REG_1] = {MIPS_R_A1, MIPS_R_A0}, ++ [BPF_REG_2] = {MIPS_R_A3, MIPS_R_A2}, ++ /* Remaining arguments, to be passed on the stack per O32 ABI */ ++ [BPF_REG_3] = {MIPS_R_T1, MIPS_R_T0}, ++ [BPF_REG_4] = {MIPS_R_T3, MIPS_R_T2}, ++ [BPF_REG_5] = {MIPS_R_T5, MIPS_R_T4}, ++ /* Callee-saved registers that in-kernel function will preserve */ ++ [BPF_REG_6] = {MIPS_R_S1, MIPS_R_S0}, ++ [BPF_REG_7] = {MIPS_R_S3, MIPS_R_S2}, ++ [BPF_REG_8] = {MIPS_R_S5, MIPS_R_S4}, ++ [BPF_REG_9] = {MIPS_R_S7, MIPS_R_S6}, ++ /* Read-only frame pointer to access the eBPF stack */ ++#ifdef __BIG_ENDIAN ++ [BPF_REG_FP] = {MIPS_R_FP, MIPS_R_ZERO}, ++#else ++ [BPF_REG_FP] = {MIPS_R_ZERO, MIPS_R_FP}, ++#endif ++ /* Temporary register for blinding constants */ ++ [BPF_REG_AX] = {MIPS_R_GP, MIPS_R_AT}, ++ /* Temporary register for internal JIT use */ ++ [JIT_REG_TMP] = {MIPS_R_T7, MIPS_R_T6}, ++}; ++ ++/* Get low CPU register for a 64-bit eBPF register mapping */ ++static inline u8 lo(const u8 reg[]) ++{ ++#ifdef __BIG_ENDIAN ++ return reg[0]; ++#else ++ return reg[1]; ++#endif ++} ++ ++/* Get high CPU register for a 64-bit eBPF register mapping */ ++static inline u8 hi(const u8 reg[]) ++{ ++#ifdef __BIG_ENDIAN ++ return reg[1]; ++#else ++ return reg[0]; ++#endif ++} ++ ++/* ++ * Mark a 64-bit CPU register pair as clobbered, it needs to be ++ * saved/restored by the program if callee-saved. ++ */ ++static void clobber_reg64(struct jit_context *ctx, const u8 reg[]) ++{ ++ clobber_reg(ctx, reg[0]); ++ clobber_reg(ctx, reg[1]); ++} ++ ++/* dst = imm (sign-extended) */ ++static void emit_mov_se_i64(struct jit_context *ctx, const u8 dst[], s32 imm) ++{ ++ emit_mov_i(ctx, lo(dst), imm); ++ if (imm < 0) ++ emit(ctx, addiu, hi(dst), MIPS_R_ZERO, -1); ++ else ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ clobber_reg64(ctx, dst); ++} ++ ++/* Zero extension, if verifier does not do it for us */ ++static void emit_zext_ver(struct jit_context *ctx, const u8 dst[]) ++{ ++ if (!ctx->program->aux->verifier_zext) { ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ clobber_reg(ctx, hi(dst)); ++ } ++} ++ ++/* Load delay slot, if ISA mandates it */ ++static void emit_load_delay(struct jit_context *ctx) ++{ ++ if (!cpu_has_mips_2_3_4_5_r) ++ emit(ctx, nop); ++} ++ ++/* ALU immediate operation (64-bit) */ ++static void emit_alu_i64(struct jit_context *ctx, ++ const u8 dst[], s32 imm, u8 op) ++{ ++ u8 src = MIPS_R_T6; ++ ++ /* ++ * ADD/SUB with all but the max negative imm can be handled by ++ * inverting the operation and the imm value, saving one insn. ++ */ ++ if (imm > S32_MIN && imm < 0) ++ switch (op) { ++ case BPF_ADD: ++ op = BPF_SUB; ++ imm = -imm; ++ break; ++ case BPF_SUB: ++ op = BPF_ADD; ++ imm = -imm; ++ break; ++ } ++ ++ /* Move immediate to temporary register */ ++ emit_mov_i(ctx, src, imm); ++ ++ switch (op) { ++ /* dst = dst + imm */ ++ case BPF_ADD: ++ emit(ctx, addu, lo(dst), lo(dst), src); ++ emit(ctx, sltu, MIPS_R_T9, lo(dst), src); ++ emit(ctx, addu, hi(dst), hi(dst), MIPS_R_T9); ++ if (imm < 0) ++ emit(ctx, addiu, hi(dst), hi(dst), -1); ++ break; ++ /* dst = dst - imm */ ++ case BPF_SUB: ++ emit(ctx, sltu, MIPS_R_T9, lo(dst), src); ++ emit(ctx, subu, lo(dst), lo(dst), src); ++ emit(ctx, subu, hi(dst), hi(dst), MIPS_R_T9); ++ if (imm < 0) ++ emit(ctx, addiu, hi(dst), hi(dst), 1); ++ break; ++ /* dst = dst | imm */ ++ case BPF_OR: ++ emit(ctx, or, lo(dst), lo(dst), src); ++ if (imm < 0) ++ emit(ctx, addiu, hi(dst), MIPS_R_ZERO, -1); ++ break; ++ /* dst = dst & imm */ ++ case BPF_AND: ++ emit(ctx, and, lo(dst), lo(dst), src); ++ if (imm >= 0) ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ break; ++ /* dst = dst ^ imm */ ++ case BPF_XOR: ++ emit(ctx, xor, lo(dst), lo(dst), src); ++ if (imm < 0) { ++ emit(ctx, subu, hi(dst), MIPS_R_ZERO, hi(dst)); ++ emit(ctx, addiu, hi(dst), hi(dst), -1); ++ } ++ break; ++ } ++ clobber_reg64(ctx, dst); ++} ++ ++/* ALU register operation (64-bit) */ ++static void emit_alu_r64(struct jit_context *ctx, ++ const u8 dst[], const u8 src[], u8 op) ++{ ++ switch (BPF_OP(op)) { ++ /* dst = dst + src */ ++ case BPF_ADD: ++ if (src == dst) { ++ emit(ctx, srl, MIPS_R_T9, lo(dst), 31); ++ emit(ctx, addu, lo(dst), lo(dst), lo(dst)); ++ } else { ++ emit(ctx, addu, lo(dst), lo(dst), lo(src)); ++ emit(ctx, sltu, MIPS_R_T9, lo(dst), lo(src)); ++ } ++ emit(ctx, addu, hi(dst), hi(dst), hi(src)); ++ emit(ctx, addu, hi(dst), hi(dst), MIPS_R_T9); ++ break; ++ /* dst = dst - src */ ++ case BPF_SUB: ++ emit(ctx, sltu, MIPS_R_T9, lo(dst), lo(src)); ++ emit(ctx, subu, lo(dst), lo(dst), lo(src)); ++ emit(ctx, subu, hi(dst), hi(dst), hi(src)); ++ emit(ctx, subu, hi(dst), hi(dst), MIPS_R_T9); ++ break; ++ /* dst = dst | src */ ++ case BPF_OR: ++ emit(ctx, or, lo(dst), lo(dst), lo(src)); ++ emit(ctx, or, hi(dst), hi(dst), hi(src)); ++ break; ++ /* dst = dst & src */ ++ case BPF_AND: ++ emit(ctx, and, lo(dst), lo(dst), lo(src)); ++ emit(ctx, and, hi(dst), hi(dst), hi(src)); ++ break; ++ /* dst = dst ^ src */ ++ case BPF_XOR: ++ emit(ctx, xor, lo(dst), lo(dst), lo(src)); ++ emit(ctx, xor, hi(dst), hi(dst), hi(src)); ++ break; ++ } ++ clobber_reg64(ctx, dst); ++} ++ ++/* ALU invert (64-bit) */ ++static void emit_neg_i64(struct jit_context *ctx, const u8 dst[]) ++{ ++ emit(ctx, sltu, MIPS_R_T9, MIPS_R_ZERO, lo(dst)); ++ emit(ctx, subu, lo(dst), MIPS_R_ZERO, lo(dst)); ++ emit(ctx, subu, hi(dst), MIPS_R_ZERO, hi(dst)); ++ emit(ctx, subu, hi(dst), hi(dst), MIPS_R_T9); ++ ++ clobber_reg64(ctx, dst); ++} ++ ++/* ALU shift immediate (64-bit) */ ++static void emit_shift_i64(struct jit_context *ctx, ++ const u8 dst[], u32 imm, u8 op) ++{ ++ switch (BPF_OP(op)) { ++ /* dst = dst << imm */ ++ case BPF_LSH: ++ if (imm < 32) { ++ emit(ctx, srl, MIPS_R_T9, lo(dst), 32 - imm); ++ emit(ctx, sll, lo(dst), lo(dst), imm); ++ emit(ctx, sll, hi(dst), hi(dst), imm); ++ emit(ctx, or, hi(dst), hi(dst), MIPS_R_T9); ++ } else { ++ emit(ctx, sll, hi(dst), lo(dst), imm - 32); ++ emit(ctx, move, lo(dst), MIPS_R_ZERO); ++ } ++ break; ++ /* dst = dst >> imm */ ++ case BPF_RSH: ++ if (imm < 32) { ++ emit(ctx, sll, MIPS_R_T9, hi(dst), 32 - imm); ++ emit(ctx, srl, lo(dst), lo(dst), imm); ++ emit(ctx, srl, hi(dst), hi(dst), imm); ++ emit(ctx, or, lo(dst), lo(dst), MIPS_R_T9); ++ } else { ++ emit(ctx, srl, lo(dst), hi(dst), imm - 32); ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ } ++ break; ++ /* dst = dst >> imm (arithmetic) */ ++ case BPF_ARSH: ++ if (imm < 32) { ++ emit(ctx, sll, MIPS_R_T9, hi(dst), 32 - imm); ++ emit(ctx, srl, lo(dst), lo(dst), imm); ++ emit(ctx, sra, hi(dst), hi(dst), imm); ++ emit(ctx, or, lo(dst), lo(dst), MIPS_R_T9); ++ } else { ++ emit(ctx, sra, lo(dst), hi(dst), imm - 32); ++ emit(ctx, sra, hi(dst), hi(dst), 31); ++ } ++ break; ++ } ++ clobber_reg64(ctx, dst); ++} ++ ++/* ALU shift register (64-bit) */ ++static void emit_shift_r64(struct jit_context *ctx, ++ const u8 dst[], u8 src, u8 op) ++{ ++ u8 t1 = MIPS_R_T8; ++ u8 t2 = MIPS_R_T9; ++ ++ emit(ctx, andi, t1, src, 32); /* t1 = src & 32 */ ++ emit(ctx, beqz, t1, 16); /* PC += 16 if t1 == 0 */ ++ emit(ctx, nor, t2, src, MIPS_R_ZERO); /* t2 = ~src (delay slot) */ ++ ++ switch (BPF_OP(op)) { ++ /* dst = dst << src */ ++ case BPF_LSH: ++ /* Next: shift >= 32 */ ++ emit(ctx, sllv, hi(dst), lo(dst), src); /* dh = dl << src */ ++ emit(ctx, move, lo(dst), MIPS_R_ZERO); /* dl = 0 */ ++ emit(ctx, b, 20); /* PC += 20 */ ++ /* +16: shift < 32 */ ++ emit(ctx, srl, t1, lo(dst), 1); /* t1 = dl >> 1 */ ++ emit(ctx, srlv, t1, t1, t2); /* t1 = t1 >> t2 */ ++ emit(ctx, sllv, lo(dst), lo(dst), src); /* dl = dl << src */ ++ emit(ctx, sllv, hi(dst), hi(dst), src); /* dh = dh << src */ ++ emit(ctx, or, hi(dst), hi(dst), t1); /* dh = dh | t1 */ ++ break; ++ /* dst = dst >> src */ ++ case BPF_RSH: ++ /* Next: shift >= 32 */ ++ emit(ctx, srlv, lo(dst), hi(dst), src); /* dl = dh >> src */ ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); /* dh = 0 */ ++ emit(ctx, b, 20); /* PC += 20 */ ++ /* +16: shift < 32 */ ++ emit(ctx, sll, t1, hi(dst), 1); /* t1 = dl << 1 */ ++ emit(ctx, sllv, t1, t1, t2); /* t1 = t1 << t2 */ ++ emit(ctx, srlv, lo(dst), lo(dst), src); /* dl = dl >> src */ ++ emit(ctx, srlv, hi(dst), hi(dst), src); /* dh = dh >> src */ ++ emit(ctx, or, lo(dst), lo(dst), t1); /* dl = dl | t1 */ ++ break; ++ /* dst = dst >> src (arithmetic) */ ++ case BPF_ARSH: ++ /* Next: shift >= 32 */ ++ emit(ctx, srav, lo(dst), hi(dst), src); /* dl = dh >>a src */ ++ emit(ctx, sra, hi(dst), hi(dst), 31); /* dh = dh >>a 31 */ ++ emit(ctx, b, 20); /* PC += 20 */ ++ /* +16: shift < 32 */ ++ emit(ctx, sll, t1, hi(dst), 1); /* t1 = dl << 1 */ ++ emit(ctx, sllv, t1, t1, t2); /* t1 = t1 << t2 */ ++ emit(ctx, srlv, lo(dst), lo(dst), src); /* dl = dl >>a src */ ++ emit(ctx, srav, hi(dst), hi(dst), src); /* dh = dh >> src */ ++ emit(ctx, or, lo(dst), lo(dst), t1); /* dl = dl | t1 */ ++ break; ++ } ++ ++ /* +20: Done */ ++ clobber_reg64(ctx, dst); ++} ++ ++/* ALU mul immediate (64x32-bit) */ ++static void emit_mul_i64(struct jit_context *ctx, const u8 dst[], s32 imm) ++{ ++ u8 src = MIPS_R_T6; ++ u8 tmp = MIPS_R_T9; ++ ++ switch (imm) { ++ /* dst = dst * 1 is a no-op */ ++ case 1: ++ break; ++ /* dst = dst * -1 */ ++ case -1: ++ emit_neg_i64(ctx, dst); ++ break; ++ case 0: ++ emit_mov_r(ctx, lo(dst), MIPS_R_ZERO); ++ emit_mov_r(ctx, hi(dst), MIPS_R_ZERO); ++ break; ++ /* Full 64x32 multiply */ ++ default: ++ /* hi(dst) = hi(dst) * src(imm) */ ++ emit_mov_i(ctx, src, imm); ++ if (cpu_has_mips32r1 || cpu_has_mips32r6) { ++ emit(ctx, mul, hi(dst), hi(dst), src); ++ } else { ++ emit(ctx, multu, hi(dst), src); ++ emit(ctx, mflo, hi(dst)); ++ } ++ ++ /* hi(dst) = hi(dst) - lo(dst) */ ++ if (imm < 0) ++ emit(ctx, subu, hi(dst), hi(dst), lo(dst)); ++ ++ /* tmp = lo(dst) * src(imm) >> 32 */ ++ /* lo(dst) = lo(dst) * src(imm) */ ++ if (cpu_has_mips32r6) { ++ emit(ctx, muhu, tmp, lo(dst), src); ++ emit(ctx, mulu, lo(dst), lo(dst), src); ++ } else { ++ emit(ctx, multu, lo(dst), src); ++ emit(ctx, mflo, lo(dst)); ++ emit(ctx, mfhi, tmp); ++ } ++ ++ /* hi(dst) += tmp */ ++ emit(ctx, addu, hi(dst), hi(dst), tmp); ++ clobber_reg64(ctx, dst); ++ break; ++ } ++} ++ ++/* ALU mul register (64x64-bit) */ ++static void emit_mul_r64(struct jit_context *ctx, ++ const u8 dst[], const u8 src[]) ++{ ++ u8 acc = MIPS_R_T8; ++ u8 tmp = MIPS_R_T9; ++ ++ /* acc = hi(dst) * lo(src) */ ++ if (cpu_has_mips32r1 || cpu_has_mips32r6) { ++ emit(ctx, mul, acc, hi(dst), lo(src)); ++ } else { ++ emit(ctx, multu, hi(dst), lo(src)); ++ emit(ctx, mflo, acc); ++ } ++ ++ /* tmp = lo(dst) * hi(src) */ ++ if (cpu_has_mips32r1 || cpu_has_mips32r6) { ++ emit(ctx, mul, tmp, lo(dst), hi(src)); ++ } else { ++ emit(ctx, multu, lo(dst), hi(src)); ++ emit(ctx, mflo, tmp); ++ } ++ ++ /* acc += tmp */ ++ emit(ctx, addu, acc, acc, tmp); ++ ++ /* tmp = lo(dst) * lo(src) >> 32 */ ++ /* lo(dst) = lo(dst) * lo(src) */ ++ if (cpu_has_mips32r6) { ++ emit(ctx, muhu, tmp, lo(dst), lo(src)); ++ emit(ctx, mulu, lo(dst), lo(dst), lo(src)); ++ } else { ++ emit(ctx, multu, lo(dst), lo(src)); ++ emit(ctx, mflo, lo(dst)); ++ emit(ctx, mfhi, tmp); ++ } ++ ++ /* hi(dst) = acc + tmp */ ++ emit(ctx, addu, hi(dst), acc, tmp); ++ clobber_reg64(ctx, dst); ++} ++ ++/* Helper function for 64-bit modulo */ ++static u64 jit_mod64(u64 a, u64 b) ++{ ++ u64 rem; ++ ++ div64_u64_rem(a, b, &rem); ++ return rem; ++} ++ ++/* ALU div/mod register (64-bit) */ ++static void emit_divmod_r64(struct jit_context *ctx, ++ const u8 dst[], const u8 src[], u8 op) ++{ ++ const u8 *r0 = bpf2mips32[BPF_REG_0]; /* Mapped to v0-v1 */ ++ const u8 *r1 = bpf2mips32[BPF_REG_1]; /* Mapped to a0-a1 */ ++ const u8 *r2 = bpf2mips32[BPF_REG_2]; /* Mapped to a2-a3 */ ++ int exclude, k; ++ u32 addr = 0; ++ ++ /* Push caller-saved registers on stack */ ++ push_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, ++ 0, JIT_RESERVED_STACK); ++ ++ /* Put 64-bit arguments 1 and 2 in registers a0-a3 */ ++ for (k = 0; k < 2; k++) { ++ emit(ctx, move, MIPS_R_T9, src[k]); ++ emit(ctx, move, r1[k], dst[k]); ++ emit(ctx, move, r2[k], MIPS_R_T9); ++ } ++ ++ /* Emit function call */ ++ switch (BPF_OP(op)) { ++ /* dst = dst / src */ ++ case BPF_DIV: ++ addr = (u32)&div64_u64; ++ break; ++ /* dst = dst % src */ ++ case BPF_MOD: ++ addr = (u32)&jit_mod64; ++ break; ++ } ++ emit_mov_i(ctx, MIPS_R_T9, addr); ++ emit(ctx, jalr, MIPS_R_RA, MIPS_R_T9); ++ emit(ctx, nop); /* Delay slot */ ++ ++ /* Store the 64-bit result in dst */ ++ emit(ctx, move, dst[0], r0[0]); ++ emit(ctx, move, dst[1], r0[1]); ++ ++ /* Restore caller-saved registers, excluding the computed result */ ++ exclude = BIT(lo(dst)) | BIT(hi(dst)); ++ pop_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, ++ exclude, JIT_RESERVED_STACK); ++ emit_load_delay(ctx); ++ ++ clobber_reg64(ctx, dst); ++ clobber_reg(ctx, MIPS_R_V0); ++ clobber_reg(ctx, MIPS_R_V1); ++ clobber_reg(ctx, MIPS_R_RA); ++} ++ ++/* Swap bytes in a register word */ ++static void emit_swap8_r(struct jit_context *ctx, u8 dst, u8 src, u8 mask) ++{ ++ u8 tmp = MIPS_R_T9; ++ ++ emit(ctx, and, tmp, src, mask); /* tmp = src & 0x00ff00ff */ ++ emit(ctx, sll, tmp, tmp, 8); /* tmp = tmp << 8 */ ++ emit(ctx, srl, dst, src, 8); /* dst = src >> 8 */ ++ emit(ctx, and, dst, dst, mask); /* dst = dst & 0x00ff00ff */ ++ emit(ctx, or, dst, dst, tmp); /* dst = dst | tmp */ ++} ++ ++/* Swap half words in a register word */ ++static void emit_swap16_r(struct jit_context *ctx, u8 dst, u8 src) ++{ ++ u8 tmp = MIPS_R_T9; ++ ++ emit(ctx, sll, tmp, src, 16); /* tmp = src << 16 */ ++ emit(ctx, srl, dst, src, 16); /* dst = src >> 16 */ ++ emit(ctx, or, dst, dst, tmp); /* dst = dst | tmp */ ++} ++ ++/* Swap bytes and truncate a register double word, word or half word */ ++static void emit_bswap_r64(struct jit_context *ctx, const u8 dst[], u32 width) ++{ ++ u8 tmp = MIPS_R_T8; ++ ++ switch (width) { ++ /* Swap bytes in a double word */ ++ case 64: ++ if (cpu_has_mips32r2 || cpu_has_mips32r6) { ++ emit(ctx, rotr, tmp, hi(dst), 16); ++ emit(ctx, rotr, hi(dst), lo(dst), 16); ++ emit(ctx, wsbh, lo(dst), tmp); ++ emit(ctx, wsbh, hi(dst), hi(dst)); ++ } else { ++ emit_swap16_r(ctx, tmp, lo(dst)); ++ emit_swap16_r(ctx, lo(dst), hi(dst)); ++ emit(ctx, move, hi(dst), tmp); ++ ++ emit(ctx, lui, tmp, 0xff); /* tmp = 0x00ff0000 */ ++ emit(ctx, ori, tmp, tmp, 0xff); /* tmp = 0x00ff00ff */ ++ emit_swap8_r(ctx, lo(dst), lo(dst), tmp); ++ emit_swap8_r(ctx, hi(dst), hi(dst), tmp); ++ } ++ break; ++ /* Swap bytes in a word */ ++ /* Swap bytes in a half word */ ++ case 32: ++ case 16: ++ emit_bswap_r(ctx, lo(dst), width); ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ break; ++ } ++ clobber_reg64(ctx, dst); ++} ++ ++/* Truncate a register double word, word or half word */ ++static void emit_trunc_r64(struct jit_context *ctx, const u8 dst[], u32 width) ++{ ++ switch (width) { ++ case 64: ++ break; ++ /* Zero-extend a word */ ++ case 32: ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ clobber_reg(ctx, hi(dst)); ++ break; ++ /* Zero-extend a half word */ ++ case 16: ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ emit(ctx, andi, lo(dst), lo(dst), 0xffff); ++ clobber_reg64(ctx, dst); ++ break; ++ } ++} ++ ++/* Load operation: dst = *(size*)(src + off) */ ++static void emit_ldx(struct jit_context *ctx, ++ const u8 dst[], u8 src, s16 off, u8 size) ++{ ++ switch (size) { ++ /* Load a byte */ ++ case BPF_B: ++ emit(ctx, lbu, lo(dst), off, src); ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ break; ++ /* Load a half word */ ++ case BPF_H: ++ emit(ctx, lhu, lo(dst), off, src); ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ break; ++ /* Load a word */ ++ case BPF_W: ++ emit(ctx, lw, lo(dst), off, src); ++ emit(ctx, move, hi(dst), MIPS_R_ZERO); ++ break; ++ /* Load a double word */ ++ case BPF_DW: ++ if (dst[1] == src) { ++ emit(ctx, lw, dst[0], off + 4, src); ++ emit(ctx, lw, dst[1], off, src); ++ } else { ++ emit(ctx, lw, dst[1], off, src); ++ emit(ctx, lw, dst[0], off + 4, src); ++ } ++ emit_load_delay(ctx); ++ break; ++ } ++ clobber_reg64(ctx, dst); ++} ++ ++/* Store operation: *(size *)(dst + off) = src */ ++static void emit_stx(struct jit_context *ctx, ++ const u8 dst, const u8 src[], s16 off, u8 size) ++{ ++ switch (size) { ++ /* Store a byte */ ++ case BPF_B: ++ emit(ctx, sb, lo(src), off, dst); ++ break; ++ /* Store a half word */ ++ case BPF_H: ++ emit(ctx, sh, lo(src), off, dst); ++ break; ++ /* Store a word */ ++ case BPF_W: ++ emit(ctx, sw, lo(src), off, dst); ++ break; ++ /* Store a double word */ ++ case BPF_DW: ++ emit(ctx, sw, src[1], off, dst); ++ emit(ctx, sw, src[0], off + 4, dst); ++ break; ++ } ++} ++ ++/* Atomic read-modify-write (32-bit, non-ll/sc fallback) */ ++static void emit_atomic_r32(struct jit_context *ctx, ++ u8 dst, u8 src, s16 off, u8 code) ++{ ++ u32 exclude = 0; ++ u32 addr = 0; ++ ++ /* Push caller-saved registers on stack */ ++ push_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, ++ 0, JIT_RESERVED_STACK); ++ /* ++ * Argument 1: dst+off if xchg, otherwise src, passed in register a0 ++ * Argument 2: src if xchg, othersize dst+off, passed in register a1 ++ */ ++ emit(ctx, move, MIPS_R_T9, dst); ++ emit(ctx, move, MIPS_R_A0, src); ++ emit(ctx, addiu, MIPS_R_A1, MIPS_R_T9, off); ++ ++ /* Emit function call */ ++ switch (code) { ++ case BPF_ADD: ++ addr = (u32)&atomic_add; ++ break; ++ case BPF_SUB: ++ addr = (u32)&atomic_sub; ++ break; ++ case BPF_OR: ++ addr = (u32)&atomic_or; ++ break; ++ case BPF_AND: ++ addr = (u32)&atomic_and; ++ break; ++ case BPF_XOR: ++ addr = (u32)&atomic_xor; ++ break; ++ } ++ emit_mov_i(ctx, MIPS_R_T9, addr); ++ emit(ctx, jalr, MIPS_R_RA, MIPS_R_T9); ++ emit(ctx, nop); /* Delay slot */ ++ ++ /* Restore caller-saved registers, except any fetched value */ ++ pop_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, ++ exclude, JIT_RESERVED_STACK); ++ emit_load_delay(ctx); ++ clobber_reg(ctx, MIPS_R_RA); ++} ++ ++/* Atomic read-modify-write (64-bit) */ ++static void emit_atomic_r64(struct jit_context *ctx, ++ u8 dst, const u8 src[], s16 off, u8 code) ++{ ++ const u8 *r1 = bpf2mips32[BPF_REG_1]; /* Mapped to a0-a1 */ ++ u32 exclude = 0; ++ u32 addr = 0; ++ ++ /* Push caller-saved registers on stack */ ++ push_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, ++ 0, JIT_RESERVED_STACK); ++ /* ++ * Argument 1: 64-bit src, passed in registers a0-a1 ++ * Argument 2: 32-bit dst+off, passed in register a2 ++ */ ++ emit(ctx, move, MIPS_R_T9, dst); ++ emit(ctx, move, r1[0], src[0]); ++ emit(ctx, move, r1[1], src[1]); ++ emit(ctx, addiu, MIPS_R_A2, MIPS_R_T9, off); ++ ++ /* Emit function call */ ++ switch (code) { ++ case BPF_ADD: ++ addr = (u32)&atomic64_add; ++ break; ++ case BPF_SUB: ++ addr = (u32)&atomic64_sub; ++ break; ++ case BPF_OR: ++ addr = (u32)&atomic64_or; ++ break; ++ case BPF_AND: ++ addr = (u32)&atomic64_and; ++ break; ++ case BPF_XOR: ++ addr = (u32)&atomic64_xor; ++ break; ++ } ++ emit_mov_i(ctx, MIPS_R_T9, addr); ++ emit(ctx, jalr, MIPS_R_RA, MIPS_R_T9); ++ emit(ctx, nop); /* Delay slot */ ++ ++ /* Restore caller-saved registers, except any fetched value */ ++ pop_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, ++ exclude, JIT_RESERVED_STACK); ++ emit_load_delay(ctx); ++ clobber_reg(ctx, MIPS_R_RA); ++} ++ ++/* ++ * Conditional movz or an emulated equivalent. ++ * Note that the rs register may be modified. ++ */ ++static void emit_movz_r(struct jit_context *ctx, u8 rd, u8 rs, u8 rt) ++{ ++ if (cpu_has_mips_2) { ++ emit(ctx, movz, rd, rs, rt); /* rd = rt ? rd : rs */ ++ } else if (cpu_has_mips32r6) { ++ if (rs != MIPS_R_ZERO) ++ emit(ctx, seleqz, rs, rs, rt); /* rs = 0 if rt == 0 */ ++ emit(ctx, selnez, rd, rd, rt); /* rd = 0 if rt != 0 */ ++ if (rs != MIPS_R_ZERO) ++ emit(ctx, or, rd, rd, rs); /* rd = rd | rs */ ++ } else { ++ emit(ctx, bnez, rt, 8); /* PC += 8 if rd != 0 */ ++ emit(ctx, nop); /* +0: delay slot */ ++ emit(ctx, or, rd, rs, MIPS_R_ZERO); /* +4: rd = rs */ ++ } ++ clobber_reg(ctx, rd); ++ clobber_reg(ctx, rs); ++} ++ ++/* ++ * Conditional movn or an emulated equivalent. ++ * Note that the rs register may be modified. ++ */ ++static void emit_movn_r(struct jit_context *ctx, u8 rd, u8 rs, u8 rt) ++{ ++ if (cpu_has_mips_2) { ++ emit(ctx, movn, rd, rs, rt); /* rd = rt ? rs : rd */ ++ } else if (cpu_has_mips32r6) { ++ if (rs != MIPS_R_ZERO) ++ emit(ctx, selnez, rs, rs, rt); /* rs = 0 if rt == 0 */ ++ emit(ctx, seleqz, rd, rd, rt); /* rd = 0 if rt != 0 */ ++ if (rs != MIPS_R_ZERO) ++ emit(ctx, or, rd, rd, rs); /* rd = rd | rs */ ++ } else { ++ emit(ctx, beqz, rt, 8); /* PC += 8 if rd == 0 */ ++ emit(ctx, nop); /* +0: delay slot */ ++ emit(ctx, or, rd, rs, MIPS_R_ZERO); /* +4: rd = rs */ ++ } ++ clobber_reg(ctx, rd); ++ clobber_reg(ctx, rs); ++} ++ ++/* Emulation of 64-bit sltiu rd, rs, imm, where imm may be S32_MAX + 1 */ ++static void emit_sltiu_r64(struct jit_context *ctx, u8 rd, ++ const u8 rs[], s64 imm) ++{ ++ u8 tmp = MIPS_R_T9; ++ ++ if (imm < 0) { ++ emit_mov_i(ctx, rd, imm); /* rd = imm */ ++ emit(ctx, sltu, rd, lo(rs), rd); /* rd = rsl < rd */ ++ emit(ctx, sltiu, tmp, hi(rs), -1); /* tmp = rsh < ~0U */ ++ emit(ctx, or, rd, rd, tmp); /* rd = rd | tmp */ ++ } else { /* imm >= 0 */ ++ if (imm > 0x7fff) { ++ emit_mov_i(ctx, rd, (s32)imm); /* rd = imm */ ++ emit(ctx, sltu, rd, lo(rs), rd); /* rd = rsl < rd */ ++ } else { ++ emit(ctx, sltiu, rd, lo(rs), imm); /* rd = rsl < imm */ ++ } ++ emit_movn_r(ctx, rd, MIPS_R_ZERO, hi(rs)); /* rd = 0 if rsh */ ++ } ++} ++ ++/* Emulation of 64-bit sltu rd, rs, rt */ ++static void emit_sltu_r64(struct jit_context *ctx, u8 rd, ++ const u8 rs[], const u8 rt[]) ++{ ++ u8 tmp = MIPS_R_T9; ++ ++ emit(ctx, sltu, rd, lo(rs), lo(rt)); /* rd = rsl < rtl */ ++ emit(ctx, subu, tmp, hi(rs), hi(rt)); /* tmp = rsh - rth */ ++ emit_movn_r(ctx, rd, MIPS_R_ZERO, tmp); /* rd = 0 if tmp != 0 */ ++ emit(ctx, sltu, tmp, hi(rs), hi(rt)); /* tmp = rsh < rth */ ++ emit(ctx, or, rd, rd, tmp); /* rd = rd | tmp */ ++} ++ ++/* Emulation of 64-bit slti rd, rs, imm, where imm may be S32_MAX + 1 */ ++static void emit_slti_r64(struct jit_context *ctx, u8 rd, ++ const u8 rs[], s64 imm) ++{ ++ u8 t1 = MIPS_R_T8; ++ u8 t2 = MIPS_R_T9; ++ u8 cmp; ++ ++ /* ++ * if ((rs < 0) ^ (imm < 0)) t1 = imm >u rsl ++ * else t1 = rsl > 31 */ ++ if (imm < 0) ++ emit_movz_r(ctx, t1, t2, rd); /* t1 = rd ? t1 : t2 */ ++ else ++ emit_movn_r(ctx, t1, t2, rd); /* t1 = rd ? t2 : t1 */ ++ /* ++ * if ((imm < 0 && rsh != 0xffffffff) || ++ * (imm >= 0 && rsh != 0)) ++ * t1 = 0 ++ */ ++ if (imm < 0) { ++ emit(ctx, addiu, rd, hi(rs), 1); /* rd = rsh + 1 */ ++ cmp = rd; ++ } else { /* imm >= 0 */ ++ cmp = hi(rs); ++ } ++ emit_movn_r(ctx, t1, MIPS_R_ZERO, cmp); /* t1 = 0 if cmp != 0 */ ++ ++ /* ++ * if (imm < 0) rd = rsh < -1 ++ * else rd = rsh != 0 ++ * rd = rd | t1 ++ */ ++ emit(ctx, slti, rd, hi(rs), imm < 0 ? -1 : 0); /* rd = rsh < hi(imm) */ ++ emit(ctx, or, rd, rd, t1); /* rd = rd | t1 */ ++} ++ ++/* Emulation of 64-bit(slt rd, rs, rt) */ ++static void emit_slt_r64(struct jit_context *ctx, u8 rd, ++ const u8 rs[], const u8 rt[]) ++{ ++ u8 t1 = MIPS_R_T7; ++ u8 t2 = MIPS_R_T8; ++ u8 t3 = MIPS_R_T9; ++ ++ /* ++ * if ((rs < 0) ^ (rt < 0)) t1 = rtl > 31 */ ++ emit_movn_r(ctx, t1, t2, rd); /* t1 = rd ? t2 : t1 */ ++ emit_movn_r(ctx, t1, MIPS_R_ZERO, t3); /* t1 = 0 if t3 != 0 */ ++ ++ /* rd = (rsh < rth) | t1 */ ++ emit(ctx, slt, rd, hi(rs), hi(rt)); /* rd = rsh = -0x7fff && imm <= 0x8000) { ++ emit(ctx, addiu, tmp, lo(dst), -imm); ++ } else if ((u32)imm <= 0xffff) { ++ emit(ctx, xori, tmp, lo(dst), imm); ++ } else { /* Register fallback */ ++ emit_mov_i(ctx, tmp, imm); ++ emit(ctx, xor, tmp, lo(dst), tmp); ++ } ++ if (imm < 0) { /* Compare sign extension */ ++ emit(ctx, addu, MIPS_R_T9, hi(dst), 1); ++ emit(ctx, or, tmp, tmp, MIPS_R_T9); ++ } else { /* Compare zero extension */ ++ emit(ctx, or, tmp, tmp, hi(dst)); ++ } ++ if (op == BPF_JEQ) ++ emit(ctx, beqz, tmp, off); ++ else /* BPF_JNE */ ++ emit(ctx, bnez, tmp, off); ++ break; ++ /* PC += off if dst & imm */ ++ /* PC += off if (dst & imm) == 0 (not in BPF, used for long jumps) */ ++ case BPF_JSET: ++ case JIT_JNSET: ++ if ((u32)imm <= 0xffff) { ++ emit(ctx, andi, tmp, lo(dst), imm); ++ } else { /* Register fallback */ ++ emit_mov_i(ctx, tmp, imm); ++ emit(ctx, and, tmp, lo(dst), tmp); ++ } ++ if (imm < 0) /* Sign-extension pulls in high word */ ++ emit(ctx, or, tmp, tmp, hi(dst)); ++ if (op == BPF_JSET) ++ emit(ctx, bnez, tmp, off); ++ else /* JIT_JNSET */ ++ emit(ctx, beqz, tmp, off); ++ break; ++ /* PC += off if dst > imm */ ++ case BPF_JGT: ++ emit_sltiu_r64(ctx, tmp, dst, (s64)imm + 1); ++ emit(ctx, beqz, tmp, off); ++ break; ++ /* PC += off if dst >= imm */ ++ case BPF_JGE: ++ emit_sltiu_r64(ctx, tmp, dst, imm); ++ emit(ctx, beqz, tmp, off); ++ break; ++ /* PC += off if dst < imm */ ++ case BPF_JLT: ++ emit_sltiu_r64(ctx, tmp, dst, imm); ++ emit(ctx, bnez, tmp, off); ++ break; ++ /* PC += off if dst <= imm */ ++ case BPF_JLE: ++ emit_sltiu_r64(ctx, tmp, dst, (s64)imm + 1); ++ emit(ctx, bnez, tmp, off); ++ break; ++ /* PC += off if dst > imm (signed) */ ++ case BPF_JSGT: ++ emit_slti_r64(ctx, tmp, dst, (s64)imm + 1); ++ emit(ctx, beqz, tmp, off); ++ break; ++ /* PC += off if dst >= imm (signed) */ ++ case BPF_JSGE: ++ emit_slti_r64(ctx, tmp, dst, imm); ++ emit(ctx, beqz, tmp, off); ++ break; ++ /* PC += off if dst < imm (signed) */ ++ case BPF_JSLT: ++ emit_slti_r64(ctx, tmp, dst, imm); ++ emit(ctx, bnez, tmp, off); ++ break; ++ /* PC += off if dst <= imm (signed) */ ++ case BPF_JSLE: ++ emit_slti_r64(ctx, tmp, dst, (s64)imm + 1); ++ emit(ctx, bnez, tmp, off); ++ break; ++ } ++} ++ ++/* Jump register (64-bit) */ ++static void emit_jmp_r64(struct jit_context *ctx, ++ const u8 dst[], const u8 src[], s32 off, u8 op) ++{ ++ u8 t1 = MIPS_R_T6; ++ u8 t2 = MIPS_R_T7; ++ ++ switch (op) { ++ /* No-op, used internally for branch optimization */ ++ case JIT_JNOP: ++ break; ++ /* PC += off if dst == src */ ++ /* PC += off if dst != src */ ++ case BPF_JEQ: ++ case BPF_JNE: ++ emit(ctx, subu, t1, lo(dst), lo(src)); ++ emit(ctx, subu, t2, hi(dst), hi(src)); ++ emit(ctx, or, t1, t1, t2); ++ if (op == BPF_JEQ) ++ emit(ctx, beqz, t1, off); ++ else /* BPF_JNE */ ++ emit(ctx, bnez, t1, off); ++ break; ++ /* PC += off if dst & src */ ++ /* PC += off if (dst & imm) == 0 (not in BPF, used for long jumps) */ ++ case BPF_JSET: ++ case JIT_JNSET: ++ emit(ctx, and, t1, lo(dst), lo(src)); ++ emit(ctx, and, t2, hi(dst), hi(src)); ++ emit(ctx, or, t1, t1, t2); ++ if (op == BPF_JSET) ++ emit(ctx, bnez, t1, off); ++ else /* JIT_JNSET */ ++ emit(ctx, beqz, t1, off); ++ break; ++ /* PC += off if dst > src */ ++ case BPF_JGT: ++ emit_sltu_r64(ctx, t1, src, dst); ++ emit(ctx, bnez, t1, off); ++ break; ++ /* PC += off if dst >= src */ ++ case BPF_JGE: ++ emit_sltu_r64(ctx, t1, dst, src); ++ emit(ctx, beqz, t1, off); ++ break; ++ /* PC += off if dst < src */ ++ case BPF_JLT: ++ emit_sltu_r64(ctx, t1, dst, src); ++ emit(ctx, bnez, t1, off); ++ break; ++ /* PC += off if dst <= src */ ++ case BPF_JLE: ++ emit_sltu_r64(ctx, t1, src, dst); ++ emit(ctx, beqz, t1, off); ++ break; ++ /* PC += off if dst > src (signed) */ ++ case BPF_JSGT: ++ emit_slt_r64(ctx, t1, src, dst); ++ emit(ctx, bnez, t1, off); ++ break; ++ /* PC += off if dst >= src (signed) */ ++ case BPF_JSGE: ++ emit_slt_r64(ctx, t1, dst, src); ++ emit(ctx, beqz, t1, off); ++ break; ++ /* PC += off if dst < src (signed) */ ++ case BPF_JSLT: ++ emit_slt_r64(ctx, t1, dst, src); ++ emit(ctx, bnez, t1, off); ++ break; ++ /* PC += off if dst <= src (signed) */ ++ case BPF_JSLE: ++ emit_slt_r64(ctx, t1, src, dst); ++ emit(ctx, beqz, t1, off); ++ break; ++ } ++} ++ ++/* Function call */ ++static int emit_call(struct jit_context *ctx, const struct bpf_insn *insn) ++{ ++ bool fixed; ++ u64 addr; ++ ++ /* Decode the call address */ ++ if (bpf_jit_get_func_addr(ctx->program, insn, false, ++ &addr, &fixed) < 0) ++ return -1; ++ if (!fixed) ++ return -1; ++ ++ /* Push stack arguments */ ++ push_regs(ctx, JIT_STACK_REGS, 0, JIT_RESERVED_STACK); ++ ++ /* Emit function call */ ++ emit_mov_i(ctx, MIPS_R_T9, addr); ++ emit(ctx, jalr, MIPS_R_RA, MIPS_R_T9); ++ emit(ctx, nop); /* Delay slot */ ++ ++ clobber_reg(ctx, MIPS_R_RA); ++ clobber_reg(ctx, MIPS_R_V0); ++ clobber_reg(ctx, MIPS_R_V1); ++ return 0; ++} ++ ++/* Function tail call */ ++static int emit_tail_call(struct jit_context *ctx) ++{ ++ u8 ary = lo(bpf2mips32[BPF_REG_2]); ++ u8 ind = lo(bpf2mips32[BPF_REG_3]); ++ u8 t1 = MIPS_R_T8; ++ u8 t2 = MIPS_R_T9; ++ int off; ++ ++ /* ++ * Tail call: ++ * eBPF R1 - function argument (context ptr), passed in a0-a1 ++ * eBPF R2 - ptr to object with array of function entry points ++ * eBPF R3 - array index of function to be called ++ * stack[sz] - remaining tail call count, initialized in prologue ++ */ ++ ++ /* if (ind >= ary->map.max_entries) goto out */ ++ off = offsetof(struct bpf_array, map.max_entries); ++ if (off > 0x7fff) ++ return -1; ++ emit(ctx, lw, t1, off, ary); /* t1 = ary->map.max_entries*/ ++ emit_load_delay(ctx); /* Load delay slot */ ++ emit(ctx, sltu, t1, ind, t1); /* t1 = ind < t1 */ ++ emit(ctx, beqz, t1, get_offset(ctx, 1)); /* PC += off(1) if t1 == 0 */ ++ /* (next insn delay slot) */ ++ /* if (TCC-- <= 0) goto out */ ++ emit(ctx, lw, t2, ctx->stack_size, MIPS_R_SP); /* t2 = *(SP + size) */ ++ emit_load_delay(ctx); /* Load delay slot */ ++ emit(ctx, blez, t2, get_offset(ctx, 1)); /* PC += off(1) if t2 < 0 */ ++ emit(ctx, addiu, t2, t2, -1); /* t2-- (delay slot) */ ++ emit(ctx, sw, t2, ctx->stack_size, MIPS_R_SP); /* *(SP + size) = t2 */ ++ ++ /* prog = ary->ptrs[ind] */ ++ off = offsetof(struct bpf_array, ptrs); ++ if (off > 0x7fff) ++ return -1; ++ emit(ctx, sll, t1, ind, 2); /* t1 = ind << 2 */ ++ emit(ctx, addu, t1, t1, ary); /* t1 += ary */ ++ emit(ctx, lw, t2, off, t1); /* t2 = *(t1 + off) */ ++ emit_load_delay(ctx); /* Load delay slot */ ++ ++ /* if (prog == 0) goto out */ ++ emit(ctx, beqz, t2, get_offset(ctx, 1)); /* PC += off(1) if t2 == 0 */ ++ emit(ctx, nop); /* Delay slot */ ++ ++ /* func = prog->bpf_func + 8 (prologue skip offset) */ ++ off = offsetof(struct bpf_prog, bpf_func); ++ if (off > 0x7fff) ++ return -1; ++ emit(ctx, lw, t1, off, t2); /* t1 = *(t2 + off) */ ++ emit_load_delay(ctx); /* Load delay slot */ ++ emit(ctx, addiu, t1, t1, JIT_TCALL_SKIP); /* t1 += skip (8 or 12) */ ++ ++ /* goto func */ ++ build_epilogue(ctx, t1); ++ return 0; ++} ++ ++/* ++ * Stack frame layout for a JITed program (stack grows down). ++ * ++ * Higher address : Caller's stack frame : ++ * :----------------------------: ++ * : 64-bit eBPF args r3-r5 : ++ * :----------------------------: ++ * : Reserved / tail call count : ++ * +============================+ <--- MIPS sp before call ++ * | Callee-saved registers, | ++ * | including RA and FP | ++ * +----------------------------+ <--- eBPF FP (MIPS zero,fp) ++ * | Local eBPF variables | ++ * | allocated by program | ++ * +----------------------------+ ++ * | Reserved for caller-saved | ++ * | registers | ++ * +----------------------------+ ++ * | Reserved for 64-bit eBPF | ++ * | args r3-r5 & args passed | ++ * | on stack in kernel calls | ++ * Lower address +============================+ <--- MIPS sp ++ */ ++ ++/* Build program prologue to set up the stack and registers */ ++void build_prologue(struct jit_context *ctx) ++{ ++ const u8 *r1 = bpf2mips32[BPF_REG_1]; ++ const u8 *fp = bpf2mips32[BPF_REG_FP]; ++ int stack, saved, locals, reserved; ++ ++ /* ++ * The first two instructions initialize TCC in the reserved (for us) ++ * 16-byte area in the parent's stack frame. On a tail call, the ++ * calling function jumps into the prologue after these instructions. ++ */ ++ emit(ctx, ori, MIPS_R_T9, MIPS_R_ZERO, ++ min(MAX_TAIL_CALL_CNT + 1, 0xffff)); ++ emit(ctx, sw, MIPS_R_T9, 0, MIPS_R_SP); ++ ++ /* ++ * Register eBPF R1 contains the 32-bit context pointer argument. ++ * A 32-bit argument is always passed in MIPS register a0, regardless ++ * of CPU endianness. Initialize R1 accordingly and zero-extend. ++ */ ++#ifdef __BIG_ENDIAN ++ emit(ctx, move, lo(r1), MIPS_R_A0); ++#endif ++ ++ /* === Entry-point for tail calls === */ ++ ++ /* Zero-extend the 32-bit argument */ ++ emit(ctx, move, hi(r1), MIPS_R_ZERO); ++ ++ /* If the eBPF frame pointer was accessed it must be saved */ ++ if (ctx->accessed & BIT(BPF_REG_FP)) ++ clobber_reg64(ctx, fp); ++ ++ /* Compute the stack space needed for callee-saved registers */ ++ saved = hweight32(ctx->clobbered & JIT_CALLEE_REGS) * sizeof(u32); ++ saved = ALIGN(saved, MIPS_STACK_ALIGNMENT); ++ ++ /* Stack space used by eBPF program local data */ ++ locals = ALIGN(ctx->program->aux->stack_depth, MIPS_STACK_ALIGNMENT); ++ ++ /* ++ * If we are emitting function calls, reserve extra stack space for ++ * caller-saved registers and function arguments passed on the stack. ++ * The required space is computed automatically during resource ++ * usage discovery (pass 1). ++ */ ++ reserved = ctx->stack_used; ++ ++ /* Allocate the stack frame */ ++ stack = ALIGN(saved + locals + reserved, MIPS_STACK_ALIGNMENT); ++ emit(ctx, addiu, MIPS_R_SP, MIPS_R_SP, -stack); ++ ++ /* Store callee-saved registers on stack */ ++ push_regs(ctx, ctx->clobbered & JIT_CALLEE_REGS, 0, stack - saved); ++ ++ /* Initialize the eBPF frame pointer if accessed */ ++ if (ctx->accessed & BIT(BPF_REG_FP)) ++ emit(ctx, addiu, lo(fp), MIPS_R_SP, stack - saved); ++ ++ ctx->saved_size = saved; ++ ctx->stack_size = stack; ++} ++ ++/* Build the program epilogue to restore the stack and registers */ ++void build_epilogue(struct jit_context *ctx, int dest_reg) ++{ ++ /* Restore callee-saved registers from stack */ ++ pop_regs(ctx, ctx->clobbered & JIT_CALLEE_REGS, 0, ++ ctx->stack_size - ctx->saved_size); ++ /* ++ * A 32-bit return value is always passed in MIPS register v0, ++ * but on big-endian targets the low part of R0 is mapped to v1. ++ */ ++#ifdef __BIG_ENDIAN ++ emit(ctx, move, MIPS_R_V0, MIPS_R_V1); ++#endif ++ ++ /* Jump to the return address and adjust the stack pointer */ ++ emit(ctx, jr, dest_reg); ++ emit(ctx, addiu, MIPS_R_SP, MIPS_R_SP, ctx->stack_size); ++} ++ ++/* Build one eBPF instruction */ ++int build_insn(const struct bpf_insn *insn, struct jit_context *ctx) ++{ ++ const u8 *dst = bpf2mips32[insn->dst_reg]; ++ const u8 *src = bpf2mips32[insn->src_reg]; ++ const u8 *tmp = bpf2mips32[JIT_REG_TMP]; ++ u8 code = insn->code; ++ s16 off = insn->off; ++ s32 imm = insn->imm; ++ s32 val, rel; ++ u8 alu, jmp; ++ ++ switch (code) { ++ /* ALU operations */ ++ /* dst = imm */ ++ case BPF_ALU | BPF_MOV | BPF_K: ++ emit_mov_i(ctx, lo(dst), imm); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = src */ ++ case BPF_ALU | BPF_MOV | BPF_X: ++ if (imm == 1) { ++ /* Special mov32 for zext */ ++ emit_mov_i(ctx, hi(dst), 0); ++ } else { ++ emit_mov_r(ctx, lo(dst), lo(src)); ++ emit_zext_ver(ctx, dst); ++ } ++ break; ++ /* dst = -dst */ ++ case BPF_ALU | BPF_NEG: ++ emit_alu_i(ctx, lo(dst), 0, BPF_NEG); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = dst & imm */ ++ /* dst = dst | imm */ ++ /* dst = dst ^ imm */ ++ /* dst = dst << imm */ ++ /* dst = dst >> imm */ ++ /* dst = dst >> imm (arithmetic) */ ++ /* dst = dst + imm */ ++ /* dst = dst - imm */ ++ /* dst = dst * imm */ ++ /* dst = dst / imm */ ++ /* dst = dst % imm */ ++ case BPF_ALU | BPF_OR | BPF_K: ++ case BPF_ALU | BPF_AND | BPF_K: ++ case BPF_ALU | BPF_XOR | BPF_K: ++ case BPF_ALU | BPF_LSH | BPF_K: ++ case BPF_ALU | BPF_RSH | BPF_K: ++ case BPF_ALU | BPF_ARSH | BPF_K: ++ case BPF_ALU | BPF_ADD | BPF_K: ++ case BPF_ALU | BPF_SUB | BPF_K: ++ case BPF_ALU | BPF_MUL | BPF_K: ++ case BPF_ALU | BPF_DIV | BPF_K: ++ case BPF_ALU | BPF_MOD | BPF_K: ++ if (!valid_alu_i(BPF_OP(code), imm)) { ++ emit_mov_i(ctx, MIPS_R_T6, imm); ++ emit_alu_r(ctx, lo(dst), MIPS_R_T6, BPF_OP(code)); ++ } else if (rewrite_alu_i(BPF_OP(code), imm, &alu, &val)) { ++ emit_alu_i(ctx, lo(dst), val, alu); ++ } ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = dst & src */ ++ /* dst = dst | src */ ++ /* dst = dst ^ src */ ++ /* dst = dst << src */ ++ /* dst = dst >> src */ ++ /* dst = dst >> src (arithmetic) */ ++ /* dst = dst + src */ ++ /* dst = dst - src */ ++ /* dst = dst * src */ ++ /* dst = dst / src */ ++ /* dst = dst % src */ ++ case BPF_ALU | BPF_AND | BPF_X: ++ case BPF_ALU | BPF_OR | BPF_X: ++ case BPF_ALU | BPF_XOR | BPF_X: ++ case BPF_ALU | BPF_LSH | BPF_X: ++ case BPF_ALU | BPF_RSH | BPF_X: ++ case BPF_ALU | BPF_ARSH | BPF_X: ++ case BPF_ALU | BPF_ADD | BPF_X: ++ case BPF_ALU | BPF_SUB | BPF_X: ++ case BPF_ALU | BPF_MUL | BPF_X: ++ case BPF_ALU | BPF_DIV | BPF_X: ++ case BPF_ALU | BPF_MOD | BPF_X: ++ emit_alu_r(ctx, lo(dst), lo(src), BPF_OP(code)); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = imm (64-bit) */ ++ case BPF_ALU64 | BPF_MOV | BPF_K: ++ emit_mov_se_i64(ctx, dst, imm); ++ break; ++ /* dst = src (64-bit) */ ++ case BPF_ALU64 | BPF_MOV | BPF_X: ++ emit_mov_r(ctx, lo(dst), lo(src)); ++ emit_mov_r(ctx, hi(dst), hi(src)); ++ break; ++ /* dst = -dst (64-bit) */ ++ case BPF_ALU64 | BPF_NEG: ++ emit_neg_i64(ctx, dst); ++ break; ++ /* dst = dst & imm (64-bit) */ ++ case BPF_ALU64 | BPF_AND | BPF_K: ++ emit_alu_i64(ctx, dst, imm, BPF_OP(code)); ++ break; ++ /* dst = dst | imm (64-bit) */ ++ /* dst = dst ^ imm (64-bit) */ ++ /* dst = dst + imm (64-bit) */ ++ /* dst = dst - imm (64-bit) */ ++ case BPF_ALU64 | BPF_OR | BPF_K: ++ case BPF_ALU64 | BPF_XOR | BPF_K: ++ case BPF_ALU64 | BPF_ADD | BPF_K: ++ case BPF_ALU64 | BPF_SUB | BPF_K: ++ if (imm) ++ emit_alu_i64(ctx, dst, imm, BPF_OP(code)); ++ break; ++ /* dst = dst << imm (64-bit) */ ++ /* dst = dst >> imm (64-bit) */ ++ /* dst = dst >> imm (64-bit, arithmetic) */ ++ case BPF_ALU64 | BPF_LSH | BPF_K: ++ case BPF_ALU64 | BPF_RSH | BPF_K: ++ case BPF_ALU64 | BPF_ARSH | BPF_K: ++ if (imm) ++ emit_shift_i64(ctx, dst, imm, BPF_OP(code)); ++ break; ++ /* dst = dst * imm (64-bit) */ ++ case BPF_ALU64 | BPF_MUL | BPF_K: ++ emit_mul_i64(ctx, dst, imm); ++ break; ++ /* dst = dst / imm (64-bit) */ ++ /* dst = dst % imm (64-bit) */ ++ case BPF_ALU64 | BPF_DIV | BPF_K: ++ case BPF_ALU64 | BPF_MOD | BPF_K: ++ /* ++ * Sign-extend the immediate value into a temporary register, ++ * and then do the operation on this register. ++ */ ++ emit_mov_se_i64(ctx, tmp, imm); ++ emit_divmod_r64(ctx, dst, tmp, BPF_OP(code)); ++ break; ++ /* dst = dst & src (64-bit) */ ++ /* dst = dst | src (64-bit) */ ++ /* dst = dst ^ src (64-bit) */ ++ /* dst = dst + src (64-bit) */ ++ /* dst = dst - src (64-bit) */ ++ case BPF_ALU64 | BPF_AND | BPF_X: ++ case BPF_ALU64 | BPF_OR | BPF_X: ++ case BPF_ALU64 | BPF_XOR | BPF_X: ++ case BPF_ALU64 | BPF_ADD | BPF_X: ++ case BPF_ALU64 | BPF_SUB | BPF_X: ++ emit_alu_r64(ctx, dst, src, BPF_OP(code)); ++ break; ++ /* dst = dst << src (64-bit) */ ++ /* dst = dst >> src (64-bit) */ ++ /* dst = dst >> src (64-bit, arithmetic) */ ++ case BPF_ALU64 | BPF_LSH | BPF_X: ++ case BPF_ALU64 | BPF_RSH | BPF_X: ++ case BPF_ALU64 | BPF_ARSH | BPF_X: ++ emit_shift_r64(ctx, dst, lo(src), BPF_OP(code)); ++ break; ++ /* dst = dst * src (64-bit) */ ++ case BPF_ALU64 | BPF_MUL | BPF_X: ++ emit_mul_r64(ctx, dst, src); ++ break; ++ /* dst = dst / src (64-bit) */ ++ /* dst = dst % src (64-bit) */ ++ case BPF_ALU64 | BPF_DIV | BPF_X: ++ case BPF_ALU64 | BPF_MOD | BPF_X: ++ emit_divmod_r64(ctx, dst, src, BPF_OP(code)); ++ break; ++ /* dst = htole(dst) */ ++ /* dst = htobe(dst) */ ++ case BPF_ALU | BPF_END | BPF_FROM_LE: ++ case BPF_ALU | BPF_END | BPF_FROM_BE: ++ if (BPF_SRC(code) == ++#ifdef __BIG_ENDIAN ++ BPF_FROM_LE ++#else ++ BPF_FROM_BE ++#endif ++ ) ++ emit_bswap_r64(ctx, dst, imm); ++ else ++ emit_trunc_r64(ctx, dst, imm); ++ break; ++ /* dst = imm64 */ ++ case BPF_LD | BPF_IMM | BPF_DW: ++ emit_mov_i(ctx, lo(dst), imm); ++ emit_mov_i(ctx, hi(dst), insn[1].imm); ++ return 1; ++ /* LDX: dst = *(size *)(src + off) */ ++ case BPF_LDX | BPF_MEM | BPF_W: ++ case BPF_LDX | BPF_MEM | BPF_H: ++ case BPF_LDX | BPF_MEM | BPF_B: ++ case BPF_LDX | BPF_MEM | BPF_DW: ++ emit_ldx(ctx, dst, lo(src), off, BPF_SIZE(code)); ++ break; ++ /* ST: *(size *)(dst + off) = imm */ ++ case BPF_ST | BPF_MEM | BPF_W: ++ case BPF_ST | BPF_MEM | BPF_H: ++ case BPF_ST | BPF_MEM | BPF_B: ++ case BPF_ST | BPF_MEM | BPF_DW: ++ switch (BPF_SIZE(code)) { ++ case BPF_DW: ++ /* Sign-extend immediate value into temporary reg */ ++ emit_mov_se_i64(ctx, tmp, imm); ++ break; ++ case BPF_W: ++ case BPF_H: ++ case BPF_B: ++ emit_mov_i(ctx, lo(tmp), imm); ++ break; ++ } ++ emit_stx(ctx, lo(dst), tmp, off, BPF_SIZE(code)); ++ break; ++ /* STX: *(size *)(dst + off) = src */ ++ case BPF_STX | BPF_MEM | BPF_W: ++ case BPF_STX | BPF_MEM | BPF_H: ++ case BPF_STX | BPF_MEM | BPF_B: ++ case BPF_STX | BPF_MEM | BPF_DW: ++ emit_stx(ctx, lo(dst), src, off, BPF_SIZE(code)); ++ break; ++ /* Speculation barrier */ ++ case BPF_ST | BPF_NOSPEC: ++ break; ++ /* Atomics */ ++ case BPF_STX | BPF_XADD | BPF_W: ++ switch (imm) { ++ case BPF_ADD: ++ case BPF_AND: ++ case BPF_OR: ++ case BPF_XOR: ++ if (cpu_has_llsc) ++ emit_atomic_r(ctx, lo(dst), lo(src), off, imm); ++ else /* Non-ll/sc fallback */ ++ emit_atomic_r32(ctx, lo(dst), lo(src), ++ off, imm); ++ break; ++ default: ++ goto notyet; ++ } ++ break; ++ /* Atomics (64-bit) */ ++ case BPF_STX | BPF_XADD | BPF_DW: ++ switch (imm) { ++ case BPF_ADD: ++ case BPF_AND: ++ case BPF_OR: ++ case BPF_XOR: ++ emit_atomic_r64(ctx, lo(dst), src, off, imm); ++ break; ++ default: ++ goto notyet; ++ } ++ break; ++ /* PC += off if dst == src */ ++ /* PC += off if dst != src */ ++ /* PC += off if dst & src */ ++ /* PC += off if dst > src */ ++ /* PC += off if dst >= src */ ++ /* PC += off if dst < src */ ++ /* PC += off if dst <= src */ ++ /* PC += off if dst > src (signed) */ ++ /* PC += off if dst >= src (signed) */ ++ /* PC += off if dst < src (signed) */ ++ /* PC += off if dst <= src (signed) */ ++ case BPF_JMP32 | BPF_JEQ | BPF_X: ++ case BPF_JMP32 | BPF_JNE | BPF_X: ++ case BPF_JMP32 | BPF_JSET | BPF_X: ++ case BPF_JMP32 | BPF_JGT | BPF_X: ++ case BPF_JMP32 | BPF_JGE | BPF_X: ++ case BPF_JMP32 | BPF_JLT | BPF_X: ++ case BPF_JMP32 | BPF_JLE | BPF_X: ++ case BPF_JMP32 | BPF_JSGT | BPF_X: ++ case BPF_JMP32 | BPF_JSGE | BPF_X: ++ case BPF_JMP32 | BPF_JSLT | BPF_X: ++ case BPF_JMP32 | BPF_JSLE | BPF_X: ++ if (off == 0) ++ break; ++ setup_jmp_r(ctx, dst == src, BPF_OP(code), off, &jmp, &rel); ++ emit_jmp_r(ctx, lo(dst), lo(src), rel, jmp); ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off if dst == imm */ ++ /* PC += off if dst != imm */ ++ /* PC += off if dst & imm */ ++ /* PC += off if dst > imm */ ++ /* PC += off if dst >= imm */ ++ /* PC += off if dst < imm */ ++ /* PC += off if dst <= imm */ ++ /* PC += off if dst > imm (signed) */ ++ /* PC += off if dst >= imm (signed) */ ++ /* PC += off if dst < imm (signed) */ ++ /* PC += off if dst <= imm (signed) */ ++ case BPF_JMP32 | BPF_JEQ | BPF_K: ++ case BPF_JMP32 | BPF_JNE | BPF_K: ++ case BPF_JMP32 | BPF_JSET | BPF_K: ++ case BPF_JMP32 | BPF_JGT | BPF_K: ++ case BPF_JMP32 | BPF_JGE | BPF_K: ++ case BPF_JMP32 | BPF_JLT | BPF_K: ++ case BPF_JMP32 | BPF_JLE | BPF_K: ++ case BPF_JMP32 | BPF_JSGT | BPF_K: ++ case BPF_JMP32 | BPF_JSGE | BPF_K: ++ case BPF_JMP32 | BPF_JSLT | BPF_K: ++ case BPF_JMP32 | BPF_JSLE | BPF_K: ++ if (off == 0) ++ break; ++ setup_jmp_i(ctx, imm, 32, BPF_OP(code), off, &jmp, &rel); ++ if (valid_jmp_i(jmp, imm)) { ++ emit_jmp_i(ctx, lo(dst), imm, rel, jmp); ++ } else { ++ /* Move large immediate to register */ ++ emit_mov_i(ctx, MIPS_R_T6, imm); ++ emit_jmp_r(ctx, lo(dst), MIPS_R_T6, rel, jmp); ++ } ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off if dst == src */ ++ /* PC += off if dst != src */ ++ /* PC += off if dst & src */ ++ /* PC += off if dst > src */ ++ /* PC += off if dst >= src */ ++ /* PC += off if dst < src */ ++ /* PC += off if dst <= src */ ++ /* PC += off if dst > src (signed) */ ++ /* PC += off if dst >= src (signed) */ ++ /* PC += off if dst < src (signed) */ ++ /* PC += off if dst <= src (signed) */ ++ case BPF_JMP | BPF_JEQ | BPF_X: ++ case BPF_JMP | BPF_JNE | BPF_X: ++ case BPF_JMP | BPF_JSET | BPF_X: ++ case BPF_JMP | BPF_JGT | BPF_X: ++ case BPF_JMP | BPF_JGE | BPF_X: ++ case BPF_JMP | BPF_JLT | BPF_X: ++ case BPF_JMP | BPF_JLE | BPF_X: ++ case BPF_JMP | BPF_JSGT | BPF_X: ++ case BPF_JMP | BPF_JSGE | BPF_X: ++ case BPF_JMP | BPF_JSLT | BPF_X: ++ case BPF_JMP | BPF_JSLE | BPF_X: ++ if (off == 0) ++ break; ++ setup_jmp_r(ctx, dst == src, BPF_OP(code), off, &jmp, &rel); ++ emit_jmp_r64(ctx, dst, src, rel, jmp); ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off if dst == imm */ ++ /* PC += off if dst != imm */ ++ /* PC += off if dst & imm */ ++ /* PC += off if dst > imm */ ++ /* PC += off if dst >= imm */ ++ /* PC += off if dst < imm */ ++ /* PC += off if dst <= imm */ ++ /* PC += off if dst > imm (signed) */ ++ /* PC += off if dst >= imm (signed) */ ++ /* PC += off if dst < imm (signed) */ ++ /* PC += off if dst <= imm (signed) */ ++ case BPF_JMP | BPF_JEQ | BPF_K: ++ case BPF_JMP | BPF_JNE | BPF_K: ++ case BPF_JMP | BPF_JSET | BPF_K: ++ case BPF_JMP | BPF_JGT | BPF_K: ++ case BPF_JMP | BPF_JGE | BPF_K: ++ case BPF_JMP | BPF_JLT | BPF_K: ++ case BPF_JMP | BPF_JLE | BPF_K: ++ case BPF_JMP | BPF_JSGT | BPF_K: ++ case BPF_JMP | BPF_JSGE | BPF_K: ++ case BPF_JMP | BPF_JSLT | BPF_K: ++ case BPF_JMP | BPF_JSLE | BPF_K: ++ if (off == 0) ++ break; ++ setup_jmp_i(ctx, imm, 64, BPF_OP(code), off, &jmp, &rel); ++ emit_jmp_i64(ctx, dst, imm, rel, jmp); ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off */ ++ case BPF_JMP | BPF_JA: ++ if (off == 0) ++ break; ++ if (emit_ja(ctx, off) < 0) ++ goto toofar; ++ break; ++ /* Tail call */ ++ case BPF_JMP | BPF_TAIL_CALL: ++ if (emit_tail_call(ctx) < 0) ++ goto invalid; ++ break; ++ /* Function call */ ++ case BPF_JMP | BPF_CALL: ++ if (emit_call(ctx, insn) < 0) ++ goto invalid; ++ break; ++ /* Function return */ ++ case BPF_JMP | BPF_EXIT: ++ /* ++ * Optimization: when last instruction is EXIT ++ * simply continue to epilogue. ++ */ ++ if (ctx->bpf_index == ctx->program->len - 1) ++ break; ++ if (emit_exit(ctx) < 0) ++ goto toofar; ++ break; ++ ++ default: ++invalid: ++ pr_err_once("unknown opcode %02x\n", code); ++ return -EINVAL; ++notyet: ++ pr_info_once("*** NOT YET: opcode %02x ***\n", code); ++ return -EFAULT; ++toofar: ++ pr_info_once("*** TOO FAR: jump at %u opcode %02x ***\n", ++ ctx->bpf_index, code); ++ return -E2BIG; ++ } ++ return 0; ++} diff --git a/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch b/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch new file mode 100644 index 0000000000..38b46c0b76 --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-03-mips-bpf-Add-new-eBPF-JIT-for-64-bit-MIPS.patch @@ -0,0 +1,1005 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:05 +0200 +Subject: [PATCH] mips: bpf: Add new eBPF JIT for 64-bit MIPS + +This is an implementation on of an eBPF JIT for 64-bit MIPS III-V and +MIPS64r1-r6. It uses the same framework introduced by the 32-bit JIT. + +Signed-off-by: Johan Almbladh +--- + create mode 100644 arch/mips/net/bpf_jit_comp64.c + +--- /dev/null ++++ b/arch/mips/net/bpf_jit_comp64.c +@@ -0,0 +1,991 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Just-In-Time compiler for eBPF bytecode on MIPS. ++ * Implementation of JIT functions for 64-bit CPUs. ++ * ++ * Copyright (c) 2021 Anyfi Networks AB. ++ * Author: Johan Almbladh ++ * ++ * Based on code and ideas from ++ * Copyright (c) 2017 Cavium, Inc. ++ * Copyright (c) 2017 Shubham Bansal ++ * Copyright (c) 2011 Mircea Gherzan ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bpf_jit_comp.h" ++ ++/* MIPS t0-t3 are not available in the n64 ABI */ ++#undef MIPS_R_T0 ++#undef MIPS_R_T1 ++#undef MIPS_R_T2 ++#undef MIPS_R_T3 ++ ++/* Stack is 16-byte aligned in n64 ABI */ ++#define MIPS_STACK_ALIGNMENT 16 ++ ++/* Extra 64-bit eBPF registers used by JIT */ ++#define JIT_REG_TC (MAX_BPF_JIT_REG + 0) ++#define JIT_REG_ZX (MAX_BPF_JIT_REG + 1) ++ ++/* Number of prologue bytes to skip when doing a tail call */ ++#define JIT_TCALL_SKIP 4 ++ ++/* Callee-saved CPU registers that the JIT must preserve */ ++#define JIT_CALLEE_REGS \ ++ (BIT(MIPS_R_S0) | \ ++ BIT(MIPS_R_S1) | \ ++ BIT(MIPS_R_S2) | \ ++ BIT(MIPS_R_S3) | \ ++ BIT(MIPS_R_S4) | \ ++ BIT(MIPS_R_S5) | \ ++ BIT(MIPS_R_S6) | \ ++ BIT(MIPS_R_S7) | \ ++ BIT(MIPS_R_GP) | \ ++ BIT(MIPS_R_FP) | \ ++ BIT(MIPS_R_RA)) ++ ++/* Caller-saved CPU registers available for JIT use */ ++#define JIT_CALLER_REGS \ ++ (BIT(MIPS_R_A5) | \ ++ BIT(MIPS_R_A6) | \ ++ BIT(MIPS_R_A7)) ++/* ++ * Mapping of 64-bit eBPF registers to 64-bit native MIPS registers. ++ * MIPS registers t4 - t7 may be used by the JIT as temporary registers. ++ * MIPS registers t8 - t9 are reserved for single-register common functions. ++ */ ++static const u8 bpf2mips64[] = { ++ /* Return value from in-kernel function, and exit value from eBPF */ ++ [BPF_REG_0] = MIPS_R_V0, ++ /* Arguments from eBPF program to in-kernel function */ ++ [BPF_REG_1] = MIPS_R_A0, ++ [BPF_REG_2] = MIPS_R_A1, ++ [BPF_REG_3] = MIPS_R_A2, ++ [BPF_REG_4] = MIPS_R_A3, ++ [BPF_REG_5] = MIPS_R_A4, ++ /* Callee-saved registers that in-kernel function will preserve */ ++ [BPF_REG_6] = MIPS_R_S0, ++ [BPF_REG_7] = MIPS_R_S1, ++ [BPF_REG_8] = MIPS_R_S2, ++ [BPF_REG_9] = MIPS_R_S3, ++ /* Read-only frame pointer to access the eBPF stack */ ++ [BPF_REG_FP] = MIPS_R_FP, ++ /* Temporary register for blinding constants */ ++ [BPF_REG_AX] = MIPS_R_AT, ++ /* Tail call count register, caller-saved */ ++ [JIT_REG_TC] = MIPS_R_A5, ++ /* Constant for register zero-extension */ ++ [JIT_REG_ZX] = MIPS_R_V1, ++}; ++ ++/* ++ * MIPS 32-bit operations on 64-bit registers generate a sign-extended ++ * result. However, the eBPF ISA mandates zero-extension, so we rely on the ++ * verifier to add that for us (emit_zext_ver). In addition, ALU arithmetic ++ * operations, right shift and byte swap require properly sign-extended ++ * operands or the result is unpredictable. We emit explicit sign-extensions ++ * in those cases. ++ */ ++ ++/* Sign extension */ ++static void emit_sext(struct jit_context *ctx, u8 dst, u8 src) ++{ ++ emit(ctx, sll, dst, src, 0); ++ clobber_reg(ctx, dst); ++} ++ ++/* Zero extension */ ++static void emit_zext(struct jit_context *ctx, u8 dst) ++{ ++ if (cpu_has_mips64r2 || cpu_has_mips64r6) { ++ emit(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32); ++ } else { ++ emit(ctx, and, dst, dst, bpf2mips64[JIT_REG_ZX]); ++ access_reg(ctx, JIT_REG_ZX); /* We need the ZX register */ ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Zero extension, if verifier does not do it for us */ ++static void emit_zext_ver(struct jit_context *ctx, u8 dst) ++{ ++ if (!ctx->program->aux->verifier_zext) ++ emit_zext(ctx, dst); ++} ++ ++/* dst = imm (64-bit) */ ++static void emit_mov_i64(struct jit_context *ctx, u8 dst, u64 imm64) ++{ ++ if (imm64 >= 0xffffffffffff8000ULL || imm64 < 0x8000ULL) { ++ emit(ctx, daddiu, dst, MIPS_R_ZERO, (s16)imm64); ++ } else if (imm64 >= 0xffffffff80000000ULL || ++ (imm64 < 0x80000000 && imm64 > 0xffff)) { ++ emit(ctx, lui, dst, (s16)(imm64 >> 16)); ++ emit(ctx, ori, dst, dst, (u16)imm64 & 0xffff); ++ } else { ++ u8 acc = MIPS_R_ZERO; ++ int k; ++ ++ for (k = 0; k < 4; k++) { ++ u16 half = imm64 >> (48 - 16 * k); ++ ++ if (acc == dst) ++ emit(ctx, dsll, dst, dst, 16); ++ ++ if (half) { ++ emit(ctx, ori, dst, acc, half); ++ acc = dst; ++ } ++ } ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* ALU immediate operation (64-bit) */ ++static void emit_alu_i64(struct jit_context *ctx, u8 dst, s32 imm, u8 op) ++{ ++ switch (BPF_OP(op)) { ++ /* dst = dst | imm */ ++ case BPF_OR: ++ emit(ctx, ori, dst, dst, (u16)imm); ++ break; ++ /* dst = dst ^ imm */ ++ case BPF_XOR: ++ emit(ctx, xori, dst, dst, (u16)imm); ++ break; ++ /* dst = -dst */ ++ case BPF_NEG: ++ emit(ctx, dsubu, dst, MIPS_R_ZERO, dst); ++ break; ++ /* dst = dst << imm */ ++ case BPF_LSH: ++ emit(ctx, dsll_safe, dst, dst, imm); ++ break; ++ /* dst = dst >> imm */ ++ case BPF_RSH: ++ emit(ctx, dsrl_safe, dst, dst, imm); ++ break; ++ /* dst = dst >> imm (arithmetic) */ ++ case BPF_ARSH: ++ emit(ctx, dsra_safe, dst, dst, imm); ++ break; ++ /* dst = dst + imm */ ++ case BPF_ADD: ++ emit(ctx, daddiu, dst, dst, imm); ++ break; ++ /* dst = dst - imm */ ++ case BPF_SUB: ++ emit(ctx, daddiu, dst, dst, -imm); ++ break; ++ default: ++ /* Width-generic operations */ ++ emit_alu_i(ctx, dst, imm, op); ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* ALU register operation (64-bit) */ ++static void emit_alu_r64(struct jit_context *ctx, u8 dst, u8 src, u8 op) ++{ ++ switch (BPF_OP(op)) { ++ /* dst = dst << src */ ++ case BPF_LSH: ++ emit(ctx, dsllv, dst, dst, src); ++ break; ++ /* dst = dst >> src */ ++ case BPF_RSH: ++ emit(ctx, dsrlv, dst, dst, src); ++ break; ++ /* dst = dst >> src (arithmetic) */ ++ case BPF_ARSH: ++ emit(ctx, dsrav, dst, dst, src); ++ break; ++ /* dst = dst + src */ ++ case BPF_ADD: ++ emit(ctx, daddu, dst, dst, src); ++ break; ++ /* dst = dst - src */ ++ case BPF_SUB: ++ emit(ctx, dsubu, dst, dst, src); ++ break; ++ /* dst = dst * src */ ++ case BPF_MUL: ++ if (cpu_has_mips64r6) { ++ emit(ctx, dmulu, dst, dst, src); ++ } else { ++ emit(ctx, dmultu, dst, src); ++ emit(ctx, mflo, dst); ++ } ++ break; ++ /* dst = dst / src */ ++ case BPF_DIV: ++ if (cpu_has_mips64r6) { ++ emit(ctx, ddivu_r6, dst, dst, src); ++ } else { ++ emit(ctx, ddivu, dst, src); ++ emit(ctx, mflo, dst); ++ } ++ break; ++ /* dst = dst % src */ ++ case BPF_MOD: ++ if (cpu_has_mips64r6) { ++ emit(ctx, dmodu, dst, dst, src); ++ } else { ++ emit(ctx, ddivu, dst, src); ++ emit(ctx, mfhi, dst); ++ } ++ break; ++ default: ++ /* Width-generic operations */ ++ emit_alu_r(ctx, dst, src, op); ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Swap sub words in a register double word */ ++static void emit_swap_r64(struct jit_context *ctx, u8 dst, u8 mask, u32 bits) ++{ ++ u8 tmp = MIPS_R_T9; ++ ++ emit(ctx, and, tmp, dst, mask); /* tmp = dst & mask */ ++ emit(ctx, dsll, tmp, tmp, bits); /* tmp = tmp << bits */ ++ emit(ctx, dsrl, dst, dst, bits); /* dst = dst >> bits */ ++ emit(ctx, and, dst, dst, mask); /* dst = dst & mask */ ++ emit(ctx, or, dst, dst, tmp); /* dst = dst | tmp */ ++} ++ ++/* Swap bytes and truncate a register double word, word or half word */ ++static void emit_bswap_r64(struct jit_context *ctx, u8 dst, u32 width) ++{ ++ switch (width) { ++ /* Swap bytes in a double word */ ++ case 64: ++ if (cpu_has_mips64r2 || cpu_has_mips64r6) { ++ emit(ctx, dsbh, dst, dst); ++ emit(ctx, dshd, dst, dst); ++ } else { ++ u8 t1 = MIPS_R_T6; ++ u8 t2 = MIPS_R_T7; ++ ++ emit(ctx, dsll32, t2, dst, 0); /* t2 = dst << 32 */ ++ emit(ctx, dsrl32, dst, dst, 0); /* dst = dst >> 32 */ ++ emit(ctx, or, dst, dst, t2); /* dst = dst | t2 */ ++ ++ emit(ctx, ori, t2, MIPS_R_ZERO, 0xffff); ++ emit(ctx, dsll32, t1, t2, 0); /* t1 = t2 << 32 */ ++ emit(ctx, or, t1, t1, t2); /* t1 = t1 | t2 */ ++ emit_swap_r64(ctx, dst, t1, 16);/* dst = swap16(dst) */ ++ ++ emit(ctx, lui, t2, 0xff); /* t2 = 0x00ff0000 */ ++ emit(ctx, ori, t2, t2, 0xff); /* t2 = t2 | 0x00ff */ ++ emit(ctx, dsll32, t1, t2, 0); /* t1 = t2 << 32 */ ++ emit(ctx, or, t1, t1, t2); /* t1 = t1 | t2 */ ++ emit_swap_r64(ctx, dst, t1, 8); /* dst = swap8(dst) */ ++ } ++ break; ++ /* Swap bytes in a half word */ ++ /* Swap bytes in a word */ ++ case 32: ++ case 16: ++ emit_sext(ctx, dst, dst); ++ emit_bswap_r(ctx, dst, width); ++ if (cpu_has_mips64r2 || cpu_has_mips64r6) ++ emit_zext(ctx, dst); ++ break; ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Truncate a register double word, word or half word */ ++static void emit_trunc_r64(struct jit_context *ctx, u8 dst, u32 width) ++{ ++ switch (width) { ++ case 64: ++ break; ++ /* Zero-extend a word */ ++ case 32: ++ emit_zext(ctx, dst); ++ break; ++ /* Zero-extend a half word */ ++ case 16: ++ emit(ctx, andi, dst, dst, 0xffff); ++ break; ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Load operation: dst = *(size*)(src + off) */ ++static void emit_ldx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size) ++{ ++ switch (size) { ++ /* Load a byte */ ++ case BPF_B: ++ emit(ctx, lbu, dst, off, src); ++ break; ++ /* Load a half word */ ++ case BPF_H: ++ emit(ctx, lhu, dst, off, src); ++ break; ++ /* Load a word */ ++ case BPF_W: ++ emit(ctx, lwu, dst, off, src); ++ break; ++ /* Load a double word */ ++ case BPF_DW: ++ emit(ctx, ld, dst, off, src); ++ break; ++ } ++ clobber_reg(ctx, dst); ++} ++ ++/* Store operation: *(size *)(dst + off) = src */ ++static void emit_stx(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 size) ++{ ++ switch (size) { ++ /* Store a byte */ ++ case BPF_B: ++ emit(ctx, sb, src, off, dst); ++ break; ++ /* Store a half word */ ++ case BPF_H: ++ emit(ctx, sh, src, off, dst); ++ break; ++ /* Store a word */ ++ case BPF_W: ++ emit(ctx, sw, src, off, dst); ++ break; ++ /* Store a double word */ ++ case BPF_DW: ++ emit(ctx, sd, src, off, dst); ++ break; ++ } ++} ++ ++/* Atomic read-modify-write */ ++static void emit_atomic_r64(struct jit_context *ctx, ++ u8 dst, u8 src, s16 off, u8 code) ++{ ++ u8 t1 = MIPS_R_T6; ++ u8 t2 = MIPS_R_T7; ++ ++ emit(ctx, lld, t1, off, dst); ++ switch (code) { ++ case BPF_ADD: ++ emit(ctx, daddu, t2, t1, src); ++ break; ++ case BPF_AND: ++ emit(ctx, and, t2, t1, src); ++ break; ++ case BPF_OR: ++ emit(ctx, or, t2, t1, src); ++ break; ++ case BPF_XOR: ++ emit(ctx, xor, t2, t1, src); ++ break; ++ } ++ emit(ctx, scd, t2, off, dst); ++ emit(ctx, beqz, t2, -16); ++ emit(ctx, nop); /* Delay slot */ ++} ++ ++/* Function call */ ++static int emit_call(struct jit_context *ctx, const struct bpf_insn *insn) ++{ ++ u8 zx = bpf2mips64[JIT_REG_ZX]; ++ u8 tmp = MIPS_R_T6; ++ bool fixed; ++ u64 addr; ++ ++ /* Decode the call address */ ++ if (bpf_jit_get_func_addr(ctx->program, insn, false, ++ &addr, &fixed) < 0) ++ return -1; ++ if (!fixed) ++ return -1; ++ ++ /* Push caller-saved registers on stack */ ++ push_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, 0, 0); ++ ++ /* Emit function call */ ++ emit_mov_i64(ctx, tmp, addr); ++ emit(ctx, jalr, MIPS_R_RA, tmp); ++ emit(ctx, nop); /* Delay slot */ ++ ++ /* Restore caller-saved registers */ ++ pop_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, 0, 0); ++ ++ /* Re-initialize the JIT zero-extension register if accessed */ ++ if (ctx->accessed & BIT(JIT_REG_ZX)) { ++ emit(ctx, daddiu, zx, MIPS_R_ZERO, -1); ++ emit(ctx, dsrl32, zx, zx, 0); ++ } ++ ++ clobber_reg(ctx, MIPS_R_RA); ++ clobber_reg(ctx, MIPS_R_V0); ++ clobber_reg(ctx, MIPS_R_V1); ++ return 0; ++} ++ ++/* Function tail call */ ++static int emit_tail_call(struct jit_context *ctx) ++{ ++ u8 ary = bpf2mips64[BPF_REG_2]; ++ u8 ind = bpf2mips64[BPF_REG_3]; ++ u8 tcc = bpf2mips64[JIT_REG_TC]; ++ u8 tmp = MIPS_R_T6; ++ int off; ++ ++ /* ++ * Tail call: ++ * eBPF R1 - function argument (context ptr), passed in a0-a1 ++ * eBPF R2 - ptr to object with array of function entry points ++ * eBPF R3 - array index of function to be called ++ */ ++ ++ /* if (ind >= ary->map.max_entries) goto out */ ++ off = offsetof(struct bpf_array, map.max_entries); ++ if (off > 0x7fff) ++ return -1; ++ emit(ctx, lwu, tmp, off, ary); /* tmp = ary->map.max_entrs*/ ++ emit(ctx, sltu, tmp, ind, tmp); /* tmp = ind < t1 */ ++ emit(ctx, beqz, tmp, get_offset(ctx, 1)); /* PC += off(1) if tmp == 0*/ ++ ++ /* if (--TCC < 0) goto out */ ++ emit(ctx, daddiu, tcc, tcc, -1); /* tcc-- (delay slot) */ ++ emit(ctx, bltz, tcc, get_offset(ctx, 1)); /* PC += off(1) if tcc < 0 */ ++ /* (next insn delay slot) */ ++ /* prog = ary->ptrs[ind] */ ++ off = offsetof(struct bpf_array, ptrs); ++ if (off > 0x7fff) ++ return -1; ++ emit(ctx, dsll, tmp, ind, 3); /* tmp = ind << 3 */ ++ emit(ctx, daddu, tmp, tmp, ary); /* tmp += ary */ ++ emit(ctx, ld, tmp, off, tmp); /* tmp = *(tmp + off) */ ++ ++ /* if (prog == 0) goto out */ ++ emit(ctx, beqz, tmp, get_offset(ctx, 1)); /* PC += off(1) if tmp == 0*/ ++ emit(ctx, nop); /* Delay slot */ ++ ++ /* func = prog->bpf_func + 8 (prologue skip offset) */ ++ off = offsetof(struct bpf_prog, bpf_func); ++ if (off > 0x7fff) ++ return -1; ++ emit(ctx, ld, tmp, off, tmp); /* tmp = *(tmp + off) */ ++ emit(ctx, daddiu, tmp, tmp, JIT_TCALL_SKIP); /* tmp += skip (4) */ ++ ++ /* goto func */ ++ build_epilogue(ctx, tmp); ++ access_reg(ctx, JIT_REG_TC); ++ return 0; ++} ++ ++/* ++ * Stack frame layout for a JITed program (stack grows down). ++ * ++ * Higher address : Previous stack frame : ++ * +===========================+ <--- MIPS sp before call ++ * | Callee-saved registers, | ++ * | including RA and FP | ++ * +---------------------------+ <--- eBPF FP (MIPS fp) ++ * | Local eBPF variables | ++ * | allocated by program | ++ * +---------------------------+ ++ * | Reserved for caller-saved | ++ * | registers | ++ * Lower address +===========================+ <--- MIPS sp ++ */ ++ ++/* Build program prologue to set up the stack and registers */ ++void build_prologue(struct jit_context *ctx) ++{ ++ u8 fp = bpf2mips64[BPF_REG_FP]; ++ u8 tc = bpf2mips64[JIT_REG_TC]; ++ u8 zx = bpf2mips64[JIT_REG_ZX]; ++ int stack, saved, locals, reserved; ++ ++ /* ++ * The first instruction initializes the tail call count register. ++ * On a tail call, the calling function jumps into the prologue ++ * after this instruction. ++ */ ++ emit(ctx, addiu, tc, MIPS_R_ZERO, min(MAX_TAIL_CALL_CNT + 1, 0xffff)); ++ ++ /* === Entry-point for tail calls === */ ++ ++ /* ++ * If the eBPF frame pointer and tail call count registers were ++ * accessed they must be preserved. Mark them as clobbered here ++ * to save and restore them on the stack as needed. ++ */ ++ if (ctx->accessed & BIT(BPF_REG_FP)) ++ clobber_reg(ctx, fp); ++ if (ctx->accessed & BIT(JIT_REG_TC)) ++ clobber_reg(ctx, tc); ++ if (ctx->accessed & BIT(JIT_REG_ZX)) ++ clobber_reg(ctx, zx); ++ ++ /* Compute the stack space needed for callee-saved registers */ ++ saved = hweight32(ctx->clobbered & JIT_CALLEE_REGS) * sizeof(u64); ++ saved = ALIGN(saved, MIPS_STACK_ALIGNMENT); ++ ++ /* Stack space used by eBPF program local data */ ++ locals = ALIGN(ctx->program->aux->stack_depth, MIPS_STACK_ALIGNMENT); ++ ++ /* ++ * If we are emitting function calls, reserve extra stack space for ++ * caller-saved registers needed by the JIT. The required space is ++ * computed automatically during resource usage discovery (pass 1). ++ */ ++ reserved = ctx->stack_used; ++ ++ /* Allocate the stack frame */ ++ stack = ALIGN(saved + locals + reserved, MIPS_STACK_ALIGNMENT); ++ if (stack) ++ emit(ctx, daddiu, MIPS_R_SP, MIPS_R_SP, -stack); ++ ++ /* Store callee-saved registers on stack */ ++ push_regs(ctx, ctx->clobbered & JIT_CALLEE_REGS, 0, stack - saved); ++ ++ /* Initialize the eBPF frame pointer if accessed */ ++ if (ctx->accessed & BIT(BPF_REG_FP)) ++ emit(ctx, daddiu, fp, MIPS_R_SP, stack - saved); ++ ++ /* Initialize the ePF JIT zero-extension register if accessed */ ++ if (ctx->accessed & BIT(JIT_REG_ZX)) { ++ emit(ctx, daddiu, zx, MIPS_R_ZERO, -1); ++ emit(ctx, dsrl32, zx, zx, 0); ++ } ++ ++ ctx->saved_size = saved; ++ ctx->stack_size = stack; ++} ++ ++/* Build the program epilogue to restore the stack and registers */ ++void build_epilogue(struct jit_context *ctx, int dest_reg) ++{ ++ /* Restore callee-saved registers from stack */ ++ pop_regs(ctx, ctx->clobbered & JIT_CALLEE_REGS, 0, ++ ctx->stack_size - ctx->saved_size); ++ ++ /* Release the stack frame */ ++ if (ctx->stack_size) ++ emit(ctx, daddiu, MIPS_R_SP, MIPS_R_SP, ctx->stack_size); ++ ++ /* Jump to return address and sign-extend the 32-bit return value */ ++ emit(ctx, jr, dest_reg); ++ emit(ctx, sll, MIPS_R_V0, MIPS_R_V0, 0); /* Delay slot */ ++} ++ ++/* Build one eBPF instruction */ ++int build_insn(const struct bpf_insn *insn, struct jit_context *ctx) ++{ ++ u8 dst = bpf2mips64[insn->dst_reg]; ++ u8 src = bpf2mips64[insn->src_reg]; ++ u8 code = insn->code; ++ s16 off = insn->off; ++ s32 imm = insn->imm; ++ s32 val, rel; ++ u8 alu, jmp; ++ ++ switch (code) { ++ /* ALU operations */ ++ /* dst = imm */ ++ case BPF_ALU | BPF_MOV | BPF_K: ++ emit_mov_i(ctx, dst, imm); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = src */ ++ case BPF_ALU | BPF_MOV | BPF_X: ++ if (imm == 1) { ++ /* Special mov32 for zext */ ++ emit_zext(ctx, dst); ++ } else { ++ emit_mov_r(ctx, dst, src); ++ emit_zext_ver(ctx, dst); ++ } ++ break; ++ /* dst = -dst */ ++ case BPF_ALU | BPF_NEG: ++ emit_sext(ctx, dst, dst); ++ emit_alu_i(ctx, dst, 0, BPF_NEG); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = dst & imm */ ++ /* dst = dst | imm */ ++ /* dst = dst ^ imm */ ++ /* dst = dst << imm */ ++ case BPF_ALU | BPF_OR | BPF_K: ++ case BPF_ALU | BPF_AND | BPF_K: ++ case BPF_ALU | BPF_XOR | BPF_K: ++ case BPF_ALU | BPF_LSH | BPF_K: ++ if (!valid_alu_i(BPF_OP(code), imm)) { ++ emit_mov_i(ctx, MIPS_R_T4, imm); ++ emit_alu_r(ctx, dst, MIPS_R_T4, BPF_OP(code)); ++ } else if (rewrite_alu_i(BPF_OP(code), imm, &alu, &val)) { ++ emit_alu_i(ctx, dst, val, alu); ++ } ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = dst >> imm */ ++ /* dst = dst >> imm (arithmetic) */ ++ /* dst = dst + imm */ ++ /* dst = dst - imm */ ++ /* dst = dst * imm */ ++ /* dst = dst / imm */ ++ /* dst = dst % imm */ ++ case BPF_ALU | BPF_RSH | BPF_K: ++ case BPF_ALU | BPF_ARSH | BPF_K: ++ case BPF_ALU | BPF_ADD | BPF_K: ++ case BPF_ALU | BPF_SUB | BPF_K: ++ case BPF_ALU | BPF_MUL | BPF_K: ++ case BPF_ALU | BPF_DIV | BPF_K: ++ case BPF_ALU | BPF_MOD | BPF_K: ++ if (!valid_alu_i(BPF_OP(code), imm)) { ++ emit_sext(ctx, dst, dst); ++ emit_mov_i(ctx, MIPS_R_T4, imm); ++ emit_alu_r(ctx, dst, MIPS_R_T4, BPF_OP(code)); ++ } else if (rewrite_alu_i(BPF_OP(code), imm, &alu, &val)) { ++ emit_sext(ctx, dst, dst); ++ emit_alu_i(ctx, dst, val, alu); ++ } ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = dst & src */ ++ /* dst = dst | src */ ++ /* dst = dst ^ src */ ++ /* dst = dst << src */ ++ case BPF_ALU | BPF_AND | BPF_X: ++ case BPF_ALU | BPF_OR | BPF_X: ++ case BPF_ALU | BPF_XOR | BPF_X: ++ case BPF_ALU | BPF_LSH | BPF_X: ++ emit_alu_r(ctx, dst, src, BPF_OP(code)); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = dst >> src */ ++ /* dst = dst >> src (arithmetic) */ ++ /* dst = dst + src */ ++ /* dst = dst - src */ ++ /* dst = dst * src */ ++ /* dst = dst / src */ ++ /* dst = dst % src */ ++ case BPF_ALU | BPF_RSH | BPF_X: ++ case BPF_ALU | BPF_ARSH | BPF_X: ++ case BPF_ALU | BPF_ADD | BPF_X: ++ case BPF_ALU | BPF_SUB | BPF_X: ++ case BPF_ALU | BPF_MUL | BPF_X: ++ case BPF_ALU | BPF_DIV | BPF_X: ++ case BPF_ALU | BPF_MOD | BPF_X: ++ emit_sext(ctx, dst, dst); ++ emit_sext(ctx, MIPS_R_T4, src); ++ emit_alu_r(ctx, dst, MIPS_R_T4, BPF_OP(code)); ++ emit_zext_ver(ctx, dst); ++ break; ++ /* dst = imm (64-bit) */ ++ case BPF_ALU64 | BPF_MOV | BPF_K: ++ emit_mov_i(ctx, dst, imm); ++ break; ++ /* dst = src (64-bit) */ ++ case BPF_ALU64 | BPF_MOV | BPF_X: ++ emit_mov_r(ctx, dst, src); ++ break; ++ /* dst = -dst (64-bit) */ ++ case BPF_ALU64 | BPF_NEG: ++ emit_alu_i64(ctx, dst, 0, BPF_NEG); ++ break; ++ /* dst = dst & imm (64-bit) */ ++ /* dst = dst | imm (64-bit) */ ++ /* dst = dst ^ imm (64-bit) */ ++ /* dst = dst << imm (64-bit) */ ++ /* dst = dst >> imm (64-bit) */ ++ /* dst = dst >> imm ((64-bit, arithmetic) */ ++ /* dst = dst + imm (64-bit) */ ++ /* dst = dst - imm (64-bit) */ ++ /* dst = dst * imm (64-bit) */ ++ /* dst = dst / imm (64-bit) */ ++ /* dst = dst % imm (64-bit) */ ++ case BPF_ALU64 | BPF_AND | BPF_K: ++ case BPF_ALU64 | BPF_OR | BPF_K: ++ case BPF_ALU64 | BPF_XOR | BPF_K: ++ case BPF_ALU64 | BPF_LSH | BPF_K: ++ case BPF_ALU64 | BPF_RSH | BPF_K: ++ case BPF_ALU64 | BPF_ARSH | BPF_K: ++ case BPF_ALU64 | BPF_ADD | BPF_K: ++ case BPF_ALU64 | BPF_SUB | BPF_K: ++ case BPF_ALU64 | BPF_MUL | BPF_K: ++ case BPF_ALU64 | BPF_DIV | BPF_K: ++ case BPF_ALU64 | BPF_MOD | BPF_K: ++ if (!valid_alu_i(BPF_OP(code), imm)) { ++ emit_mov_i(ctx, MIPS_R_T4, imm); ++ emit_alu_r64(ctx, dst, MIPS_R_T4, BPF_OP(code)); ++ } else if (rewrite_alu_i(BPF_OP(code), imm, &alu, &val)) { ++ emit_alu_i64(ctx, dst, val, alu); ++ } ++ break; ++ /* dst = dst & src (64-bit) */ ++ /* dst = dst | src (64-bit) */ ++ /* dst = dst ^ src (64-bit) */ ++ /* dst = dst << src (64-bit) */ ++ /* dst = dst >> src (64-bit) */ ++ /* dst = dst >> src (64-bit, arithmetic) */ ++ /* dst = dst + src (64-bit) */ ++ /* dst = dst - src (64-bit) */ ++ /* dst = dst * src (64-bit) */ ++ /* dst = dst / src (64-bit) */ ++ /* dst = dst % src (64-bit) */ ++ case BPF_ALU64 | BPF_AND | BPF_X: ++ case BPF_ALU64 | BPF_OR | BPF_X: ++ case BPF_ALU64 | BPF_XOR | BPF_X: ++ case BPF_ALU64 | BPF_LSH | BPF_X: ++ case BPF_ALU64 | BPF_RSH | BPF_X: ++ case BPF_ALU64 | BPF_ARSH | BPF_X: ++ case BPF_ALU64 | BPF_ADD | BPF_X: ++ case BPF_ALU64 | BPF_SUB | BPF_X: ++ case BPF_ALU64 | BPF_MUL | BPF_X: ++ case BPF_ALU64 | BPF_DIV | BPF_X: ++ case BPF_ALU64 | BPF_MOD | BPF_X: ++ emit_alu_r64(ctx, dst, src, BPF_OP(code)); ++ break; ++ /* dst = htole(dst) */ ++ /* dst = htobe(dst) */ ++ case BPF_ALU | BPF_END | BPF_FROM_LE: ++ case BPF_ALU | BPF_END | BPF_FROM_BE: ++ if (BPF_SRC(code) == ++#ifdef __BIG_ENDIAN ++ BPF_FROM_LE ++#else ++ BPF_FROM_BE ++#endif ++ ) ++ emit_bswap_r64(ctx, dst, imm); ++ else ++ emit_trunc_r64(ctx, dst, imm); ++ break; ++ /* dst = imm64 */ ++ case BPF_LD | BPF_IMM | BPF_DW: ++ emit_mov_i64(ctx, dst, (u32)imm | ((u64)insn[1].imm << 32)); ++ return 1; ++ /* LDX: dst = *(size *)(src + off) */ ++ case BPF_LDX | BPF_MEM | BPF_W: ++ case BPF_LDX | BPF_MEM | BPF_H: ++ case BPF_LDX | BPF_MEM | BPF_B: ++ case BPF_LDX | BPF_MEM | BPF_DW: ++ emit_ldx(ctx, dst, src, off, BPF_SIZE(code)); ++ break; ++ /* ST: *(size *)(dst + off) = imm */ ++ case BPF_ST | BPF_MEM | BPF_W: ++ case BPF_ST | BPF_MEM | BPF_H: ++ case BPF_ST | BPF_MEM | BPF_B: ++ case BPF_ST | BPF_MEM | BPF_DW: ++ emit_mov_i(ctx, MIPS_R_T4, imm); ++ emit_stx(ctx, dst, MIPS_R_T4, off, BPF_SIZE(code)); ++ break; ++ /* STX: *(size *)(dst + off) = src */ ++ case BPF_STX | BPF_MEM | BPF_W: ++ case BPF_STX | BPF_MEM | BPF_H: ++ case BPF_STX | BPF_MEM | BPF_B: ++ case BPF_STX | BPF_MEM | BPF_DW: ++ emit_stx(ctx, dst, src, off, BPF_SIZE(code)); ++ break; ++ /* Speculation barrier */ ++ case BPF_ST | BPF_NOSPEC: ++ break; ++ /* Atomics */ ++ case BPF_STX | BPF_XADD | BPF_W: ++ case BPF_STX | BPF_XADD | BPF_DW: ++ switch (imm) { ++ case BPF_ADD: ++ case BPF_AND: ++ case BPF_OR: ++ case BPF_XOR: ++ if (BPF_SIZE(code) == BPF_DW) { ++ emit_atomic_r64(ctx, dst, src, off, imm); ++ } else { /* 32-bit, no fetch */ ++ emit_sext(ctx, MIPS_R_T4, src); ++ emit_atomic_r(ctx, dst, MIPS_R_T4, off, imm); ++ } ++ break; ++ default: ++ goto notyet; ++ } ++ break; ++ /* PC += off if dst == src */ ++ /* PC += off if dst != src */ ++ /* PC += off if dst & src */ ++ /* PC += off if dst > src */ ++ /* PC += off if dst >= src */ ++ /* PC += off if dst < src */ ++ /* PC += off if dst <= src */ ++ /* PC += off if dst > src (signed) */ ++ /* PC += off if dst >= src (signed) */ ++ /* PC += off if dst < src (signed) */ ++ /* PC += off if dst <= src (signed) */ ++ case BPF_JMP32 | BPF_JEQ | BPF_X: ++ case BPF_JMP32 | BPF_JNE | BPF_X: ++ case BPF_JMP32 | BPF_JSET | BPF_X: ++ case BPF_JMP32 | BPF_JGT | BPF_X: ++ case BPF_JMP32 | BPF_JGE | BPF_X: ++ case BPF_JMP32 | BPF_JLT | BPF_X: ++ case BPF_JMP32 | BPF_JLE | BPF_X: ++ case BPF_JMP32 | BPF_JSGT | BPF_X: ++ case BPF_JMP32 | BPF_JSGE | BPF_X: ++ case BPF_JMP32 | BPF_JSLT | BPF_X: ++ case BPF_JMP32 | BPF_JSLE | BPF_X: ++ if (off == 0) ++ break; ++ setup_jmp_r(ctx, dst == src, BPF_OP(code), off, &jmp, &rel); ++ emit_sext(ctx, MIPS_R_T4, dst); /* Sign-extended dst */ ++ emit_sext(ctx, MIPS_R_T5, src); /* Sign-extended src */ ++ emit_jmp_r(ctx, MIPS_R_T4, MIPS_R_T5, rel, jmp); ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off if dst == imm */ ++ /* PC += off if dst != imm */ ++ /* PC += off if dst & imm */ ++ /* PC += off if dst > imm */ ++ /* PC += off if dst >= imm */ ++ /* PC += off if dst < imm */ ++ /* PC += off if dst <= imm */ ++ /* PC += off if dst > imm (signed) */ ++ /* PC += off if dst >= imm (signed) */ ++ /* PC += off if dst < imm (signed) */ ++ /* PC += off if dst <= imm (signed) */ ++ case BPF_JMP32 | BPF_JEQ | BPF_K: ++ case BPF_JMP32 | BPF_JNE | BPF_K: ++ case BPF_JMP32 | BPF_JSET | BPF_K: ++ case BPF_JMP32 | BPF_JGT | BPF_K: ++ case BPF_JMP32 | BPF_JGE | BPF_K: ++ case BPF_JMP32 | BPF_JLT | BPF_K: ++ case BPF_JMP32 | BPF_JLE | BPF_K: ++ case BPF_JMP32 | BPF_JSGT | BPF_K: ++ case BPF_JMP32 | BPF_JSGE | BPF_K: ++ case BPF_JMP32 | BPF_JSLT | BPF_K: ++ case BPF_JMP32 | BPF_JSLE | BPF_K: ++ if (off == 0) ++ break; ++ setup_jmp_i(ctx, imm, 32, BPF_OP(code), off, &jmp, &rel); ++ emit_sext(ctx, MIPS_R_T4, dst); /* Sign-extended dst */ ++ if (valid_jmp_i(jmp, imm)) { ++ emit_jmp_i(ctx, MIPS_R_T4, imm, rel, jmp); ++ } else { ++ /* Move large immediate to register, sign-extended */ ++ emit_mov_i(ctx, MIPS_R_T5, imm); ++ emit_jmp_r(ctx, MIPS_R_T4, MIPS_R_T5, rel, jmp); ++ } ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off if dst == src */ ++ /* PC += off if dst != src */ ++ /* PC += off if dst & src */ ++ /* PC += off if dst > src */ ++ /* PC += off if dst >= src */ ++ /* PC += off if dst < src */ ++ /* PC += off if dst <= src */ ++ /* PC += off if dst > src (signed) */ ++ /* PC += off if dst >= src (signed) */ ++ /* PC += off if dst < src (signed) */ ++ /* PC += off if dst <= src (signed) */ ++ case BPF_JMP | BPF_JEQ | BPF_X: ++ case BPF_JMP | BPF_JNE | BPF_X: ++ case BPF_JMP | BPF_JSET | BPF_X: ++ case BPF_JMP | BPF_JGT | BPF_X: ++ case BPF_JMP | BPF_JGE | BPF_X: ++ case BPF_JMP | BPF_JLT | BPF_X: ++ case BPF_JMP | BPF_JLE | BPF_X: ++ case BPF_JMP | BPF_JSGT | BPF_X: ++ case BPF_JMP | BPF_JSGE | BPF_X: ++ case BPF_JMP | BPF_JSLT | BPF_X: ++ case BPF_JMP | BPF_JSLE | BPF_X: ++ if (off == 0) ++ break; ++ setup_jmp_r(ctx, dst == src, BPF_OP(code), off, &jmp, &rel); ++ emit_jmp_r(ctx, dst, src, rel, jmp); ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off if dst == imm */ ++ /* PC += off if dst != imm */ ++ /* PC += off if dst & imm */ ++ /* PC += off if dst > imm */ ++ /* PC += off if dst >= imm */ ++ /* PC += off if dst < imm */ ++ /* PC += off if dst <= imm */ ++ /* PC += off if dst > imm (signed) */ ++ /* PC += off if dst >= imm (signed) */ ++ /* PC += off if dst < imm (signed) */ ++ /* PC += off if dst <= imm (signed) */ ++ case BPF_JMP | BPF_JEQ | BPF_K: ++ case BPF_JMP | BPF_JNE | BPF_K: ++ case BPF_JMP | BPF_JSET | BPF_K: ++ case BPF_JMP | BPF_JGT | BPF_K: ++ case BPF_JMP | BPF_JGE | BPF_K: ++ case BPF_JMP | BPF_JLT | BPF_K: ++ case BPF_JMP | BPF_JLE | BPF_K: ++ case BPF_JMP | BPF_JSGT | BPF_K: ++ case BPF_JMP | BPF_JSGE | BPF_K: ++ case BPF_JMP | BPF_JSLT | BPF_K: ++ case BPF_JMP | BPF_JSLE | BPF_K: ++ if (off == 0) ++ break; ++ setup_jmp_i(ctx, imm, 64, BPF_OP(code), off, &jmp, &rel); ++ if (valid_jmp_i(jmp, imm)) { ++ emit_jmp_i(ctx, dst, imm, rel, jmp); ++ } else { ++ /* Move large immediate to register */ ++ emit_mov_i(ctx, MIPS_R_T4, imm); ++ emit_jmp_r(ctx, dst, MIPS_R_T4, rel, jmp); ++ } ++ if (finish_jmp(ctx, jmp, off) < 0) ++ goto toofar; ++ break; ++ /* PC += off */ ++ case BPF_JMP | BPF_JA: ++ if (off == 0) ++ break; ++ if (emit_ja(ctx, off) < 0) ++ goto toofar; ++ break; ++ /* Tail call */ ++ case BPF_JMP | BPF_TAIL_CALL: ++ if (emit_tail_call(ctx) < 0) ++ goto invalid; ++ break; ++ /* Function call */ ++ case BPF_JMP | BPF_CALL: ++ if (emit_call(ctx, insn) < 0) ++ goto invalid; ++ break; ++ /* Function return */ ++ case BPF_JMP | BPF_EXIT: ++ /* ++ * Optimization: when last instruction is EXIT ++ * simply continue to epilogue. ++ */ ++ if (ctx->bpf_index == ctx->program->len - 1) ++ break; ++ if (emit_exit(ctx) < 0) ++ goto toofar; ++ break; ++ ++ default: ++invalid: ++ pr_err_once("unknown opcode %02x\n", code); ++ return -EINVAL; ++notyet: ++ pr_info_once("*** NOT YET: opcode %02x ***\n", code); ++ return -EFAULT; ++toofar: ++ pr_info_once("*** TOO FAR: jump at %u opcode %02x ***\n", ++ ctx->bpf_index, code); ++ return -E2BIG; ++ } ++ return 0; ++} diff --git a/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch b/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch new file mode 100644 index 0000000000..63553ebe58 --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-04-mips-bpf-Add-JIT-workarounds-for-CPU-errata.patch @@ -0,0 +1,120 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:06 +0200 +Subject: [PATCH] mips: bpf: Add JIT workarounds for CPU errata + +This patch adds workarounds for the following CPU errata to the MIPS +eBPF JIT, if enabled in the kernel configuration. + + - R10000 ll/sc weak ordering + - Loongson-3 ll/sc weak ordering + - Loongson-2F jump hang + +The Loongson-2F nop errata is implemented in uasm, which the JIT uses, +so no additional mitigations are needed for that. + +Signed-off-by: Johan Almbladh +Reviewed-by: Jiaxun Yang +--- + +--- a/arch/mips/net/bpf_jit_comp.c ++++ b/arch/mips/net/bpf_jit_comp.c +@@ -404,6 +404,7 @@ void emit_alu_r(struct jit_context *ctx, + /* Atomic read-modify-write (32-bit) */ + void emit_atomic_r(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 code) + { ++ LLSC_sync(ctx); + emit(ctx, ll, MIPS_R_T9, off, dst); + switch (code) { + case BPF_ADD: +@@ -420,18 +421,19 @@ void emit_atomic_r(struct jit_context *c + break; + } + emit(ctx, sc, MIPS_R_T8, off, dst); +- emit(ctx, beqz, MIPS_R_T8, -16); ++ emit(ctx, LLSC_beqz, MIPS_R_T8, -16 - LLSC_offset); + emit(ctx, nop); /* Delay slot */ + } + + /* Atomic compare-and-exchange (32-bit) */ + void emit_cmpxchg_r(struct jit_context *ctx, u8 dst, u8 src, u8 res, s16 off) + { ++ LLSC_sync(ctx); + emit(ctx, ll, MIPS_R_T9, off, dst); + emit(ctx, bne, MIPS_R_T9, res, 12); + emit(ctx, move, MIPS_R_T8, src); /* Delay slot */ + emit(ctx, sc, MIPS_R_T8, off, dst); +- emit(ctx, beqz, MIPS_R_T8, -20); ++ emit(ctx, LLSC_beqz, MIPS_R_T8, -20 - LLSC_offset); + emit(ctx, move, res, MIPS_R_T9); /* Delay slot */ + clobber_reg(ctx, res); + } +--- a/arch/mips/net/bpf_jit_comp.h ++++ b/arch/mips/net/bpf_jit_comp.h +@@ -87,7 +87,7 @@ struct jit_context { + }; + + /* Emit the instruction if the JIT memory space has been allocated */ +-#define emit(ctx, func, ...) \ ++#define __emit(ctx, func, ...) \ + do { \ + if ((ctx)->target != NULL) { \ + u32 *p = &(ctx)->target[ctx->jit_index]; \ +@@ -95,6 +95,30 @@ do { \ + } \ + (ctx)->jit_index++; \ + } while (0) ++#define emit(...) __emit(__VA_ARGS__) ++ ++/* Workaround for R10000 ll/sc errata */ ++#ifdef CONFIG_WAR_R10000 ++#define LLSC_beqz beqzl ++#else ++#define LLSC_beqz beqz ++#endif ++ ++/* Workaround for Loongson-3 ll/sc errata */ ++#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS ++#define LLSC_sync(ctx) emit(ctx, sync, 0) ++#define LLSC_offset 4 ++#else ++#define LLSC_sync(ctx) ++#define LLSC_offset 0 ++#endif ++ ++/* Workaround for Loongson-2F jump errata */ ++#ifdef CONFIG_CPU_JUMP_WORKAROUNDS ++#define JALR_MASK 0xffffffffcfffffffULL ++#else ++#define JALR_MASK (~0ULL) ++#endif + + /* + * Mark a BPF register as accessed, it needs to be +--- a/arch/mips/net/bpf_jit_comp64.c ++++ b/arch/mips/net/bpf_jit_comp64.c +@@ -375,6 +375,7 @@ static void emit_atomic_r64(struct jit_c + u8 t1 = MIPS_R_T6; + u8 t2 = MIPS_R_T7; + ++ LLSC_sync(ctx); + emit(ctx, lld, t1, off, dst); + switch (code) { + case BPF_ADD: +@@ -391,7 +392,7 @@ static void emit_atomic_r64(struct jit_c + break; + } + emit(ctx, scd, t2, off, dst); +- emit(ctx, beqz, t2, -16); ++ emit(ctx, LLSC_beqz, t2, -16 - LLSC_offset); + emit(ctx, nop); /* Delay slot */ + } + +@@ -414,7 +415,7 @@ static int emit_call(struct jit_context + push_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, 0, 0); + + /* Emit function call */ +- emit_mov_i64(ctx, tmp, addr); ++ emit_mov_i64(ctx, tmp, addr & JALR_MASK); + emit(ctx, jalr, MIPS_R_RA, tmp); + emit(ctx, nop); /* Delay slot */ + diff --git a/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch b/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch new file mode 100644 index 0000000000..10685c5f3c --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch @@ -0,0 +1,61 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:07 +0200 +Subject: [PATCH] mips: bpf: Enable eBPF JITs + +This patch enables the new eBPF JITs for 32-bit and 64-bit MIPS. It also +disables the old cBPF JIT to so cBPF programs are converted to use the +new JIT. + +Workarounds for R4000 CPU errata are not implemented by the JIT, so the +JIT is disabled if any of those workarounds are configured. + +Signed-off-by: Johan Almbladh +--- + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3294,6 +3294,7 @@ S: Supported + F: arch/arm64/net/ + + BPF JIT for MIPS (32-BIT AND 64-BIT) ++M: Johan Almbladh + M: Paul Burton + L: netdev@vger.kernel.org + L: bpf@vger.kernel.org +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -49,7 +49,6 @@ config MIPS + select HAVE_ARCH_TRACEHOOK + select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES + select HAVE_ASM_MODVERSIONS +- select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS + select HAVE_CONTEXT_TRACKING + select HAVE_TIF_NOHZ + select HAVE_C_RECORDMCOUNT +@@ -57,7 +56,10 @@ config MIPS + select HAVE_DEBUG_STACKOVERFLOW + select HAVE_DMA_CONTIGUOUS + select HAVE_DYNAMIC_FTRACE +- select HAVE_EBPF_JIT if 64BIT && !CPU_MICROMIPS && TARGET_ISA_REV >= 2 ++ select HAVE_EBPF_JIT if !CPU_MICROMIPS && \ ++ !CPU_DADDI_WORKAROUNDS && \ ++ !CPU_R4000_WORKAROUNDS && \ ++ !CPU_R4400_WORKAROUNDS + select HAVE_EXIT_THREAD + select HAVE_FAST_GUP + select HAVE_FTRACE_MCOUNT_RECORD +--- a/arch/mips/net/Makefile ++++ b/arch/mips/net/Makefile +@@ -2,9 +2,10 @@ + # MIPS networking code + + obj-$(CONFIG_MIPS_CBPF_JIT) += bpf_jit.o bpf_jit_asm.o ++obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp.o + + ifeq ($(CONFIG_32BIT),y) +- obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp.o bpf_jit_comp32.o ++ obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp32.o + else +- obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o ++ obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp64.o + endif diff --git a/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch b/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch new file mode 100644 index 0000000000..e25c336831 --- /dev/null +++ b/target/linux/generic/backport-5.15/050-v5.16-06-mips-bpf-Remove-old-BPF-JIT-implementations.patch @@ -0,0 +1,387 @@ +From: Johan Almbladh +Date: Tue, 5 Oct 2021 18:54:08 +0200 +Subject: [PATCH] mips: bpf: Remove old BPF JIT implementations + +This patch removes the old 32-bit cBPF and 64-bit eBPF JIT implementations. +They are replaced by a new eBPF implementation that supports both 32-bit +and 64-bit MIPS CPUs. + +Signed-off-by: Johan Almbladh +--- + delete mode 100644 arch/mips/net/bpf_jit.c + delete mode 100644 arch/mips/net/bpf_jit.h + delete mode 100644 arch/mips/net/bpf_jit_asm.S + delete mode 100644 arch/mips/net/ebpf_jit.c + +--- a/arch/mips/net/bpf_jit.h ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * Just-In-Time compiler for BPF filters on MIPS +- * +- * Copyright (c) 2014 Imagination Technologies Ltd. +- * Author: Markos Chandras +- */ +- +-#ifndef BPF_JIT_MIPS_OP_H +-#define BPF_JIT_MIPS_OP_H +- +-/* Registers used by JIT */ +-#define MIPS_R_ZERO 0 +-#define MIPS_R_V0 2 +-#define MIPS_R_A0 4 +-#define MIPS_R_A1 5 +-#define MIPS_R_T4 12 +-#define MIPS_R_T5 13 +-#define MIPS_R_T6 14 +-#define MIPS_R_T7 15 +-#define MIPS_R_S0 16 +-#define MIPS_R_S1 17 +-#define MIPS_R_S2 18 +-#define MIPS_R_S3 19 +-#define MIPS_R_S4 20 +-#define MIPS_R_S5 21 +-#define MIPS_R_S6 22 +-#define MIPS_R_S7 23 +-#define MIPS_R_SP 29 +-#define MIPS_R_RA 31 +- +-/* Conditional codes */ +-#define MIPS_COND_EQ 0x1 +-#define MIPS_COND_GE (0x1 << 1) +-#define MIPS_COND_GT (0x1 << 2) +-#define MIPS_COND_NE (0x1 << 3) +-#define MIPS_COND_ALL (0x1 << 4) +-/* Conditionals on X register or K immediate */ +-#define MIPS_COND_X (0x1 << 5) +-#define MIPS_COND_K (0x1 << 6) +- +-#define r_ret MIPS_R_V0 +- +-/* +- * Use 2 scratch registers to avoid pipeline interlocks. +- * There is no overhead during epilogue and prologue since +- * any of the $s0-$s6 registers will only be preserved if +- * they are going to actually be used. +- */ +-#define r_skb_hl MIPS_R_S0 /* skb header length */ +-#define r_skb_data MIPS_R_S1 /* skb actual data */ +-#define r_off MIPS_R_S2 +-#define r_A MIPS_R_S3 +-#define r_X MIPS_R_S4 +-#define r_skb MIPS_R_S5 +-#define r_M MIPS_R_S6 +-#define r_skb_len MIPS_R_S7 +-#define r_s0 MIPS_R_T4 /* scratch reg 1 */ +-#define r_s1 MIPS_R_T5 /* scratch reg 2 */ +-#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */ +-#define r_tmp MIPS_R_T7 /* No need to preserve this */ +-#define r_zero MIPS_R_ZERO +-#define r_sp MIPS_R_SP +-#define r_ra MIPS_R_RA +- +-#ifndef __ASSEMBLY__ +- +-/* Declare ASM helpers */ +- +-#define DECLARE_LOAD_FUNC(func) \ +- extern u8 func(unsigned long *skb, int offset); \ +- extern u8 func##_negative(unsigned long *skb, int offset); \ +- extern u8 func##_positive(unsigned long *skb, int offset) +- +-DECLARE_LOAD_FUNC(sk_load_word); +-DECLARE_LOAD_FUNC(sk_load_half); +-DECLARE_LOAD_FUNC(sk_load_byte); +- +-#endif +- +-#endif /* BPF_JIT_MIPS_OP_H */ +--- a/arch/mips/net/bpf_jit_asm.S ++++ /dev/null +@@ -1,285 +0,0 @@ +-/* +- * bpf_jib_asm.S: Packet/header access helper functions for MIPS/MIPS64 BPF +- * compiler. +- * +- * Copyright (C) 2015 Imagination Technologies Ltd. +- * Author: Markos Chandras +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; version 2 of the License. +- */ +- +-#include +-#include +-#include +-#include "bpf_jit.h" +- +-/* ABI +- * +- * r_skb_hl skb header length +- * r_skb_data skb data +- * r_off(a1) offset register +- * r_A BPF register A +- * r_X PF register X +- * r_skb(a0) *skb +- * r_M *scratch memory +- * r_skb_le skb length +- * r_s0 Scratch register 0 +- * r_s1 Scratch register 1 +- * +- * On entry: +- * a0: *skb +- * a1: offset (imm or imm + X) +- * +- * All non-BPF-ABI registers are free for use. On return, we only +- * care about r_ret. The BPF-ABI registers are assumed to remain +- * unmodified during the entire filter operation. +- */ +- +-#define skb a0 +-#define offset a1 +-#define SKF_LL_OFF (-0x200000) /* Can't include linux/filter.h in assembly */ +- +- /* We know better :) so prevent assembler reordering etc */ +- .set noreorder +- +-#define is_offset_negative(TYPE) \ +- /* If offset is negative we have more work to do */ \ +- slti t0, offset, 0; \ +- bgtz t0, bpf_slow_path_##TYPE##_neg; \ +- /* Be careful what follows in DS. */ +- +-#define is_offset_in_header(SIZE, TYPE) \ +- /* Reading from header? */ \ +- addiu $r_s0, $r_skb_hl, -SIZE; \ +- slt t0, $r_s0, offset; \ +- bgtz t0, bpf_slow_path_##TYPE; \ +- +-LEAF(sk_load_word) +- is_offset_negative(word) +-FEXPORT(sk_load_word_positive) +- is_offset_in_header(4, word) +- /* Offset within header boundaries */ +- PTR_ADDU t1, $r_skb_data, offset +- .set reorder +- lw $r_A, 0(t1) +- .set noreorder +-#ifdef CONFIG_CPU_LITTLE_ENDIAN +-# if MIPS_ISA_REV >= 2 +- wsbh t0, $r_A +- rotr $r_A, t0, 16 +-# else +- sll t0, $r_A, 24 +- srl t1, $r_A, 24 +- srl t2, $r_A, 8 +- or t0, t0, t1 +- andi t2, t2, 0xff00 +- andi t1, $r_A, 0xff00 +- or t0, t0, t2 +- sll t1, t1, 8 +- or $r_A, t0, t1 +-# endif +-#endif +- jr $r_ra +- move $r_ret, zero +- END(sk_load_word) +- +-LEAF(sk_load_half) +- is_offset_negative(half) +-FEXPORT(sk_load_half_positive) +- is_offset_in_header(2, half) +- /* Offset within header boundaries */ +- PTR_ADDU t1, $r_skb_data, offset +- lhu $r_A, 0(t1) +-#ifdef CONFIG_CPU_LITTLE_ENDIAN +-# if MIPS_ISA_REV >= 2 +- wsbh $r_A, $r_A +-# else +- sll t0, $r_A, 8 +- srl t1, $r_A, 8 +- andi t0, t0, 0xff00 +- or $r_A, t0, t1 +-# endif +-#endif +- jr $r_ra +- move $r_ret, zero +- END(sk_load_half) +- +-LEAF(sk_load_byte) +- is_offset_negative(byte) +-FEXPORT(sk_load_byte_positive) +- is_offset_in_header(1, byte) +- /* Offset within header boundaries */ +- PTR_ADDU t1, $r_skb_data, offset +- lbu $r_A, 0(t1) +- jr $r_ra +- move $r_ret, zero +- END(sk_load_byte) +- +-/* +- * call skb_copy_bits: +- * (prototype in linux/skbuff.h) +- * +- * int skb_copy_bits(sk_buff *skb, int offset, void *to, int len) +- * +- * o32 mandates we leave 4 spaces for argument registers in case +- * the callee needs to use them. Even though we don't care about +- * the argument registers ourselves, we need to allocate that space +- * to remain ABI compliant since the callee may want to use that space. +- * We also allocate 2 more spaces for $r_ra and our return register (*to). +- * +- * n64 is a bit different. The *caller* will allocate the space to preserve +- * the arguments. So in 64-bit kernels, we allocate the 4-arg space for no +- * good reason but it does not matter that much really. +- * +- * (void *to) is returned in r_s0 +- * +- */ +-#ifdef CONFIG_CPU_LITTLE_ENDIAN +-#define DS_OFFSET(SIZE) (4 * SZREG) +-#else +-#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE)) +-#endif +-#define bpf_slow_path_common(SIZE) \ +- /* Quick check. Are we within reasonable boundaries? */ \ +- LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \ +- sltu $r_s0, offset, $r_s1; \ +- beqz $r_s0, fault; \ +- /* Load 4th argument in DS */ \ +- LONG_ADDIU a3, zero, SIZE; \ +- PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \ +- PTR_LA t0, skb_copy_bits; \ +- PTR_S $r_ra, (5 * SZREG)($r_sp); \ +- /* Assign low slot to a2 */ \ +- PTR_ADDIU a2, $r_sp, DS_OFFSET(SIZE); \ +- jalr t0; \ +- /* Reset our destination slot (DS but it's ok) */ \ +- INT_S zero, (4 * SZREG)($r_sp); \ +- /* \ +- * skb_copy_bits returns 0 on success and -EFAULT \ +- * on error. Our data live in a2. Do not bother with \ +- * our data if an error has been returned. \ +- */ \ +- /* Restore our frame */ \ +- PTR_L $r_ra, (5 * SZREG)($r_sp); \ +- INT_L $r_s0, (4 * SZREG)($r_sp); \ +- bltz v0, fault; \ +- PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \ +- move $r_ret, zero; \ +- +-NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp) +- bpf_slow_path_common(4) +-#ifdef CONFIG_CPU_LITTLE_ENDIAN +-# if MIPS_ISA_REV >= 2 +- wsbh t0, $r_s0 +- jr $r_ra +- rotr $r_A, t0, 16 +-# else +- sll t0, $r_s0, 24 +- srl t1, $r_s0, 24 +- srl t2, $r_s0, 8 +- or t0, t0, t1 +- andi t2, t2, 0xff00 +- andi t1, $r_s0, 0xff00 +- or t0, t0, t2 +- sll t1, t1, 8 +- jr $r_ra +- or $r_A, t0, t1 +-# endif +-#else +- jr $r_ra +- move $r_A, $r_s0 +-#endif +- +- END(bpf_slow_path_word) +- +-NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp) +- bpf_slow_path_common(2) +-#ifdef CONFIG_CPU_LITTLE_ENDIAN +-# if MIPS_ISA_REV >= 2 +- jr $r_ra +- wsbh $r_A, $r_s0 +-# else +- sll t0, $r_s0, 8 +- andi t1, $r_s0, 0xff00 +- andi t0, t0, 0xff00 +- srl t1, t1, 8 +- jr $r_ra +- or $r_A, t0, t1 +-# endif +-#else +- jr $r_ra +- move $r_A, $r_s0 +-#endif +- +- END(bpf_slow_path_half) +- +-NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp) +- bpf_slow_path_common(1) +- jr $r_ra +- move $r_A, $r_s0 +- +- END(bpf_slow_path_byte) +- +-/* +- * Negative entry points +- */ +- .macro bpf_is_end_of_data +- li t0, SKF_LL_OFF +- /* Reading link layer data? */ +- slt t1, offset, t0 +- bgtz t1, fault +- /* Be careful what follows in DS. */ +- .endm +-/* +- * call skb_copy_bits: +- * (prototype in linux/filter.h) +- * +- * void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, +- * int k, unsigned int size) +- * +- * see above (bpf_slow_path_common) for ABI restrictions +- */ +-#define bpf_negative_common(SIZE) \ +- PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \ +- PTR_LA t0, bpf_internal_load_pointer_neg_helper; \ +- PTR_S $r_ra, (5 * SZREG)($r_sp); \ +- jalr t0; \ +- li a2, SIZE; \ +- PTR_L $r_ra, (5 * SZREG)($r_sp); \ +- /* Check return pointer */ \ +- beqz v0, fault; \ +- PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \ +- /* Preserve our pointer */ \ +- move $r_s0, v0; \ +- /* Set return value */ \ +- move $r_ret, zero; \ +- +-bpf_slow_path_word_neg: +- bpf_is_end_of_data +-NESTED(sk_load_word_negative, (6 * SZREG), $r_sp) +- bpf_negative_common(4) +- jr $r_ra +- lw $r_A, 0($r_s0) +- END(sk_load_word_negative) +- +-bpf_slow_path_half_neg: +- bpf_is_end_of_data +-NESTED(sk_load_half_negative, (6 * SZREG), $r_sp) +- bpf_negative_common(2) +- jr $r_ra +- lhu $r_A, 0($r_s0) +- END(sk_load_half_negative) +- +-bpf_slow_path_byte_neg: +- bpf_is_end_of_data +-NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp) +- bpf_negative_common(1) +- jr $r_ra +- lbu $r_A, 0($r_s0) +- END(sk_load_byte_negative) +- +-fault: +- jr $r_ra +- addiu $r_ret, zero, 1 diff --git a/target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch b/target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch new file mode 100644 index 0000000000..b1f46e9af8 --- /dev/null +++ b/target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch @@ -0,0 +1,272 @@ +From 03662fcd41f4b764857f17b95f9a2a63c24bddd4 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 3 Nov 2020 17:28:09 +0100 +Subject: [PATCH 1/2] crypto: arm/chacha-neon - optimize for non-block size + multiples + +commit 86cd97ec4b943af35562a74688bc4e909b32c3d1 upstream. + +The current NEON based ChaCha implementation for ARM is optimized for +multiples of 4x the ChaCha block size (64 bytes). This makes sense for +block encryption, but given that ChaCha is also often used in the +context of networking, it makes sense to consider arbitrary length +inputs as well. + +For example, WireGuard typically uses 1420 byte packets, and performing +ChaCha encryption involves 5 invocations of chacha_4block_xor_neon() +and 3 invocations of chacha_block_xor_neon(), where the last one also +involves a memcpy() using a buffer on the stack to process the final +chunk of 1420 % 64 == 12 bytes. + +Let's optimize for this case as well, by letting chacha_4block_xor_neon() +deal with any input size between 64 and 256 bytes, using NEON permutation +instructions and overlapping loads and stores. This way, the 140 byte +tail of a 1420 byte input buffer can simply be processed in one go. + +This results in the following performance improvements for 1420 byte +blocks, without significant impact on power-of-2 input sizes. (Note +that Raspberry Pi is widely used in combination with a 32-bit kernel, +even though the core is 64-bit capable) + + Cortex-A8 (BeagleBone) : 7% + Cortex-A15 (Calxeda Midway) : 21% + Cortex-A53 (Raspberry Pi 3) : 3% + Cortex-A72 (Raspberry Pi 4) : 19% + +Cc: Eric Biggers +Cc: "Jason A . Donenfeld" +Signed-off-by: Ard Biesheuvel +Signed-off-by: Herbert Xu +Signed-off-by: Jason A. Donenfeld +--- + arch/arm/crypto/chacha-glue.c | 34 +++++------ + arch/arm/crypto/chacha-neon-core.S | 97 +++++++++++++++++++++++++++--- + 2 files changed, 107 insertions(+), 24 deletions(-) + +--- a/arch/arm/crypto/chacha-glue.c ++++ b/arch/arm/crypto/chacha-glue.c +@@ -23,7 +23,7 @@ + asmlinkage void chacha_block_xor_neon(const u32 *state, u8 *dst, const u8 *src, + int nrounds); + asmlinkage void chacha_4block_xor_neon(const u32 *state, u8 *dst, const u8 *src, +- int nrounds); ++ int nrounds, unsigned int nbytes); + asmlinkage void hchacha_block_arm(const u32 *state, u32 *out, int nrounds); + asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds); + +@@ -42,24 +42,24 @@ static void chacha_doneon(u32 *state, u8 + { + u8 buf[CHACHA_BLOCK_SIZE]; + +- while (bytes >= CHACHA_BLOCK_SIZE * 4) { +- chacha_4block_xor_neon(state, dst, src, nrounds); +- bytes -= CHACHA_BLOCK_SIZE * 4; +- src += CHACHA_BLOCK_SIZE * 4; +- dst += CHACHA_BLOCK_SIZE * 4; +- state[12] += 4; +- } +- while (bytes >= CHACHA_BLOCK_SIZE) { +- chacha_block_xor_neon(state, dst, src, nrounds); +- bytes -= CHACHA_BLOCK_SIZE; +- src += CHACHA_BLOCK_SIZE; +- dst += CHACHA_BLOCK_SIZE; +- state[12]++; ++ while (bytes > CHACHA_BLOCK_SIZE) { ++ unsigned int l = min(bytes, CHACHA_BLOCK_SIZE * 4U); ++ ++ chacha_4block_xor_neon(state, dst, src, nrounds, l); ++ bytes -= l; ++ src += l; ++ dst += l; ++ state[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE); + } + if (bytes) { +- memcpy(buf, src, bytes); +- chacha_block_xor_neon(state, buf, buf, nrounds); +- memcpy(dst, buf, bytes); ++ const u8 *s = src; ++ u8 *d = dst; ++ ++ if (bytes != CHACHA_BLOCK_SIZE) ++ s = d = memcpy(buf, src, bytes); ++ chacha_block_xor_neon(state, d, s, nrounds); ++ if (d != dst) ++ memcpy(dst, buf, bytes); + } + } + +--- a/arch/arm/crypto/chacha-neon-core.S ++++ b/arch/arm/crypto/chacha-neon-core.S +@@ -47,6 +47,7 @@ + */ + + #include ++#include + + .text + .fpu neon +@@ -205,7 +206,7 @@ ENDPROC(hchacha_block_neon) + + .align 5 + ENTRY(chacha_4block_xor_neon) +- push {r4-r5} ++ push {r4, lr} + mov r4, sp // preserve the stack pointer + sub ip, sp, #0x20 // allocate a 32 byte buffer + bic ip, ip, #0x1f // aligned to 32 bytes +@@ -229,10 +230,10 @@ ENTRY(chacha_4block_xor_neon) + vld1.32 {q0-q1}, [r0] + vld1.32 {q2-q3}, [ip] + +- adr r5, .Lctrinc ++ adr lr, .Lctrinc + vdup.32 q15, d7[1] + vdup.32 q14, d7[0] +- vld1.32 {q4}, [r5, :128] ++ vld1.32 {q4}, [lr, :128] + vdup.32 q13, d6[1] + vdup.32 q12, d6[0] + vdup.32 q11, d5[1] +@@ -455,7 +456,7 @@ ENTRY(chacha_4block_xor_neon) + + // Re-interleave the words in the first two rows of each block (x0..7). + // Also add the counter values 0-3 to x12[0-3]. +- vld1.32 {q8}, [r5, :128] // load counter values 0-3 ++ vld1.32 {q8}, [lr, :128] // load counter values 0-3 + vzip.32 q0, q1 // => (0 1 0 1) (0 1 0 1) + vzip.32 q2, q3 // => (2 3 2 3) (2 3 2 3) + vzip.32 q4, q5 // => (4 5 4 5) (4 5 4 5) +@@ -493,6 +494,8 @@ ENTRY(chacha_4block_xor_neon) + + // Re-interleave the words in the last two rows of each block (x8..15). + vld1.32 {q8-q9}, [sp, :256] ++ mov sp, r4 // restore original stack pointer ++ ldr r4, [r4, #8] // load number of bytes + vzip.32 q12, q13 // => (12 13 12 13) (12 13 12 13) + vzip.32 q14, q15 // => (14 15 14 15) (14 15 14 15) + vzip.32 q8, q9 // => (8 9 8 9) (8 9 8 9) +@@ -520,41 +523,121 @@ ENTRY(chacha_4block_xor_neon) + // XOR the rest of the data with the keystream + + vld1.8 {q0-q1}, [r2]! ++ subs r4, r4, #96 + veor q0, q0, q8 + veor q1, q1, q12 ++ ble .Lle96 + vst1.8 {q0-q1}, [r1]! + + vld1.8 {q0-q1}, [r2]! ++ subs r4, r4, #32 + veor q0, q0, q2 + veor q1, q1, q6 ++ ble .Lle128 + vst1.8 {q0-q1}, [r1]! + + vld1.8 {q0-q1}, [r2]! ++ subs r4, r4, #32 + veor q0, q0, q10 + veor q1, q1, q14 ++ ble .Lle160 + vst1.8 {q0-q1}, [r1]! + + vld1.8 {q0-q1}, [r2]! ++ subs r4, r4, #32 + veor q0, q0, q4 + veor q1, q1, q5 ++ ble .Lle192 + vst1.8 {q0-q1}, [r1]! + + vld1.8 {q0-q1}, [r2]! ++ subs r4, r4, #32 + veor q0, q0, q9 + veor q1, q1, q13 ++ ble .Lle224 + vst1.8 {q0-q1}, [r1]! + + vld1.8 {q0-q1}, [r2]! ++ subs r4, r4, #32 + veor q0, q0, q3 + veor q1, q1, q7 ++ blt .Llt256 ++.Lout: + vst1.8 {q0-q1}, [r1]! + + vld1.8 {q0-q1}, [r2] +- mov sp, r4 // restore original stack pointer + veor q0, q0, q11 + veor q1, q1, q15 + vst1.8 {q0-q1}, [r1] + +- pop {r4-r5} +- bx lr ++ pop {r4, pc} ++ ++.Lle192: ++ vmov q4, q9 ++ vmov q5, q13 ++ ++.Lle160: ++ // nothing to do ++ ++.Lfinalblock: ++ // Process the final block if processing less than 4 full blocks. ++ // Entered with 32 bytes of ChaCha cipher stream in q4-q5, and the ++ // previous 32 byte output block that still needs to be written at ++ // [r1] in q0-q1. ++ beq .Lfullblock ++ ++.Lpartialblock: ++ adr lr, .Lpermute + 32 ++ add r2, r2, r4 ++ add lr, lr, r4 ++ add r4, r4, r1 ++ ++ vld1.8 {q2-q3}, [lr] ++ vld1.8 {q6-q7}, [r2] ++ ++ add r4, r4, #32 ++ ++ vtbl.8 d4, {q4-q5}, d4 ++ vtbl.8 d5, {q4-q5}, d5 ++ vtbl.8 d6, {q4-q5}, d6 ++ vtbl.8 d7, {q4-q5}, d7 ++ ++ veor q6, q6, q2 ++ veor q7, q7, q3 ++ ++ vst1.8 {q6-q7}, [r4] // overlapping stores ++ vst1.8 {q0-q1}, [r1] ++ pop {r4, pc} ++ ++.Lfullblock: ++ vmov q11, q4 ++ vmov q15, q5 ++ b .Lout ++.Lle96: ++ vmov q4, q2 ++ vmov q5, q6 ++ b .Lfinalblock ++.Lle128: ++ vmov q4, q10 ++ vmov q5, q14 ++ b .Lfinalblock ++.Lle224: ++ vmov q4, q3 ++ vmov q5, q7 ++ b .Lfinalblock ++.Llt256: ++ vmov q4, q11 ++ vmov q5, q15 ++ b .Lpartialblock + ENDPROC(chacha_4block_xor_neon) ++ ++ .align L1_CACHE_SHIFT ++.Lpermute: ++ .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ++ .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ++ .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 ++ .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f ++ .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ++ .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ++ .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 ++ .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f diff --git a/target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch b/target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch new file mode 100644 index 0000000000..1e4d2041e5 --- /dev/null +++ b/target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch @@ -0,0 +1,38 @@ +From 7f63462faf9eab69132bea9abd48c2c05a93145b Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Sun, 13 Dec 2020 15:39:29 +0100 +Subject: [PATCH 2/2] crypto: arm/chacha-neon - add missing counter increment + +commit fd16931a2f518a32753920ff20895e5cf04c8ff1 upstream. + +Commit 86cd97ec4b943af3 ("crypto: arm/chacha-neon - optimize for non-block +size multiples") refactored the chacha block handling in the glue code in +a way that may result in the counter increment to be omitted when calling +chacha_block_xor_neon() to process a full block. This violates the skcipher +API, which requires that the output IV is suitable for handling more input +as long as the preceding input has been presented in round multiples of the +block size. Also, the same code is exposed via the chacha library interface +whose callers may actually rely on this increment to occur even for final +blocks that are smaller than the chacha block size. + +So increment the counter after calling chacha_block_xor_neon(). + +Fixes: 86cd97ec4b943af3 ("crypto: arm/chacha-neon - optimize for non-block size multiples") +Reported-by: Eric Biggers +Signed-off-by: Ard Biesheuvel +Signed-off-by: Herbert Xu +Signed-off-by: Jason A. Donenfeld +--- + arch/arm/crypto/chacha-glue.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/crypto/chacha-glue.c ++++ b/arch/arm/crypto/chacha-glue.c +@@ -60,6 +60,7 @@ static void chacha_doneon(u32 *state, u8 + chacha_block_xor_neon(state, d, s, nrounds); + if (d != dst) + memcpy(dst, buf, bytes); ++ state[12]++; + } + } + diff --git a/target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch b/target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch new file mode 100644 index 0000000000..444fd677b4 --- /dev/null +++ b/target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch @@ -0,0 +1,42 @@ +From a13827e9091c07e25cdeec9a402d74a27e2a1111 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Mon, 22 Feb 2021 17:25:46 +0100 +Subject: [PATCH] wireguard: peer: put frequently used members above cache + lines + +commit 5a0598695634a6bb4126818902dd9140cd9df8b6 upstream. + +The is_dead boolean is checked for every single packet, while the +internal_id member is used basically only for pr_debug messages. So it +makes sense to hoist up is_dead into some space formerly unused by a +struct hole, while demoting internal_api to below the lowest struct +cache line. + +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Jakub Kicinski +Signed-off-by: Jason A. Donenfeld +--- + drivers/net/wireguard/peer.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireguard/peer.h ++++ b/drivers/net/wireguard/peer.h +@@ -39,6 +39,7 @@ struct wg_peer { + struct prev_queue tx_queue, rx_queue; + struct sk_buff_head staged_packet_queue; + int serial_work_cpu; ++ bool is_dead; + struct noise_keypairs keypairs; + struct endpoint endpoint; + struct dst_cache endpoint_cache; +@@ -61,9 +62,8 @@ struct wg_peer { + struct rcu_head rcu; + struct list_head peer_list; + struct list_head allowedips_list; +- u64 internal_id; + struct napi_struct napi; +- bool is_dead; ++ u64 internal_id; + }; + + struct wg_peer *wg_peer_create(struct wg_device *wg, diff --git a/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch b/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch new file mode 100644 index 0000000000..6e274acb1f --- /dev/null +++ b/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch @@ -0,0 +1,52 @@ +From 02d6fdecb9c38de19065f6bed8d5214556fd061d Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 4 Nov 2021 16:00:40 +0100 +Subject: regmap: allow to define reg_update_bits for no bus configuration + +Some device requires a special handling for reg_update_bits and can't use +the normal regmap read write logic. An example is when locking is +handled by the device and rmw operations requires to do atomic operations. +Allow to declare a dedicated function in regmap_config for +reg_update_bits in no bus configuration. + +Signed-off-by: Ansuel Smith +Link: https://lore.kernel.org/r/20211104150040.1260-1-ansuelsmth@gmail.com +Signed-off-by: Mark Brown +--- + drivers/base/regmap/regmap.c | 1 + + include/linux/regmap.h | 7 +++++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -842,6 +842,7 @@ struct regmap *__regmap_init(struct devi + if (!bus) { + map->reg_read = config->reg_read; + map->reg_write = config->reg_write; ++ map->reg_update_bits = config->reg_update_bits; + + map->defer_caching = false; + goto skip_format_initialization; +--- a/include/linux/regmap.h ++++ b/include/linux/regmap.h +@@ -289,6 +289,11 @@ typedef void (*regmap_unlock)(void *); + * read operation on a bus such as SPI, I2C, etc. Most of the + * devices do not need this. + * @reg_write: Same as above for writing. ++ * @reg_update_bits: Optional callback that if filled will be used to perform ++ * all the update_bits(rmw) operation. Should only be provided ++ * if the function require special handling with lock and reg ++ * handling and the operation cannot be represented as a simple ++ * update_bits operation on a bus such as SPI, I2C, etc. + * @fast_io: Register IO is fast. Use a spinlock instead of a mutex + * to perform locking. This field is ignored if custom lock/unlock + * functions are used (see fields lock/unlock of struct regmap_config). +@@ -366,6 +371,8 @@ struct regmap_config { + + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); ++ int (*reg_update_bits)(void *context, unsigned int reg, ++ unsigned int mask, unsigned int val); + + bool fast_io; + diff --git a/target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch b/target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch new file mode 100644 index 0000000000..fafe530ac5 --- /dev/null +++ b/target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch @@ -0,0 +1,36 @@ +From 6523061868212473f63812a0c477a161742bed42 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Sat, 27 Feb 2021 13:20:24 +0100 +Subject: [PATCH] MIPS: select CPU_MIPS64 for remaining MIPS64 CPUs + +The CPU_MIPS64 and CPU_MIPS32 variables are supposed to be able to +distinguish broadly between 64-bit and 32-bit MIPS CPUs. However, they +weren't selected by the specialty CPUs, Octeon and Loongson, which meant +it was possible to hit a weird state of: + + MIPS=y, CONFIG_64BIT=y, CPU_MIPS64=n + +This commit rectifies the issue by having CPU_MIPS64 be selected when +the missing Octeon or Loongson models are selected. + +Cc: Thomas Bogendoerfer +Cc: Ralf Baechle +Cc: George Cherian +Cc: Huacai Chen +Cc: Jiaxun Yang +Signed-off-by: Jason A. Donenfeld +--- + arch/mips/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -2088,7 +2088,7 @@ config CPU_MIPS32 + config CPU_MIPS64 + bool + default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R5 || \ +- CPU_MIPS64_R6 ++ CPU_MIPS64_R6 || CPU_LOONGSON64 || CPU_CAVIUM_OCTEON + + # + # These indicate the revision of the architecture diff --git a/target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch b/target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch new file mode 100644 index 0000000000..3f8808f702 --- /dev/null +++ b/target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch @@ -0,0 +1,36 @@ +From 7d1531c81c0fb4c93bea8dc316043ad0e4d0c270 Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Sun, 25 Oct 2020 23:19:40 +0800 +Subject: [PATCH] MIPS: zboot: put appended dtb into a section + +This will make a separated section for dtb appear in ELF, and we can +then use objcopy to patch a dtb into vmlinuz when RAW_APPENDED_DTB +is set in kernel config. + +command to patch a dtb: +objcopy --set-section-flags=.appended_dtb=alloc,contents \ + --update-section=.appended_dtb=.dtb vmlinuz vmlinuz-dtb + +Signed-off-by: Chuanhong Guo +--- + arch/mips/boot/compressed/ld.script | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/arch/mips/boot/compressed/ld.script ++++ b/arch/mips/boot/compressed/ld.script +@@ -31,9 +31,12 @@ SECTIONS + CONSTRUCTORS + . = ALIGN(16); + } +- __appended_dtb = .; +- /* leave space for appended DTB */ +- . += 0x100000; ++ ++ .appended_dtb : { ++ __appended_dtb = .; ++ /* leave space for appended DTB */ ++ . += 0x100000; ++ } + + _edata = .; + /* End of data section */ diff --git a/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch new file mode 100644 index 0000000000..d300af3342 --- /dev/null +++ b/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -0,0 +1,106 @@ +From: Pablo Neira Ayuso +Date: Thu, 25 Jan 2018 12:58:55 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from + nf_flow_table + +Move the code that deals with device events to the core. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -576,13 +576,41 @@ void nf_flow_table_free(struct nf_flowta + } + EXPORT_SYMBOL_GPL(nf_flow_table_free); + ++static int nf_flow_table_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_DOWN) ++ return NOTIFY_DONE; ++ ++ nf_flow_table_cleanup(dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = nf_flow_table_netdev_event, ++}; ++ + static int __init nf_flow_table_module_init(void) + { +- return nf_flow_table_offload_init(); ++ int ret; ++ ++ ret = nf_flow_table_offload_init(); ++ if (ret) ++ return ret; ++ ++ ret = register_netdevice_notifier(&flow_offload_netdev_notifier); ++ if (ret) ++ nf_flow_table_offload_exit(); ++ ++ return ret; + } + + static void __exit nf_flow_table_module_exit(void) + { ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); + nf_flow_table_offload_exit(); + } + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -237,47 +237,14 @@ static struct nft_expr_type nft_flow_off + .owner = THIS_MODULE, + }; + +-static int flow_offload_netdev_event(struct notifier_block *this, +- unsigned long event, void *ptr) +-{ +- struct net_device *dev = netdev_notifier_info_to_dev(ptr); +- +- if (event != NETDEV_DOWN) +- return NOTIFY_DONE; +- +- nf_flow_table_cleanup(dev); +- +- return NOTIFY_DONE; +-} +- +-static struct notifier_block flow_offload_netdev_notifier = { +- .notifier_call = flow_offload_netdev_event, +-}; +- + static int __init nft_flow_offload_module_init(void) + { +- int err; +- +- err = register_netdevice_notifier(&flow_offload_netdev_notifier); +- if (err) +- goto err; +- +- err = nft_register_expr(&nft_flow_offload_type); +- if (err < 0) +- goto register_expr; +- +- return 0; +- +-register_expr: +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); +-err: +- return err; ++ return nft_register_expr(&nft_flow_offload_type); + } + + static void __exit nft_flow_offload_module_exit(void) + { + nft_unregister_expr(&nft_flow_offload_type); +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); + } + + module_init(nft_flow_offload_module_init); diff --git a/target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch b/target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch new file mode 100644 index 0000000000..8aded43526 --- /dev/null +++ b/target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch @@ -0,0 +1,324 @@ +From 04e9ab75267489224364fa510a88ada83e11c325 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 10 Dec 2020 18:23:52 +0100 +Subject: [PATCH] dt-bindings: mtd: convert "fixed-partitions" to the + json-schema +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This standardizes its documentation, allows validating with Makefile +checks and helps writing DTS files. + +Noticeable changes: +1. Dropped "Partitions can be represented by sub-nodes of a flash + device." as we also support subpartitions (don't have to be part of + flash device node) +2. Dropped "to Linux" as bindings are meant to be os agnostic. + +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20201210172352.31632-1-zajec5@gmail.com +Signed-off-by: Rob Herring +--- + .../devicetree/bindings/mtd/partition.txt | 131 +-------------- + .../mtd/partitions/fixed-partitions.yaml | 152 ++++++++++++++++++ + 2 files changed, 154 insertions(+), 129 deletions(-) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml + +--- a/Documentation/devicetree/bindings/mtd/partition.txt ++++ b/Documentation/devicetree/bindings/mtd/partition.txt +@@ -24,137 +24,10 @@ another partitioning method. + Available bindings are listed in the "partitions" subdirectory. + + +-Fixed Partitions +-================ +- +-Partitions can be represented by sub-nodes of a flash device. This can be used +-on platforms which have strong conventions about which portions of a flash are +-used for what purposes, but which don't use an on-flash partition table such +-as RedBoot. +- +-The partition table should be a subnode of the flash node and should be named +-'partitions'. This node should have the following property: +-- compatible : (required) must be "fixed-partitions" +-Partitions are then defined in subnodes of the partitions node. ++Deprecated: partitions defined in flash node ++============================================ + + For backwards compatibility partitions as direct subnodes of the flash device are + supported. This use is discouraged. + NOTE: also for backwards compatibility, direct subnodes that have a compatible + string are not considered partitions, as they may be used for other bindings. +- +-#address-cells & #size-cells must both be present in the partitions subnode of the +-flash device. There are two valid values for both: +-<1>: for partitions that require a single 32-bit cell to represent their +- size/address (aka the value is below 4 GiB) +-<2>: for partitions that require two 32-bit cells to represent their +- size/address (aka the value is 4 GiB or greater). +- +-Required properties: +-- reg : The partition's offset and size within the flash +- +-Optional properties: +-- label : The label / name for this partition. If omitted, the label is taken +- from the node name (excluding the unit address). +-- read-only : This parameter, if present, is a hint to Linux that this +- partition should only be mounted read-only. This is usually used for flash +- partitions containing early-boot firmware images or data which should not be +- clobbered. +-- lock : Do not unlock the partition at initialization time (not supported on +- all devices) +-- slc-mode: This parameter, if present, allows one to emulate SLC mode on a +- partition attached to an MLC NAND thus making this partition immune to +- paired-pages corruptions +- +-Examples: +- +- +-flash@0 { +- partitions { +- compatible = "fixed-partitions"; +- #address-cells = <1>; +- #size-cells = <1>; +- +- partition@0 { +- label = "u-boot"; +- reg = <0x0000000 0x100000>; +- read-only; +- }; +- +- uimage@100000 { +- reg = <0x0100000 0x200000>; +- }; +- }; +-}; +- +-flash@1 { +- partitions { +- compatible = "fixed-partitions"; +- #address-cells = <1>; +- #size-cells = <2>; +- +- /* a 4 GiB partition */ +- partition@0 { +- label = "filesystem"; +- reg = <0x00000000 0x1 0x00000000>; +- }; +- }; +-}; +- +-flash@2 { +- partitions { +- compatible = "fixed-partitions"; +- #address-cells = <2>; +- #size-cells = <2>; +- +- /* an 8 GiB partition */ +- partition@0 { +- label = "filesystem #1"; +- reg = <0x0 0x00000000 0x2 0x00000000>; +- }; +- +- /* a 4 GiB partition */ +- partition@200000000 { +- label = "filesystem #2"; +- reg = <0x2 0x00000000 0x1 0x00000000>; +- }; +- }; +-}; +- +-flash@3 { +- partitions { +- compatible = "fixed-partitions"; +- #address-cells = <1>; +- #size-cells = <1>; +- +- partition@0 { +- label = "bootloader"; +- reg = <0x000000 0x100000>; +- read-only; +- }; +- +- firmware@100000 { +- label = "firmware"; +- reg = <0x100000 0xe00000>; +- compatible = "brcm,trx"; +- }; +- +- calibration@f00000 { +- label = "calibration"; +- reg = <0xf00000 0x100000>; +- compatible = "fixed-partitions"; +- ranges = <0 0xf00000 0x100000>; +- #address-cells = <1>; +- #size-cells = <1>; +- +- partition@0 { +- label = "wifi0"; +- reg = <0x000000 0x080000>; +- }; +- +- partition@80000 { +- label = "wifi1"; +- reg = <0x080000 0x080000>; +- }; +- }; +- }; +-}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml +@@ -0,0 +1,152 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/fixed-partitions.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Fixed partitions ++ ++description: | ++ This binding can be used on platforms which have strong conventions about ++ which portions of a flash are used for what purposes, but which don't use an ++ on-flash partition table such as RedBoot. ++ ++ The partition table should be a node named "partitions". Partitions are then ++ defined as subnodes. ++ ++maintainers: ++ - Rafał Miłecki ++ ++properties: ++ compatible: ++ const: fixed-partitions ++ ++ "#address-cells": true ++ ++ "#size-cells": true ++ ++patternProperties: ++ "@[0-9a-f]+$": ++ description: node describing a single flash partition ++ type: object ++ ++ properties: ++ reg: ++ description: partition's offset and size within the flash ++ maxItems: 1 ++ ++ label: ++ description: The label / name for this partition. If omitted, the label ++ is taken from the node name (excluding the unit address). ++ ++ read-only: ++ description: This parameter, if present, is a hint that this partition ++ should only be mounted read-only. This is usually used for flash ++ partitions containing early-boot firmware images or data which should ++ not be clobbered. ++ type: boolean ++ ++ lock: ++ description: Do not unlock the partition at initialization time (not ++ supported on all devices) ++ type: boolean ++ ++ slc-mode: ++ description: This parameter, if present, allows one to emulate SLC mode ++ on a partition attached to an MLC NAND thus making this partition ++ immune to paired-pages corruptions ++ type: boolean ++ ++ required: ++ - reg ++ ++required: ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: true ++ ++examples: ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "u-boot"; ++ reg = <0x0000000 0x100000>; ++ read-only; ++ }; ++ ++ uimage@100000 { ++ reg = <0x0100000 0x200000>; ++ }; ++ }; ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <2>; ++ ++ /* a 4 GiB partition */ ++ partition@0 { ++ label = "filesystem"; ++ reg = <0x00000000 0x1 0x00000000>; ++ }; ++ }; ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ /* an 8 GiB partition */ ++ partition@0 { ++ label = "filesystem #1"; ++ reg = <0x0 0x00000000 0x2 0x00000000>; ++ }; ++ ++ /* a 4 GiB partition */ ++ partition@200000000 { ++ label = "filesystem #2"; ++ reg = <0x2 0x00000000 0x1 0x00000000>; ++ }; ++ }; ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bootloader"; ++ reg = <0x000000 0x100000>; ++ read-only; ++ }; ++ ++ firmware@100000 { ++ compatible = "brcm,trx"; ++ label = "firmware"; ++ reg = <0x100000 0xe00000>; ++ }; ++ ++ calibration@f00000 { ++ compatible = "fixed-partitions"; ++ label = "calibration"; ++ reg = <0xf00000 0x100000>; ++ ranges = <0 0xf00000 0x100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "wifi0"; ++ reg = <0x000000 0x080000>; ++ }; ++ ++ partition@80000 { ++ label = "wifi1"; ++ reg = <0x080000 0x080000>; ++ }; ++ }; ++ }; diff --git a/target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch b/target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch new file mode 100644 index 0000000000..f3b1179ecd --- /dev/null +++ b/target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch @@ -0,0 +1,115 @@ +From 6418522022c706fd867b00b2571edba48b8fa8c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 11 Feb 2021 23:04:25 +0100 +Subject: [PATCH] dt-bindings: mtd: move partition binding to its own file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Single partition binding is quite common and may be: +1. Used by multiple parsers +2. Extended for more specific cases + +Move it to separated file to avoid code duplication. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Rob Herring +Signed-off-by: Richard Weinberger +--- + .../mtd/partitions/fixed-partitions.yaml | 33 +------------ + .../bindings/mtd/partitions/partition.yaml | 47 +++++++++++++++++++ + 2 files changed, 48 insertions(+), 32 deletions(-) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/partition.yaml + +--- a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml ++++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml +@@ -27,38 +27,7 @@ properties: + + patternProperties: + "@[0-9a-f]+$": +- description: node describing a single flash partition +- type: object +- +- properties: +- reg: +- description: partition's offset and size within the flash +- maxItems: 1 +- +- label: +- description: The label / name for this partition. If omitted, the label +- is taken from the node name (excluding the unit address). +- +- read-only: +- description: This parameter, if present, is a hint that this partition +- should only be mounted read-only. This is usually used for flash +- partitions containing early-boot firmware images or data which should +- not be clobbered. +- type: boolean +- +- lock: +- description: Do not unlock the partition at initialization time (not +- supported on all devices) +- type: boolean +- +- slc-mode: +- description: This parameter, if present, allows one to emulate SLC mode +- on a partition attached to an MLC NAND thus making this partition +- immune to paired-pages corruptions +- type: boolean +- +- required: +- - reg ++ $ref: "partition.yaml#" + + required: + - "#address-cells" +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml +@@ -0,0 +1,47 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/partition.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Partition ++ ++description: | ++ This binding describes a single flash partition. Each partition must have its ++ relative offset and size specified. Depending on partition function extra ++ properties can be used. ++ ++maintainers: ++ - Rafał Miłecki ++ ++properties: ++ reg: ++ description: partition's offset and size within the flash ++ maxItems: 1 ++ ++ label: ++ description: The label / name for this partition. If omitted, the label ++ is taken from the node name (excluding the unit address). ++ ++ read-only: ++ description: This parameter, if present, is a hint that this partition ++ should only be mounted read-only. This is usually used for flash ++ partitions containing early-boot firmware images or data which should ++ not be clobbered. ++ type: boolean ++ ++ lock: ++ description: Do not unlock the partition at initialization time (not ++ supported on all devices) ++ type: boolean ++ ++ slc-mode: ++ description: This parameter, if present, allows one to emulate SLC mode ++ on a partition attached to an MLC NAND thus making this partition ++ immune to paired-pages corruptions ++ type: boolean ++ ++required: ++ - reg ++ ++additionalProperties: true diff --git a/target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch b/target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch new file mode 100644 index 0000000000..8576c7d78d --- /dev/null +++ b/target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch @@ -0,0 +1,92 @@ +From 6e9dff6fe3fbc452f16566e4a7e293b0decefdba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 11 Feb 2021 23:04:26 +0100 +Subject: [PATCH] dt-bindings: mtd: add binding for BCM4908 partitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM4908 uses fixed partitions layout but function of some partitions may +vary. Some devices use multiple firmware partitions and those partitions +should be marked to let system discover their purpose. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Richard Weinberger +--- + .../partitions/brcm,bcm4908-partitions.yaml | 70 +++++++++++++++++++ + 1 file changed, 70 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml +@@ -0,0 +1,70 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/brcm,bcm4908-partitions.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Broadcom BCM4908 partitioning ++ ++description: | ++ Broadcom BCM4908 CFE bootloader supports two firmware partitions. One is used ++ for regular booting, the other is treated as fallback. ++ ++ This binding allows defining all fixed partitions and marking those containing ++ firmware. System can use that information e.g. for booting or flashing ++ purposes. ++ ++maintainers: ++ - Rafał Miłecki ++ ++properties: ++ compatible: ++ const: brcm,bcm4908-partitions ++ ++ "#address-cells": ++ enum: [ 1, 2 ] ++ ++ "#size-cells": ++ enum: [ 1, 2 ] ++ ++patternProperties: ++ "^partition@[0-9a-f]+$": ++ $ref: "partition.yaml#" ++ properties: ++ compatible: ++ const: brcm,bcm4908-firmware ++ unevaluatedProperties: false ++ ++required: ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ partitions { ++ compatible = "brcm,bcm4908-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "cferom"; ++ reg = <0x0 0x100000>; ++ }; ++ ++ partition@100000 { ++ compatible = "brcm,bcm4908-firmware"; ++ reg = <0x100000 0xf00000>; ++ }; ++ ++ partition@1000000 { ++ compatible = "brcm,bcm4908-firmware"; ++ reg = <0x1000000 0xf00000>; ++ }; ++ ++ partition@1f00000 { ++ label = "calibration"; ++ reg = <0x1f00000 0x100000>; ++ }; ++ }; diff --git a/target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch b/target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch new file mode 100644 index 0000000000..d3891228e2 --- /dev/null +++ b/target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch @@ -0,0 +1,654 @@ +From afbef8efb591792579c633a7c545f914c6165f82 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 11 Feb 2021 23:04:27 +0100 +Subject: [PATCH] mtd: parsers: ofpart: support BCM4908 fixed partitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some devices use fixed partitioning with some partitions requiring some +extra logic. E.g. BCM4908 may have multiple firmware partitions but +detecting currently used one requires checking bootloader parameters. + +To support such cases without duplicating a lot of code (without copying +most of the ofpart.c code) support for post-parsing callback was added. + +BCM4908 support in ofpart can be enabled using config option and results +in compiling & executing a specific callback. It simply reads offset of +currently used firmware partition from the DT. Bootloader specifies it +using the "brcm_blparms" property. + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/parsers/Kconfig | 9 +++ + drivers/mtd/parsers/Makefile | 2 + + drivers/mtd/parsers/ofpart_bcm4908.c | 64 +++++++++++++++++++ + drivers/mtd/parsers/ofpart_bcm4908.h | 15 +++++ + .../mtd/parsers/{ofpart.c => ofpart_core.c} | 28 +++++++- + 5 files changed, 116 insertions(+), 2 deletions(-) + create mode 100644 drivers/mtd/parsers/ofpart_bcm4908.c + create mode 100644 drivers/mtd/parsers/ofpart_bcm4908.h + rename drivers/mtd/parsers/{ofpart.c => ofpart_core.c} (88%) + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -67,6 +67,15 @@ config MTD_OF_PARTS + flash memory node, as described in + Documentation/devicetree/bindings/mtd/partition.txt. + ++config MTD_OF_PARTS_BCM4908 ++ bool "BCM4908 partitioning support" ++ depends on MTD_OF_PARTS && (ARCH_BCM4908 || COMPILE_TEST) ++ default ARCH_BCM4908 ++ help ++ This provides partitions parser for BCM4908 family devices ++ that can have multiple "firmware" partitions. It takes care of ++ finding currently used one and backup ones. ++ + config MTD_PARSER_IMAGETAG + tristate "Parser for BCM963XX Image Tag format partitions" + depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -4,6 +4,8 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4 + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ++ofpart-y += ofpart_core.o ++ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o + obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o +--- /dev/null ++++ b/drivers/mtd/parsers/ofpart_bcm4908.c +@@ -0,0 +1,64 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2021 Rafał Miłecki ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ofpart_bcm4908.h" ++ ++#define BLPARAMS_FW_OFFSET "NAND_RFS_OFS" ++ ++static long long bcm4908_partitions_fw_offset(void) ++{ ++ struct device_node *root; ++ struct property *prop; ++ const char *s; ++ ++ root = of_find_node_by_path("/"); ++ if (!root) ++ return -ENOENT; ++ ++ of_property_for_each_string(root, "brcm_blparms", prop, s) { ++ size_t len = strlen(BLPARAMS_FW_OFFSET); ++ unsigned long offset; ++ int err; ++ ++ if (strncmp(s, BLPARAMS_FW_OFFSET, len) || s[len] != '=') ++ continue; ++ ++ err = kstrtoul(s + len + 1, 0, &offset); ++ if (err) { ++ pr_err("failed to parse %s\n", s + len + 1); ++ return err; ++ } ++ ++ return offset << 10; ++ } ++ ++ return -ENOENT; ++} ++ ++int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts) ++{ ++ long long fw_offset; ++ int i; ++ ++ fw_offset = bcm4908_partitions_fw_offset(); ++ ++ for (i = 0; i < nr_parts; i++) { ++ if (of_device_is_compatible(parts[i].of_node, "brcm,bcm4908-firmware")) { ++ if (fw_offset < 0 || parts[i].offset == fw_offset) ++ parts[i].name = "firmware"; ++ else ++ parts[i].name = "backup"; ++ } ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/mtd/parsers/ofpart_bcm4908.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __BCM4908_PARTITIONS_H ++#define __BCM4908_PARTITIONS_H ++ ++#ifdef CONFIG_MTD_OF_PARTS_BCM4908 ++int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); ++#else ++static inline int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, ++ int nr_parts) ++{ ++ return -EOPNOTSUPP; ++} ++#endif ++ ++#endif +--- a/drivers/mtd/parsers/ofpart.c ++++ /dev/null +@@ -1,239 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Flash partitions described by the OF (or flattened) device tree +- * +- * Copyright © 2006 MontaVista Software Inc. +- * Author: Vitaly Wool +- * +- * Revised to handle newer style flash binding by: +- * Copyright © 2007 David Gibson, IBM Corporation. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-static bool node_has_compatible(struct device_node *pp) +-{ +- return of_get_property(pp, "compatible", NULL); +-} +- +-static int parse_fixed_partitions(struct mtd_info *master, +- const struct mtd_partition **pparts, +- struct mtd_part_parser_data *data) +-{ +- struct mtd_partition *parts; +- struct device_node *mtd_node; +- struct device_node *ofpart_node; +- const char *partname; +- struct device_node *pp; +- int nr_parts, i, ret = 0; +- bool dedicated = true; +- +- +- /* Pull of_node from the master device node */ +- mtd_node = mtd_get_of_node(master); +- if (!mtd_node) +- return 0; +- +- ofpart_node = of_get_child_by_name(mtd_node, "partitions"); +- if (!ofpart_node) { +- /* +- * We might get here even when ofpart isn't used at all (e.g., +- * when using another parser), so don't be louder than +- * KERN_DEBUG +- */ +- pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", +- master->name, mtd_node); +- ofpart_node = mtd_node; +- dedicated = false; +- } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) { +- /* The 'partitions' subnode might be used by another parser */ +- return 0; +- } +- +- /* First count the subnodes */ +- nr_parts = 0; +- for_each_child_of_node(ofpart_node, pp) { +- if (!dedicated && node_has_compatible(pp)) +- continue; +- +- nr_parts++; +- } +- +- if (nr_parts == 0) +- return 0; +- +- parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); +- if (!parts) +- return -ENOMEM; +- +- i = 0; +- for_each_child_of_node(ofpart_node, pp) { +- const __be32 *reg; +- int len; +- int a_cells, s_cells; +- +- if (!dedicated && node_has_compatible(pp)) +- continue; +- +- reg = of_get_property(pp, "reg", &len); +- if (!reg) { +- if (dedicated) { +- pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n", +- master->name, pp, +- mtd_node); +- goto ofpart_fail; +- } else { +- nr_parts--; +- continue; +- } +- } +- +- a_cells = of_n_addr_cells(pp); +- s_cells = of_n_size_cells(pp); +- if (len / 4 != a_cells + s_cells) { +- pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n", +- master->name, pp, +- mtd_node); +- goto ofpart_fail; +- } +- +- parts[i].offset = of_read_number(reg, a_cells); +- parts[i].size = of_read_number(reg + a_cells, s_cells); +- parts[i].of_node = pp; +- +- partname = of_get_property(pp, "label", &len); +- if (!partname) +- partname = of_get_property(pp, "name", &len); +- parts[i].name = partname; +- +- if (of_get_property(pp, "read-only", &len)) +- parts[i].mask_flags |= MTD_WRITEABLE; +- +- if (of_get_property(pp, "lock", &len)) +- parts[i].mask_flags |= MTD_POWERUP_LOCK; +- +- if (of_property_read_bool(pp, "slc-mode")) +- parts[i].add_flags |= MTD_SLC_ON_MLC_EMULATION; +- +- i++; +- } +- +- if (!nr_parts) +- goto ofpart_none; +- +- *pparts = parts; +- return nr_parts; +- +-ofpart_fail: +- pr_err("%s: error parsing ofpart partition %pOF (%pOF)\n", +- master->name, pp, mtd_node); +- ret = -EINVAL; +-ofpart_none: +- of_node_put(pp); +- kfree(parts); +- return ret; +-} +- +-static const struct of_device_id parse_ofpart_match_table[] = { +- { .compatible = "fixed-partitions" }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); +- +-static struct mtd_part_parser ofpart_parser = { +- .parse_fn = parse_fixed_partitions, +- .name = "fixed-partitions", +- .of_match_table = parse_ofpart_match_table, +-}; +- +-static int parse_ofoldpart_partitions(struct mtd_info *master, +- const struct mtd_partition **pparts, +- struct mtd_part_parser_data *data) +-{ +- struct mtd_partition *parts; +- struct device_node *dp; +- int i, plen, nr_parts; +- const struct { +- __be32 offset, len; +- } *part; +- const char *names; +- +- /* Pull of_node from the master device node */ +- dp = mtd_get_of_node(master); +- if (!dp) +- return 0; +- +- part = of_get_property(dp, "partitions", &plen); +- if (!part) +- return 0; /* No partitions found */ +- +- pr_warn("Device tree uses obsolete partition map binding: %pOF\n", dp); +- +- nr_parts = plen / sizeof(part[0]); +- +- parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); +- if (!parts) +- return -ENOMEM; +- +- names = of_get_property(dp, "partition-names", &plen); +- +- for (i = 0; i < nr_parts; i++) { +- parts[i].offset = be32_to_cpu(part->offset); +- parts[i].size = be32_to_cpu(part->len) & ~1; +- /* bit 0 set signifies read only partition */ +- if (be32_to_cpu(part->len) & 1) +- parts[i].mask_flags = MTD_WRITEABLE; +- +- if (names && (plen > 0)) { +- int len = strlen(names) + 1; +- +- parts[i].name = names; +- plen -= len; +- names += len; +- } else { +- parts[i].name = "unnamed"; +- } +- +- part++; +- } +- +- *pparts = parts; +- return nr_parts; +-} +- +-static struct mtd_part_parser ofoldpart_parser = { +- .parse_fn = parse_ofoldpart_partitions, +- .name = "ofoldpart", +-}; +- +-static int __init ofpart_parser_init(void) +-{ +- register_mtd_parser(&ofpart_parser); +- register_mtd_parser(&ofoldpart_parser); +- return 0; +-} +- +-static void __exit ofpart_parser_exit(void) +-{ +- deregister_mtd_parser(&ofpart_parser); +- deregister_mtd_parser(&ofoldpart_parser); +-} +- +-module_init(ofpart_parser_init); +-module_exit(ofpart_parser_exit); +- +-MODULE_LICENSE("GPL"); +-MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree"); +-MODULE_AUTHOR("Vitaly Wool, David Gibson"); +-/* +- * When MTD core cannot find the requested parser, it tries to load the module +- * with the same name. Since we provide the ofoldpart parser, we should have +- * the corresponding alias. +- */ +-MODULE_ALIAS("fixed-partitions"); +-MODULE_ALIAS("ofoldpart"); +--- /dev/null ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -0,0 +1,263 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Flash partitions described by the OF (or flattened) device tree ++ * ++ * Copyright © 2006 MontaVista Software Inc. ++ * Author: Vitaly Wool ++ * ++ * Revised to handle newer style flash binding by: ++ * Copyright © 2007 David Gibson, IBM Corporation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ofpart_bcm4908.h" ++ ++struct fixed_partitions_quirks { ++ int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); ++}; ++ ++struct fixed_partitions_quirks bcm4908_partitions_quirks = { ++ .post_parse = bcm4908_partitions_post_parse, ++}; ++ ++static const struct of_device_id parse_ofpart_match_table[]; ++ ++static bool node_has_compatible(struct device_node *pp) ++{ ++ return of_get_property(pp, "compatible", NULL); ++} ++ ++static int parse_fixed_partitions(struct mtd_info *master, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ const struct fixed_partitions_quirks *quirks; ++ const struct of_device_id *of_id; ++ struct mtd_partition *parts; ++ struct device_node *mtd_node; ++ struct device_node *ofpart_node; ++ const char *partname; ++ struct device_node *pp; ++ int nr_parts, i, ret = 0; ++ bool dedicated = true; ++ ++ /* Pull of_node from the master device node */ ++ mtd_node = mtd_get_of_node(master); ++ if (!mtd_node) ++ return 0; ++ ++ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); ++ if (!ofpart_node) { ++ /* ++ * We might get here even when ofpart isn't used at all (e.g., ++ * when using another parser), so don't be louder than ++ * KERN_DEBUG ++ */ ++ pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", ++ master->name, mtd_node); ++ ofpart_node = mtd_node; ++ dedicated = false; ++ } ++ ++ of_id = of_match_node(parse_ofpart_match_table, ofpart_node); ++ if (dedicated && !of_id) { ++ /* The 'partitions' subnode might be used by another parser */ ++ return 0; ++ } ++ ++ quirks = of_id ? of_id->data : NULL; ++ ++ /* First count the subnodes */ ++ nr_parts = 0; ++ for_each_child_of_node(ofpart_node, pp) { ++ if (!dedicated && node_has_compatible(pp)) ++ continue; ++ ++ nr_parts++; ++ } ++ ++ if (nr_parts == 0) ++ return 0; ++ ++ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); ++ if (!parts) ++ return -ENOMEM; ++ ++ i = 0; ++ for_each_child_of_node(ofpart_node, pp) { ++ const __be32 *reg; ++ int len; ++ int a_cells, s_cells; ++ ++ if (!dedicated && node_has_compatible(pp)) ++ continue; ++ ++ reg = of_get_property(pp, "reg", &len); ++ if (!reg) { ++ if (dedicated) { ++ pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n", ++ master->name, pp, ++ mtd_node); ++ goto ofpart_fail; ++ } else { ++ nr_parts--; ++ continue; ++ } ++ } ++ ++ a_cells = of_n_addr_cells(pp); ++ s_cells = of_n_size_cells(pp); ++ if (len / 4 != a_cells + s_cells) { ++ pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n", ++ master->name, pp, ++ mtd_node); ++ goto ofpart_fail; ++ } ++ ++ parts[i].offset = of_read_number(reg, a_cells); ++ parts[i].size = of_read_number(reg + a_cells, s_cells); ++ parts[i].of_node = pp; ++ ++ partname = of_get_property(pp, "label", &len); ++ if (!partname) ++ partname = of_get_property(pp, "name", &len); ++ parts[i].name = partname; ++ ++ if (of_get_property(pp, "read-only", &len)) ++ parts[i].mask_flags |= MTD_WRITEABLE; ++ ++ if (of_get_property(pp, "lock", &len)) ++ parts[i].mask_flags |= MTD_POWERUP_LOCK; ++ ++ if (of_property_read_bool(pp, "slc-mode")) ++ parts[i].add_flags |= MTD_SLC_ON_MLC_EMULATION; ++ ++ i++; ++ } ++ ++ if (!nr_parts) ++ goto ofpart_none; ++ ++ if (quirks && quirks->post_parse) ++ quirks->post_parse(master, parts, nr_parts); ++ ++ *pparts = parts; ++ return nr_parts; ++ ++ofpart_fail: ++ pr_err("%s: error parsing ofpart partition %pOF (%pOF)\n", ++ master->name, pp, mtd_node); ++ ret = -EINVAL; ++ofpart_none: ++ of_node_put(pp); ++ kfree(parts); ++ return ret; ++} ++ ++static const struct of_device_id parse_ofpart_match_table[] = { ++ /* Generic */ ++ { .compatible = "fixed-partitions" }, ++ /* Customized */ ++ { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); ++ ++static struct mtd_part_parser ofpart_parser = { ++ .parse_fn = parse_fixed_partitions, ++ .name = "fixed-partitions", ++ .of_match_table = parse_ofpart_match_table, ++}; ++ ++static int parse_ofoldpart_partitions(struct mtd_info *master, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct mtd_partition *parts; ++ struct device_node *dp; ++ int i, plen, nr_parts; ++ const struct { ++ __be32 offset, len; ++ } *part; ++ const char *names; ++ ++ /* Pull of_node from the master device node */ ++ dp = mtd_get_of_node(master); ++ if (!dp) ++ return 0; ++ ++ part = of_get_property(dp, "partitions", &plen); ++ if (!part) ++ return 0; /* No partitions found */ ++ ++ pr_warn("Device tree uses obsolete partition map binding: %pOF\n", dp); ++ ++ nr_parts = plen / sizeof(part[0]); ++ ++ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); ++ if (!parts) ++ return -ENOMEM; ++ ++ names = of_get_property(dp, "partition-names", &plen); ++ ++ for (i = 0; i < nr_parts; i++) { ++ parts[i].offset = be32_to_cpu(part->offset); ++ parts[i].size = be32_to_cpu(part->len) & ~1; ++ /* bit 0 set signifies read only partition */ ++ if (be32_to_cpu(part->len) & 1) ++ parts[i].mask_flags = MTD_WRITEABLE; ++ ++ if (names && (plen > 0)) { ++ int len = strlen(names) + 1; ++ ++ parts[i].name = names; ++ plen -= len; ++ names += len; ++ } else { ++ parts[i].name = "unnamed"; ++ } ++ ++ part++; ++ } ++ ++ *pparts = parts; ++ return nr_parts; ++} ++ ++static struct mtd_part_parser ofoldpart_parser = { ++ .parse_fn = parse_ofoldpart_partitions, ++ .name = "ofoldpart", ++}; ++ ++static int __init ofpart_parser_init(void) ++{ ++ register_mtd_parser(&ofpart_parser); ++ register_mtd_parser(&ofoldpart_parser); ++ return 0; ++} ++ ++static void __exit ofpart_parser_exit(void) ++{ ++ deregister_mtd_parser(&ofpart_parser); ++ deregister_mtd_parser(&ofoldpart_parser); ++} ++ ++module_init(ofpart_parser_init); ++module_exit(ofpart_parser_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree"); ++MODULE_AUTHOR("Vitaly Wool, David Gibson"); ++/* ++ * When MTD core cannot find the requested parser, it tries to load the module ++ * with the same name. Since we provide the ofoldpart parser, we should have ++ * the corresponding alias. ++ */ ++MODULE_ALIAS("fixed-partitions"); ++MODULE_ALIAS("ofoldpart"); diff --git a/target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch b/target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch new file mode 100644 index 0000000000..55a91d7680 --- /dev/null +++ b/target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch @@ -0,0 +1,69 @@ +From 2d751203aacf86a1b301a188d8551c7da91043ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 2 Mar 2021 20:00:12 +0100 +Subject: [PATCH] mtd: parsers: ofpart: limit parsing of deprecated DT syntax +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For backward compatibility ofpart still supports the old syntax like: +spi-flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x100000>; + }; +}; +(without "partitions" subnode). + +There is no reason however to support nested partitions without a clear +"compatible" string like: +partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x100000>; + + partition@0 { + label = "config"; + reg = <0x80000 0x80000>; + }; + }; +}; +(we never officially supported or documented that). + +Make sure ofpart doesn't attempt to parse above. + +Cc: Ansuel Smith +Signed-off-by: Rafał Miłecki +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210302190012.1255-1-zajec5@gmail.com +--- + drivers/mtd/parsers/ofpart_core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -53,7 +53,7 @@ static int parse_fixed_partitions(struct + return 0; + + ofpart_node = of_get_child_by_name(mtd_node, "partitions"); +- if (!ofpart_node) { ++ if (!ofpart_node && !master->parent) { + /* + * We might get here even when ofpart isn't used at all (e.g., + * when using another parser), so don't be louder than +@@ -64,6 +64,8 @@ static int parse_fixed_partitions(struct + ofpart_node = mtd_node; + dedicated = false; + } ++ if (!ofpart_node) ++ return 0; + + of_id = of_match_node(parse_ofpart_match_table, ofpart_node); + if (dedicated && !of_id) { diff --git a/target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch b/target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch new file mode 100644 index 0000000000..f1b778a6e1 --- /dev/null +++ b/target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch @@ -0,0 +1,34 @@ +From b87b6d2d6f540e29c3f98e1572d64e560d73d6c1 Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Thu, 4 Mar 2021 06:46:00 +0000 +Subject: [PATCH] mtd: parsers: ofpart: make symbol 'bcm4908_partitions_quirks' + static + +The sparse tool complains as follows: + +drivers/mtd/parsers/ofpart_core.c:25:32: warning: + symbol 'bcm4908_partitions_quirks' was not declared. Should it be static? + +This symbol is not used outside of ofpart_core.c, so this +commit marks it static. + +Fixes: 457da931b608 ("mtd: parsers: ofpart: support BCM4908 fixed partitions") +Reported-by: Hulk Robot +Signed-off-by: Wei Yongjun +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210304064600.3279138-1-weiyongjun1@huawei.com +--- + drivers/mtd/parsers/ofpart_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -22,7 +22,7 @@ struct fixed_partitions_quirks { + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); + }; + +-struct fixed_partitions_quirks bcm4908_partitions_quirks = { ++static struct fixed_partitions_quirks bcm4908_partitions_quirks = { + .post_parse = bcm4908_partitions_post_parse, + }; + diff --git a/target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch b/target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch new file mode 100644 index 0000000000..28335cb71f --- /dev/null +++ b/target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch @@ -0,0 +1,38 @@ +From a5d83d6e2bc747b13f347962d4b335d70b23559b Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 12 Mar 2021 07:28:19 +0100 +Subject: [PATCH] mtd: core: add nvmem-cells compatible to parse mtd as nvmem + cells +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Partitions that contains the nvmem-cells compatible will register +their direct subonodes as nvmem cells and the node will be treated as a +nvmem provider. + +Signed-off-by: Ansuel Smith +Tested-by: Rafał Miłecki +--- + drivers/mtd/mtdcore.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -531,6 +531,7 @@ static int mtd_nvmem_reg_read(void *priv + + static int mtd_nvmem_add(struct mtd_info *mtd) + { ++ struct device_node *node = mtd_get_of_node(mtd); + struct nvmem_config config = {}; + + config.id = -1; +@@ -543,7 +544,7 @@ static int mtd_nvmem_add(struct mtd_info + config.stride = 1; + config.read_only = true; + config.root_only = true; +- config.no_of_node = true; ++ config.no_of_node = !of_device_is_compatible(node, "nvmem-cells"); + config.priv = mtd; + + mtd->nvmem = nvmem_register(&config); diff --git a/target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch b/target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch new file mode 100644 index 0000000000..14ea3f6b8c --- /dev/null +++ b/target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch @@ -0,0 +1,25 @@ +From 42645976c3289b03a12f1bd2bc131fd98fc27170 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 12 Mar 2021 07:28:20 +0100 +Subject: [PATCH] devicetree: nvmem: nvmem: drop $nodename restriction + +Drop $nodename restriction as now mtd partition can also be used as +nvmem provider. + +Signed-off-by: Ansuel Smith +--- + Documentation/devicetree/bindings/nvmem/nvmem.yaml | 3 --- + 1 file changed, 3 deletions(-) + +--- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml ++++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml +@@ -20,9 +20,6 @@ description: | + storage device. + + properties: +- $nodename: +- pattern: "^(eeprom|efuse|nvram)(@.*|-[0-9a-f])*$" +- + "#address-cells": + const: 1 + diff --git a/target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch b/target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch new file mode 100644 index 0000000000..0eb4c637cf --- /dev/null +++ b/target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch @@ -0,0 +1,117 @@ +From 377aa0135dc8489312edd3184d143ce3a89ff7ee Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 12 Mar 2021 07:28:21 +0100 +Subject: [PATCH] dt-bindings: mtd: Document use of nvmem-cells compatible + +Document nvmem-cells compatible used to treat mtd partitions as a +nvmem provider. + +Signed-off-by: Ansuel Smith +Reviewed-by: Rob Herring +--- + .../bindings/mtd/partitions/nvmem-cells.yaml | 99 +++++++++++++++++++ + 1 file changed, 99 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml +@@ -0,0 +1,99 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/nvmem-cells.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Nvmem cells ++ ++description: | ++ Any partition containing the compatible "nvmem-cells" will register as a ++ nvmem provider. ++ Each direct subnodes represents a nvmem cell following the nvmem binding. ++ Nvmem binding to declare nvmem-cells can be found in: ++ Documentation/devicetree/bindings/nvmem/nvmem.yaml ++ ++maintainers: ++ - Ansuel Smith ++ ++allOf: ++ - $ref: /schemas/nvmem/nvmem.yaml# ++ ++properties: ++ compatible: ++ const: nvmem-cells ++ ++required: ++ - compatible ++ ++additionalProperties: true ++ ++examples: ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ /* ... */ ++ ++ }; ++ art: art@1200000 { ++ compatible = "nvmem-cells"; ++ reg = <0x1200000 0x0140000>; ++ label = "art"; ++ read-only; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr_gmac1: macaddr_gmac1@0 { ++ reg = <0x0 0x6>; ++ }; ++ ++ macaddr_gmac2: macaddr_gmac2@6 { ++ reg = <0x6 0x6>; ++ }; ++ ++ pre_cal_24g: pre_cal_24g@1000 { ++ reg = <0x1000 0x2f20>; ++ }; ++ ++ pre_cal_5g: pre_cal_5g@5000{ ++ reg = <0x5000 0x2f20>; ++ }; ++ }; ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bootloader"; ++ reg = <0x000000 0x100000>; ++ read-only; ++ }; ++ ++ firmware@100000 { ++ compatible = "brcm,trx"; ++ label = "firmware"; ++ reg = <0x100000 0xe00000>; ++ }; ++ ++ calibration@f00000 { ++ compatible = "nvmem-cells"; ++ label = "calibration"; ++ reg = <0xf00000 0x100000>; ++ ranges = <0 0xf00000 0x100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ wifi0@0 { ++ reg = <0x000000 0x080000>; ++ }; ++ ++ wifi1@80000 { ++ reg = <0x080000 0x080000>; ++ }; ++ }; ++ }; diff --git a/target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch b/target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch new file mode 100644 index 0000000000..35a4afd67b --- /dev/null +++ b/target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch @@ -0,0 +1,98 @@ +From 2fa7294175c76e1ec568aa75c1891fd908728c8d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 12 Mar 2021 14:49:18 +0100 +Subject: [PATCH] dt-bindings: mtd: add binding for Linksys Northstar + partitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Linksys on Broadcom Northstar devices uses fixed flash layout with +multiple firmware partitions. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Rob Herring +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210312134919.7767-1-zajec5@gmail.com +--- + .../mtd/partitions/linksys,ns-partitions.yaml | 74 +++++++++++++++++++ + 1 file changed, 74 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml +@@ -0,0 +1,74 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/linksys,ns-partitions.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Linksys Northstar partitioning ++ ++description: | ++ Linksys devices based on Broadcom Northstar architecture often use two ++ firmware partitions. One is used for regular booting, the other is treated as ++ fallback. ++ ++ This binding allows defining all fixed partitions and marking those containing ++ firmware. System can use that information e.g. for booting or flashing ++ purposes. ++ ++maintainers: ++ - Rafał Miłecki ++ ++properties: ++ compatible: ++ const: linksys,ns-partitions ++ ++ "#address-cells": ++ enum: [ 1, 2 ] ++ ++ "#size-cells": ++ enum: [ 1, 2 ] ++ ++patternProperties: ++ "^partition@[0-9a-f]+$": ++ $ref: "partition.yaml#" ++ properties: ++ compatible: ++ items: ++ - const: linksys,ns-firmware ++ - const: brcm,trx ++ unevaluatedProperties: false ++ ++required: ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ partitions { ++ compatible = "linksys,ns-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "boot"; ++ reg = <0x0 0x100000>; ++ read-only; ++ }; ++ ++ partition@100000 { ++ label = "nvram"; ++ reg = <0x100000 0x100000>; ++ }; ++ ++ partition@200000 { ++ compatible = "linksys,ns-firmware", "brcm,trx"; ++ reg = <0x200000 0xf00000>; ++ }; ++ ++ partition@1100000 { ++ compatible = "linksys,ns-firmware", "brcm,trx"; ++ reg = <0x1100000 0xf00000>; ++ }; ++ }; diff --git a/target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch b/target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch new file mode 100644 index 0000000000..f317889785 --- /dev/null +++ b/target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch @@ -0,0 +1,156 @@ +From 7134a2d026d942210b4d26d6059c9d979ca7866e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 12 Mar 2021 14:49:19 +0100 +Subject: [PATCH] mtd: parsers: ofpart: support Linksys Northstar partitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows extending ofpart parser with support for Linksys Northstar +devices. That support uses recently added quirks mechanism. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210312134919.7767-2-zajec5@gmail.com +--- + drivers/mtd/parsers/Kconfig | 10 +++++ + drivers/mtd/parsers/Makefile | 1 + + drivers/mtd/parsers/ofpart_core.c | 6 +++ + drivers/mtd/parsers/ofpart_linksys_ns.c | 50 +++++++++++++++++++++++++ + drivers/mtd/parsers/ofpart_linksys_ns.h | 18 +++++++++ + 5 files changed, 85 insertions(+) + create mode 100644 drivers/mtd/parsers/ofpart_linksys_ns.c + create mode 100644 drivers/mtd/parsers/ofpart_linksys_ns.h + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -76,6 +76,16 @@ config MTD_OF_PARTS_BCM4908 + that can have multiple "firmware" partitions. It takes care of + finding currently used one and backup ones. + ++config MTD_OF_PARTS_LINKSYS_NS ++ bool "Linksys Northstar partitioning support" ++ depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST) ++ default ARCH_BCM_5301X ++ help ++ This provides partitions parser for Linksys devices based on Broadcom ++ Northstar architecture. Linksys commonly uses fixed flash layout with ++ two "firmware" partitions. Currently used firmware has to be detected ++ using CFE environment variable. ++ + config MTD_PARSER_IMAGETAG + tristate "Parser for BCM963XX Image Tag format partitions" + depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdl + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o + ofpart-y += ofpart_core.o + ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o ++ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o + obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -17,6 +17,7 @@ + #include + + #include "ofpart_bcm4908.h" ++#include "ofpart_linksys_ns.h" + + struct fixed_partitions_quirks { + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); +@@ -26,6 +27,10 @@ static struct fixed_partitions_quirks bc + .post_parse = bcm4908_partitions_post_parse, + }; + ++static struct fixed_partitions_quirks linksys_ns_partitions_quirks = { ++ .post_parse = linksys_ns_partitions_post_parse, ++}; ++ + static const struct of_device_id parse_ofpart_match_table[]; + + static bool node_has_compatible(struct device_node *pp) +@@ -167,6 +172,7 @@ static const struct of_device_id parse_o + { .compatible = "fixed-partitions" }, + /* Customized */ + { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, }, ++ { .compatible = "linksys,ns-partitions", .data = &linksys_ns_partitions_quirks, }, + {}, + }; + MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); +--- /dev/null ++++ b/drivers/mtd/parsers/ofpart_linksys_ns.c +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2021 Rafał Miłecki ++ */ ++ ++#include ++#include ++#include ++ ++#include "ofpart_linksys_ns.h" ++ ++#define NVRAM_BOOT_PART "bootpartition" ++ ++static int ofpart_linksys_ns_bootpartition(void) ++{ ++ char buf[4]; ++ int bootpartition; ++ ++ /* Check CFE environment variable */ ++ if (bcm47xx_nvram_getenv(NVRAM_BOOT_PART, buf, sizeof(buf)) > 0) { ++ if (!kstrtoint(buf, 0, &bootpartition)) ++ return bootpartition; ++ pr_warn("Failed to parse %s value \"%s\"\n", NVRAM_BOOT_PART, ++ buf); ++ } else { ++ pr_warn("Failed to get NVRAM \"%s\"\n", NVRAM_BOOT_PART); ++ } ++ ++ return 0; ++} ++ ++int linksys_ns_partitions_post_parse(struct mtd_info *mtd, ++ struct mtd_partition *parts, ++ int nr_parts) ++{ ++ int bootpartition = ofpart_linksys_ns_bootpartition(); ++ int trx_idx = 0; ++ int i; ++ ++ for (i = 0; i < nr_parts; i++) { ++ if (of_device_is_compatible(parts[i].of_node, "linksys,ns-firmware")) { ++ if (trx_idx++ == bootpartition) ++ parts[i].name = "firmware"; ++ else ++ parts[i].name = "backup"; ++ } ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/mtd/parsers/ofpart_linksys_ns.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __OFPART_LINKSYS_NS_H ++#define __OFPART_LINKSYS_NS_H ++ ++#ifdef CONFIG_MTD_OF_PARTS_LINKSYS_NS ++int linksys_ns_partitions_post_parse(struct mtd_info *mtd, ++ struct mtd_partition *parts, ++ int nr_parts); ++#else ++static inline int linksys_ns_partitions_post_parse(struct mtd_info *mtd, ++ struct mtd_partition *parts, ++ int nr_parts) ++{ ++ return -EOPNOTSUPP; ++} ++#endif ++ ++#endif diff --git a/target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch b/target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch new file mode 100644 index 0000000000..3af641e62e --- /dev/null +++ b/target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch @@ -0,0 +1,54 @@ +From 7e4404113686868858a34210c28ae122e967aa64 Mon Sep 17 00:00:00 2001 +From: Mauri Sandberg +Date: Tue, 9 Mar 2021 19:48:59 +0200 +Subject: [PATCH] mtd: cfi_cmdset_0002: Disable buffered writes for AMD chip + 0x2201 + +Buffer writes do not work with AMD chip 0x2201. The chip in question +is a AMD/Spansion/Cypress Semiconductor S29GL256N and datasheet [1] +talks about writing buffers being possible. While waiting for a neater +solution resort to writing word-sized chunks only. + +Without the patch kernel logs will be flooded with entries like below: + +jffs2_scan_eraseblock(): End of filesystem marker found at 0x0 +jffs2_build_filesystem(): unlocking the mtd device... +done. +jffs2_build_filesystem(): erasing all blocks after the end marker... +MTD do_write_buffer_wait(): software timeout, address:0x01ec000a. +jffs2: Write clean marker to block at 0x01920000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01e2000a. +jffs2: Write clean marker to block at 0x01880000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01e0000a. +jffs2: Write clean marker to block at 0x01860000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01dc000a. +jffs2: Write clean marker to block at 0x01820000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01da000a. +jffs2: Write clean marker to block at 0x01800000 failed: -5 +... + +Tested on a Buffalo wzr-hp-g300nh running kernel 5.10.16. + +[1] https://www.cypress.com/file/219941/download +or https://datasheetspdf.com/pdf-file/565708/SPANSION/S29GL256N/1 + +Signed-off-by: Mauri Sandberg +Signed-off-by: Vignesh Raghavendra +Link: https://lore.kernel.org/r/20210309174859.362060-1-sandberg@mailfence.com +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -272,6 +272,10 @@ static void fixup_use_write_buffers(stru + { + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; ++ ++ if (cfi->mfr == CFI_MFR_AMD && cfi->id == 0x2201) ++ return; ++ + if (cfi->cfiq->BufWriteTimeoutTyp) { + pr_debug("Using buffer write method\n"); + mtd->_write = cfi_amdstd_write_buffers; diff --git a/target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch b/target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch new file mode 100644 index 0000000000..1f34652141 --- /dev/null +++ b/target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch @@ -0,0 +1,32 @@ +From a4d82940ff85a7e307953dfa715f65d5ab487e10 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 18 Apr 2021 23:46:14 +0200 +Subject: dt-bindings: mtd: brcm,trx: Add brcm,trx-magic + +This adds the description of an additional property which allows to +specify a custom partition parser magic to detect a trx partition. +Buffalo has multiple device which are using the trx format, but with +different magic values. + +Signed-off-by: Hauke Mehrtens +Acked-by: Rob Herring +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-2-hauke@hauke-m.de +--- + .../devicetree/bindings/mtd/partitions/brcm,trx.txt | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt ++++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt +@@ -28,6 +28,11 @@ detected by a software parsing TRX heade + Required properties: + - compatible : (required) must be "brcm,trx" + ++Optional properties: ++ ++- brcm,trx-magic: TRX magic, if it is different from the default magic ++ 0x30524448 as a u32. ++ + Example: + + flash@0 { diff --git a/target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch b/target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch new file mode 100644 index 0000000000..de2d914852 --- /dev/null +++ b/target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch @@ -0,0 +1,50 @@ +From d7f7e04f8b67571a4bf5a0dcd4f9da4214f5262c Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 18 Apr 2021 23:46:15 +0200 +Subject: mtd: parsers: trx: Allow to specify brcm, trx-magic in DT + +Buffalo uses a different TRX magic for every device, to be able to use +this trx parser, make it possible to specify the TRX magic in device +tree. If no TRX magic is specified in device tree, the standard value +will be used. This value should only be specified if a vendor chooses to +use a non standard TRX magic. + +Signed-off-by: Hauke Mehrtens +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-3-hauke@hauke-m.de +--- + drivers/mtd/parsers/parser_trx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/parsers/parser_trx.c ++++ b/drivers/mtd/parsers/parser_trx.c +@@ -51,13 +51,20 @@ static int parser_trx_parse(struct mtd_i + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) + { ++ struct device_node *np = mtd_get_of_node(mtd); + struct mtd_partition *parts; + struct mtd_partition *part; + struct trx_header trx; + size_t bytes_read; + uint8_t curr_part = 0, i = 0; ++ uint32_t trx_magic = TRX_MAGIC; + int err; + ++ /* Get different magic from device tree if specified */ ++ err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic); ++ if (err != 0 && err != -EINVAL) ++ pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err); ++ + parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), + GFP_KERNEL); + if (!parts) +@@ -70,7 +77,7 @@ static int parser_trx_parse(struct mtd_i + return err; + } + +- if (trx.magic != TRX_MAGIC) { ++ if (trx.magic != trx_magic) { + kfree(parts); + return -ENOENT; + } diff --git a/target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch b/target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch new file mode 100644 index 0000000000..faac535270 --- /dev/null +++ b/target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch @@ -0,0 +1,25 @@ +From 81bb218c829246962a6327c64eec18ddcc049936 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 18 Apr 2021 23:46:16 +0200 +Subject: mtd: parsers: trx: Allow to use TRX parser on Mediatek SoCs + +Buffalo uses the TRX partition format also on Mediatek MT7622 SoCs. + +Signed-off-by: Hauke Mehrtens +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-4-hauke@hauke-m.de +--- + drivers/mtd/parsers/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -115,7 +115,7 @@ config MTD_AFS_PARTS + + config MTD_PARSER_TRX + tristate "Parser for TRX format partitions" +- depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) ++ depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST) + help + TRX is a firmware format used by Broadcom on their devices. It + may contain up to 3/4 partitions (depending on the version). diff --git a/target/linux/generic/backport-5.15/410-mtd-next-mtd-parsers-trx-allow-to-use-on-MediaTek-MIPS-SoCs.patch b/target/linux/generic/backport-5.15/410-mtd-next-mtd-parsers-trx-allow-to-use-on-MediaTek-MIPS-SoCs.patch new file mode 100644 index 0000000000..5c49841760 --- /dev/null +++ b/target/linux/generic/backport-5.15/410-mtd-next-mtd-parsers-trx-allow-to-use-on-MediaTek-MIPS-SoCs.patch @@ -0,0 +1,33 @@ +From 2365f91c861cbfeef7141c69842848c7b2d3c2db Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Sun, 13 Feb 2022 15:40:44 +0900 +Subject: [PATCH] mtd: parsers: trx: allow to use on MediaTek MIPS SoCs + +Buffalo sells some router devices which have trx-formatted firmware, +based on MediaTek MIPS SoCs. To use parser_trx on those devices, add +"RALINK" to dependency and allow to compile for MediaTek MIPS SoCs. + +examples: + +- WCR-1166DS (MT7628) +- WSR-1166DHP (MT7621) +- WSR-2533DHP (MT7621) + +Signed-off-by: INAGAKI Hiroshi +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220213064045.1781-1-musashino.open@gmail.com +--- + drivers/mtd/parsers/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -115,7 +115,7 @@ config MTD_AFS_PARTS + + config MTD_PARSER_TRX + tristate "Parser for TRX format partitions" +- depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST) ++ depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST) + help + TRX is a firmware format used by Broadcom on their devices. It + may contain up to 3/4 partitions (depending on the version). diff --git a/target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch b/target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch new file mode 100644 index 0000000000..dd50c19c27 --- /dev/null +++ b/target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch @@ -0,0 +1,25 @@ +From dcdf415b740923530dc71d89fecc8361078473f5 Mon Sep 17 00:00:00 2001 +From: Rui Salvaterra +Date: Mon, 5 Apr 2021 16:11:55 +0100 +Subject: [PATCH] ubifs: default to zstd compression + +Compared to lzo and zlib, zstd is the best all-around performer, both in terms +of speed and compression ratio. Set it as the default, if available. + +Signed-off-by: Rui Salvaterra +--- + fs/ubifs/sb.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/ubifs/sb.c ++++ b/fs/ubifs/sb.c +@@ -53,6 +53,9 @@ + + static int get_default_compressor(struct ubifs_info *c) + { ++ if (ubifs_compr_present(c, UBIFS_COMPR_ZSTD)) ++ return UBIFS_COMPR_ZSTD; ++ + if (ubifs_compr_present(c, UBIFS_COMPR_LZO)) + return UBIFS_COMPR_LZO; + diff --git a/target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch b/target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch new file mode 100644 index 0000000000..1fca4a5e74 --- /dev/null +++ b/target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch @@ -0,0 +1,88 @@ +From: Felix Fietkau +Date: Mon, 8 Feb 2021 11:34:08 -0800 +Subject: [PATCH] net: extract napi poll functionality to __napi_poll() + +This commit introduces a new function __napi_poll() which does the main +logic of the existing napi_poll() function, and will be called by other +functions in later commits. +This idea and implementation is done by Felix Fietkau and +is proposed as part of the patch to move napi work to work_queue +context. +This commit by itself is a code restructure. + +Signed-off-by: Felix Fietkau +Signed-off-by: Wei Wang +Reviewed-by: Alexander Duyck +Signed-off-by: David S. Miller +--- + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6805,15 +6805,10 @@ void __netif_napi_del(struct napi_struct + } + EXPORT_SYMBOL(__netif_napi_del); + +-static int napi_poll(struct napi_struct *n, struct list_head *repoll) ++static int __napi_poll(struct napi_struct *n, bool *repoll) + { +- void *have; + int work, weight; + +- list_del_init(&n->poll_list); +- +- have = netpoll_poll_lock(n); +- + weight = n->weight; + + /* This NAPI_STATE_SCHED test is for avoiding a race +@@ -6833,7 +6828,7 @@ static int napi_poll(struct napi_struct + n->poll, work, weight); + + if (likely(work < weight)) +- goto out_unlock; ++ return work; + + /* Drivers must not modify the NAPI state if they + * consume the entire weight. In such cases this code +@@ -6842,7 +6837,7 @@ static int napi_poll(struct napi_struct + */ + if (unlikely(napi_disable_pending(n))) { + napi_complete(n); +- goto out_unlock; ++ return work; + } + + if (n->gro_bitmask) { +@@ -6860,12 +6855,29 @@ static int napi_poll(struct napi_struct + if (unlikely(!list_empty(&n->poll_list))) { + pr_warn_once("%s: Budget exhausted after napi rescheduled\n", + n->dev ? n->dev->name : "backlog"); +- goto out_unlock; ++ return work; + } + +- list_add_tail(&n->poll_list, repoll); ++ *repoll = true; ++ ++ return work; ++} ++ ++static int napi_poll(struct napi_struct *n, struct list_head *repoll) ++{ ++ bool do_repoll = false; ++ void *have; ++ int work; ++ ++ list_del_init(&n->poll_list); ++ ++ have = netpoll_poll_lock(n); ++ ++ work = __napi_poll(n, &do_repoll); ++ ++ if (do_repoll) ++ list_add_tail(&n->poll_list, repoll); + +-out_unlock: + netpoll_poll_unlock(have); + + return work; diff --git a/target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch b/target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch new file mode 100644 index 0000000000..38e276ef72 --- /dev/null +++ b/target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch @@ -0,0 +1,261 @@ +From: Wei Wang +Date: Mon, 8 Feb 2021 11:34:09 -0800 +Subject: [PATCH] net: implement threaded-able napi poll loop support + +This patch allows running each napi poll loop inside its own +kernel thread. +The kthread is created during netif_napi_add() if dev->threaded +is set. And threaded mode is enabled in napi_enable(). We will +provide a way to set dev->threaded and enable threaded mode +without a device up/down in the following patch. + +Once that threaded mode is enabled and the kthread is +started, napi_schedule() will wake-up such thread instead +of scheduling the softirq. + +The threaded poll loop behaves quite likely the net_rx_action, +but it does not have to manipulate local irqs and uses +an explicit scheduling point based on netdev_budget. + +Co-developed-by: Paolo Abeni +Signed-off-by: Paolo Abeni +Co-developed-by: Hannes Frederic Sowa +Signed-off-by: Hannes Frederic Sowa +Co-developed-by: Jakub Kicinski +Signed-off-by: Jakub Kicinski +Signed-off-by: Wei Wang +Reviewed-by: Alexander Duyck +Signed-off-by: David S. Miller +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -347,6 +347,7 @@ struct napi_struct { + struct list_head dev_list; + struct hlist_node napi_hash_node; + unsigned int napi_id; ++ struct task_struct *thread; + }; + + enum { +@@ -357,6 +358,7 @@ enum { + NAPI_STATE_LISTED, /* NAPI added to system lists */ + NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ + NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ ++ NAPI_STATE_THREADED, /* The poll is performed inside its own thread*/ + }; + + enum { +@@ -367,6 +369,7 @@ enum { + NAPIF_STATE_LISTED = BIT(NAPI_STATE_LISTED), + NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), + NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), ++ NAPIF_STATE_THREADED = BIT(NAPI_STATE_THREADED), + }; + + enum gro_result { +@@ -497,20 +500,7 @@ static inline bool napi_complete(struct + */ + void napi_disable(struct napi_struct *n); + +-/** +- * napi_enable - enable NAPI scheduling +- * @n: NAPI context +- * +- * Resume NAPI from being scheduled on this context. +- * Must be paired with napi_disable. +- */ +-static inline void napi_enable(struct napi_struct *n) +-{ +- BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); +- smp_mb__before_atomic(); +- clear_bit(NAPI_STATE_SCHED, &n->state); +- clear_bit(NAPI_STATE_NPSVC, &n->state); +-} ++void napi_enable(struct napi_struct *n); + + /** + * napi_synchronize - wait until NAPI is not running +@@ -1842,6 +1832,8 @@ enum netdev_ml_priv_type { + * + * @wol_enabled: Wake-on-LAN is enabled + * ++ * @threaded: napi threaded mode is enabled ++ * + * @net_notifier_list: List of per-net netdev notifier block + * that follow this device when it is moved + * to another network namespace. +@@ -2161,6 +2153,7 @@ struct net_device { + struct lock_class_key *qdisc_running_key; + bool proto_down; + unsigned wol_enabled:1; ++ unsigned threaded:1; + + struct list_head net_notifier_list; + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -91,6 +91,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1500,6 +1501,27 @@ void netdev_notify_peers(struct net_devi + } + EXPORT_SYMBOL(netdev_notify_peers); + ++static int napi_threaded_poll(void *data); ++ ++static int napi_kthread_create(struct napi_struct *n) ++{ ++ int err = 0; ++ ++ /* Create and wake up the kthread once to put it in ++ * TASK_INTERRUPTIBLE mode to avoid the blocked task ++ * warning and work with loadavg. ++ */ ++ n->thread = kthread_run(napi_threaded_poll, n, "napi/%s-%d", ++ n->dev->name, n->napi_id); ++ if (IS_ERR(n->thread)) { ++ err = PTR_ERR(n->thread); ++ pr_err("kthread_run failed with err %d\n", err); ++ n->thread = NULL; ++ } ++ ++ return err; ++} ++ + static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack) + { + const struct net_device_ops *ops = dev->netdev_ops; +@@ -4267,6 +4289,21 @@ int gro_normal_batch __read_mostly = 8; + static inline void ____napi_schedule(struct softnet_data *sd, + struct napi_struct *napi) + { ++ struct task_struct *thread; ++ ++ if (test_bit(NAPI_STATE_THREADED, &napi->state)) { ++ /* Paired with smp_mb__before_atomic() in ++ * napi_enable(). Use READ_ONCE() to guarantee ++ * a complete read on napi->thread. Only call ++ * wake_up_process() when it's not NULL. ++ */ ++ thread = READ_ONCE(napi->thread); ++ if (thread) { ++ wake_up_process(thread); ++ return; ++ } ++ } ++ + list_add_tail(&napi->poll_list, &sd->poll_list); + __raise_softirq_irqoff(NET_RX_SOFTIRQ); + } +@@ -6758,6 +6795,12 @@ void netif_napi_add(struct net_device *d + set_bit(NAPI_STATE_NPSVC, &napi->state); + list_add_rcu(&napi->dev_list, &dev->napi_list); + napi_hash_add(napi); ++ /* Create kthread for this napi if dev->threaded is set. ++ * Clear dev->threaded if kthread creation failed so that ++ * threaded mode will not be enabled in napi_enable(). ++ */ ++ if (dev->threaded && napi_kthread_create(napi)) ++ dev->threaded = 0; + } + EXPORT_SYMBOL(netif_napi_add); + +@@ -6774,9 +6817,28 @@ void napi_disable(struct napi_struct *n) + hrtimer_cancel(&n->timer); + + clear_bit(NAPI_STATE_DISABLE, &n->state); ++ clear_bit(NAPI_STATE_THREADED, &n->state); + } + EXPORT_SYMBOL(napi_disable); + ++/** ++ * napi_enable - enable NAPI scheduling ++ * @n: NAPI context ++ * ++ * Resume NAPI from being scheduled on this context. ++ * Must be paired with napi_disable. ++ */ ++void napi_enable(struct napi_struct *n) ++{ ++ BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); ++ smp_mb__before_atomic(); ++ clear_bit(NAPI_STATE_SCHED, &n->state); ++ clear_bit(NAPI_STATE_NPSVC, &n->state); ++ if (n->dev->threaded && n->thread) ++ set_bit(NAPI_STATE_THREADED, &n->state); ++} ++EXPORT_SYMBOL(napi_enable); ++ + static void flush_gro_hash(struct napi_struct *napi) + { + int i; +@@ -6802,6 +6864,11 @@ void __netif_napi_del(struct napi_struct + + flush_gro_hash(napi); + napi->gro_bitmask = 0; ++ ++ if (napi->thread) { ++ kthread_stop(napi->thread); ++ napi->thread = NULL; ++ } + } + EXPORT_SYMBOL(__netif_napi_del); + +@@ -6883,6 +6950,51 @@ static int napi_poll(struct napi_struct + return work; + } + ++static int napi_thread_wait(struct napi_struct *napi) ++{ ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ while (!kthread_should_stop() && !napi_disable_pending(napi)) { ++ if (test_bit(NAPI_STATE_SCHED, &napi->state)) { ++ WARN_ON(!list_empty(&napi->poll_list)); ++ __set_current_state(TASK_RUNNING); ++ return 0; ++ } ++ ++ schedule(); ++ set_current_state(TASK_INTERRUPTIBLE); ++ } ++ __set_current_state(TASK_RUNNING); ++ return -1; ++} ++ ++static int napi_threaded_poll(void *data) ++{ ++ struct napi_struct *napi = data; ++ void *have; ++ ++ while (!napi_thread_wait(napi)) { ++ for (;;) { ++ bool repoll = false; ++ ++ local_bh_disable(); ++ ++ have = netpoll_poll_lock(napi); ++ __napi_poll(napi, &repoll); ++ netpoll_poll_unlock(have); ++ ++ __kfree_skb_flush(); ++ local_bh_enable(); ++ ++ if (!repoll) ++ break; ++ ++ cond_resched(); ++ } ++ } ++ return 0; ++} ++ + static __latent_entropy void net_rx_action(struct softirq_action *h) + { + struct softnet_data *sd = this_cpu_ptr(&softnet_data); diff --git a/target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch b/target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch new file mode 100644 index 0000000000..c3119a6e9b --- /dev/null +++ b/target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch @@ -0,0 +1,177 @@ +From: Wei Wang +Date: Mon, 8 Feb 2021 11:34:10 -0800 +Subject: [PATCH] net: add sysfs attribute to control napi threaded mode + +This patch adds a new sysfs attribute to the network device class. +Said attribute provides a per-device control to enable/disable the +threaded mode for all the napi instances of the given network device, +without the need for a device up/down. +User sets it to 1 or 0 to enable or disable threaded mode. +Note: when switching between threaded and the current softirq based mode +for a napi instance, it will not immediately take effect if the napi is +currently being polled. The mode switch will happen for the next time +napi_schedule() is called. + +Co-developed-by: Paolo Abeni +Signed-off-by: Paolo Abeni +Co-developed-by: Hannes Frederic Sowa +Signed-off-by: Hannes Frederic Sowa +Co-developed-by: Felix Fietkau +Signed-off-by: Felix Fietkau +Signed-off-by: Wei Wang +Reviewed-by: Alexander Duyck +Signed-off-by: David S. Miller +--- + +--- a/Documentation/ABI/testing/sysfs-class-net ++++ b/Documentation/ABI/testing/sysfs-class-net +@@ -337,3 +337,18 @@ Contact: netdev@vger.kernel.org + Description: + 32-bit unsigned integer counting the number of times the link has + been down ++ ++What: /sys/class/net//threaded ++Date: Jan 2021 ++KernelVersion: 5.12 ++Contact: netdev@vger.kernel.org ++Description: ++ Boolean value to control the threaded mode per device. User could ++ set this value to enable/disable threaded mode for all napi ++ belonging to this device, without the need to do device up/down. ++ ++ Possible values: ++ == ================================== ++ 0 threaded mode disabled for this dev ++ 1 threaded mode enabled for this dev ++ == ================================== +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -491,6 +491,8 @@ static inline bool napi_complete(struct + return napi_complete_done(n, 0); + } + ++int dev_set_threaded(struct net_device *dev, bool threaded); ++ + /** + * napi_disable - prevent NAPI from scheduling + * @n: NAPI context +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4293,8 +4293,9 @@ static inline void ____napi_schedule(str + + if (test_bit(NAPI_STATE_THREADED, &napi->state)) { + /* Paired with smp_mb__before_atomic() in +- * napi_enable(). Use READ_ONCE() to guarantee +- * a complete read on napi->thread. Only call ++ * napi_enable()/dev_set_threaded(). ++ * Use READ_ONCE() to guarantee a complete ++ * read on napi->thread. Only call + * wake_up_process() when it's not NULL. + */ + thread = READ_ONCE(napi->thread); +@@ -6768,6 +6769,49 @@ static void init_gro_hash(struct napi_st + napi->gro_bitmask = 0; + } + ++int dev_set_threaded(struct net_device *dev, bool threaded) ++{ ++ struct napi_struct *napi; ++ int err = 0; ++ ++ if (dev->threaded == threaded) ++ return 0; ++ ++ if (threaded) { ++ list_for_each_entry(napi, &dev->napi_list, dev_list) { ++ if (!napi->thread) { ++ err = napi_kthread_create(napi); ++ if (err) { ++ threaded = false; ++ break; ++ } ++ } ++ } ++ } ++ ++ dev->threaded = threaded; ++ ++ /* Make sure kthread is created before THREADED bit ++ * is set. ++ */ ++ smp_mb__before_atomic(); ++ ++ /* Setting/unsetting threaded mode on a napi might not immediately ++ * take effect, if the current napi instance is actively being ++ * polled. In this case, the switch between threaded mode and ++ * softirq mode will happen in the next round of napi_schedule(). ++ * This should not cause hiccups/stalls to the live traffic. ++ */ ++ list_for_each_entry(napi, &dev->napi_list, dev_list) { ++ if (threaded) ++ set_bit(NAPI_STATE_THREADED, &napi->state); ++ else ++ clear_bit(NAPI_STATE_THREADED, &napi->state); ++ } ++ ++ return err; ++} ++ + void netif_napi_add(struct net_device *dev, struct napi_struct *napi, + int (*poll)(struct napi_struct *, int), int weight) + { +--- a/net/core/net-sysfs.c ++++ b/net/core/net-sysfs.c +@@ -587,6 +587,45 @@ static ssize_t phys_switch_id_show(struc + } + static DEVICE_ATTR_RO(phys_switch_id); + ++static ssize_t threaded_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *netdev = to_net_dev(dev); ++ ssize_t ret = -EINVAL; ++ ++ if (!rtnl_trylock()) ++ return restart_syscall(); ++ ++ if (dev_isalive(netdev)) ++ ret = sprintf(buf, fmt_dec, netdev->threaded); ++ ++ rtnl_unlock(); ++ return ret; ++} ++ ++static int modify_napi_threaded(struct net_device *dev, unsigned long val) ++{ ++ int ret; ++ ++ if (list_empty(&dev->napi_list)) ++ return -EOPNOTSUPP; ++ ++ if (val != 0 && val != 1) ++ return -EOPNOTSUPP; ++ ++ ret = dev_set_threaded(dev, val); ++ ++ return ret; ++} ++ ++static ssize_t threaded_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ return netdev_store(dev, attr, buf, len, modify_napi_threaded); ++} ++static DEVICE_ATTR_RW(threaded); ++ + static struct attribute *net_class_attrs[] __ro_after_init = { + &dev_attr_netdev_group.attr, + &dev_attr_type.attr, +@@ -619,6 +658,7 @@ static struct attribute *net_class_attrs + &dev_attr_proto_down.attr, + &dev_attr_carrier_up_count.attr, + &dev_attr_carrier_down_count.attr, ++ &dev_attr_threaded.attr, + NULL, + }; + ATTRIBUTE_GROUPS(net_class); diff --git a/target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch b/target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch new file mode 100644 index 0000000000..febef3e28a --- /dev/null +++ b/target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch @@ -0,0 +1,93 @@ +From: Wei Wang +Date: Mon, 1 Mar 2021 17:21:13 -0800 +Subject: [PATCH] net: fix race between napi kthread mode and busy poll + +Currently, napi_thread_wait() checks for NAPI_STATE_SCHED bit to +determine if the kthread owns this napi and could call napi->poll() on +it. However, if socket busy poll is enabled, it is possible that the +busy poll thread grabs this SCHED bit (after the previous napi->poll() +invokes napi_complete_done() and clears SCHED bit) and tries to poll +on the same napi. napi_disable() could grab the SCHED bit as well. +This patch tries to fix this race by adding a new bit +NAPI_STATE_SCHED_THREADED in napi->state. This bit gets set in +____napi_schedule() if the threaded mode is enabled, and gets cleared +in napi_complete_done(), and we only poll the napi in kthread if this +bit is set. This helps distinguish the ownership of the napi between +kthread and other scenarios and fixes the race issue. + +Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") +Reported-by: Martin Zaharinov +Suggested-by: Jakub Kicinski +Signed-off-by: Wei Wang +Cc: Alexander Duyck +Cc: Eric Dumazet +Cc: Paolo Abeni +Cc: Hannes Frederic Sowa +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -359,6 +359,7 @@ enum { + NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ + NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ + NAPI_STATE_THREADED, /* The poll is performed inside its own thread*/ ++ NAPI_STATE_SCHED_THREADED, /* Napi is currently scheduled in threaded mode */ + }; + + enum { +@@ -370,6 +371,7 @@ enum { + NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), + NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), + NAPIF_STATE_THREADED = BIT(NAPI_STATE_THREADED), ++ NAPIF_STATE_SCHED_THREADED = BIT(NAPI_STATE_SCHED_THREADED), + }; + + enum gro_result { +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4300,6 +4300,8 @@ static inline void ____napi_schedule(str + */ + thread = READ_ONCE(napi->thread); + if (thread) { ++ if (thread->state != TASK_INTERRUPTIBLE) ++ set_bit(NAPI_STATE_SCHED_THREADED, &napi->state); + wake_up_process(thread); + return; + } +@@ -6560,7 +6562,8 @@ bool napi_complete_done(struct napi_stru + + WARN_ON_ONCE(!(val & NAPIF_STATE_SCHED)); + +- new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED); ++ new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED | ++ NAPIF_STATE_SCHED_THREADED); + + /* If STATE_MISSED was set, leave STATE_SCHED set, + * because we will call napi->poll() one more time. +@@ -6996,16 +6999,25 @@ static int napi_poll(struct napi_struct + + static int napi_thread_wait(struct napi_struct *napi) + { ++ bool woken = false; ++ + set_current_state(TASK_INTERRUPTIBLE); + + while (!kthread_should_stop() && !napi_disable_pending(napi)) { +- if (test_bit(NAPI_STATE_SCHED, &napi->state)) { ++ /* Testing SCHED_THREADED bit here to make sure the current ++ * kthread owns this napi and could poll on this napi. ++ * Testing SCHED bit is not enough because SCHED bit might be ++ * set by some other busy poll thread or by napi_disable(). ++ */ ++ if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state) || woken) { + WARN_ON(!list_empty(&napi->poll_list)); + __set_current_state(TASK_RUNNING); + return 0; + } + + schedule(); ++ /* woken being true indicates this thread owns this napi. */ ++ woken = true; + set_current_state(TASK_INTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); diff --git a/target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch b/target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch new file mode 100644 index 0000000000..1223b15c33 --- /dev/null +++ b/target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch @@ -0,0 +1,53 @@ +From: Paolo Abeni +Date: Fri, 9 Apr 2021 17:24:17 +0200 +Subject: [PATCH] net: fix hangup on napi_disable for threaded napi + +napi_disable() is subject to an hangup, when the threaded +mode is enabled and the napi is under heavy traffic. + +If the relevant napi has been scheduled and the napi_disable() +kicks in before the next napi_threaded_wait() completes - so +that the latter quits due to the napi_disable_pending() condition, +the existing code leaves the NAPI_STATE_SCHED bit set and the +napi_disable() loop waiting for such bit will hang. + +This patch addresses the issue by dropping the NAPI_STATE_DISABLE +bit test in napi_thread_wait(). The later napi_threaded_poll() +iteration will take care of clearing the NAPI_STATE_SCHED. + +This also addresses a related problem reported by Jakub: +before this patch a napi_disable()/napi_enable() pair killed +the napi thread, effectively disabling the threaded mode. +On the patched kernel napi_disable() simply stops scheduling +the relevant thread. + +v1 -> v2: + - let the main napi_thread_poll() loop clear the SCHED bit + +Reported-by: Jakub Kicinski +Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") +Signed-off-by: Paolo Abeni +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/883923fa22745a9589e8610962b7dc59df09fb1f.1617981844.git.pabeni@redhat.com +Signed-off-by: Jakub Kicinski +--- + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -7003,7 +7003,7 @@ static int napi_thread_wait(struct napi_ + + set_current_state(TASK_INTERRUPTIBLE); + +- while (!kthread_should_stop() && !napi_disable_pending(napi)) { ++ while (!kthread_should_stop()) { + /* Testing SCHED_THREADED bit here to make sure the current + * kthread owns this napi and could poll on this napi. + * Testing SCHED bit is not enough because SCHED bit might be +@@ -7021,6 +7021,7 @@ static int napi_thread_wait(struct napi_ + set_current_state(TASK_INTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); ++ + return -1; + } + diff --git a/target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch b/target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch new file mode 100644 index 0000000000..c881ccfcb0 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch @@ -0,0 +1,52 @@ +From: Pablo Neira Ayuso +Date: Fri, 20 Nov 2020 13:49:13 +0100 +Subject: [PATCH] netfilter: flowtable: add hash offset field to tuple + +Add a placeholder field to calculate hash tuple offset. Similar to +2c407aca6497 ("netfilter: conntrack: avoid gcc-10 zero-length-bounds +warning"). + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -107,6 +107,10 @@ struct flow_offload_tuple { + + u8 l3proto; + u8 l4proto; ++ ++ /* All members above are keys for lookups, see flow_offload_hash(). */ ++ struct { } __hash; ++ + u8 dir; + + u16 mtu; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -191,14 +191,14 @@ static u32 flow_offload_hash(const void + { + const struct flow_offload_tuple *tuple = data; + +- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); ++ return jhash(tuple, offsetof(struct flow_offload_tuple, __hash), seed); + } + + static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) + { + const struct flow_offload_tuple_rhash *tuplehash = data; + +- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); ++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, __hash), seed); + } + + static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, +@@ -207,7 +207,7 @@ static int flow_offload_hash_cmp(struct + const struct flow_offload_tuple *tuple = arg->key; + const struct flow_offload_tuple_rhash *x = ptr; + +- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) ++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, __hash))) + return 1; + + return 0; diff --git a/target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch b/target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch new file mode 100644 index 0000000000..d98b4bfb7f --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch @@ -0,0 +1,98 @@ +From: Oz Shlomo +Date: Tue, 23 Mar 2021 00:56:19 +0100 +Subject: [PATCH] netfilter: flowtable: separate replace, destroy and + stats to different workqueues + +Currently the flow table offload replace, destroy and stats work items are +executed on a single workqueue. As such, DESTROY and STATS commands may +be backloged after a burst of REPLACE work items. This scenario can bloat +up memory and may cause active connections to age. + +Instatiate add, del and stats workqueues to avoid backlogs of non-dependent +actions. Provide sysfs control over the workqueue attributes, allowing +userspace applications to control the workqueue cpumask. + +Signed-off-by: Oz Shlomo +Reviewed-by: Paul Blakey +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -13,7 +13,9 @@ + #include + #include + +-static struct workqueue_struct *nf_flow_offload_wq; ++static struct workqueue_struct *nf_flow_offload_add_wq; ++static struct workqueue_struct *nf_flow_offload_del_wq; ++static struct workqueue_struct *nf_flow_offload_stats_wq; + + struct flow_offload_work { + struct list_head list; +@@ -827,7 +829,12 @@ static void flow_offload_work_handler(st + + static void flow_offload_queue_work(struct flow_offload_work *offload) + { +- queue_work(nf_flow_offload_wq, &offload->work); ++ if (offload->cmd == FLOW_CLS_REPLACE) ++ queue_work(nf_flow_offload_add_wq, &offload->work); ++ else if (offload->cmd == FLOW_CLS_DESTROY) ++ queue_work(nf_flow_offload_del_wq, &offload->work); ++ else ++ queue_work(nf_flow_offload_stats_wq, &offload->work); + } + + static struct flow_offload_work * +@@ -899,8 +906,11 @@ void nf_flow_offload_stats(struct nf_flo + + void nf_flow_table_offload_flush(struct nf_flowtable *flowtable) + { +- if (nf_flowtable_hw_offload(flowtable)) +- flush_workqueue(nf_flow_offload_wq); ++ if (nf_flowtable_hw_offload(flowtable)) { ++ flush_workqueue(nf_flow_offload_add_wq); ++ flush_workqueue(nf_flow_offload_del_wq); ++ flush_workqueue(nf_flow_offload_stats_wq); ++ } + } + + static int nf_flow_table_block_setup(struct nf_flowtable *flowtable, +@@ -1013,15 +1023,33 @@ EXPORT_SYMBOL_GPL(nf_flow_table_offload_ + + int nf_flow_table_offload_init(void) + { +- nf_flow_offload_wq = alloc_workqueue("nf_flow_table_offload", +- WQ_UNBOUND, 0); +- if (!nf_flow_offload_wq) ++ nf_flow_offload_add_wq = alloc_workqueue("nf_ft_offload_add", ++ WQ_UNBOUND | WQ_SYSFS, 0); ++ if (!nf_flow_offload_add_wq) + return -ENOMEM; + ++ nf_flow_offload_del_wq = alloc_workqueue("nf_ft_offload_del", ++ WQ_UNBOUND | WQ_SYSFS, 0); ++ if (!nf_flow_offload_del_wq) ++ goto err_del_wq; ++ ++ nf_flow_offload_stats_wq = alloc_workqueue("nf_ft_offload_stats", ++ WQ_UNBOUND | WQ_SYSFS, 0); ++ if (!nf_flow_offload_stats_wq) ++ goto err_stats_wq; ++ + return 0; ++ ++err_stats_wq: ++ destroy_workqueue(nf_flow_offload_del_wq); ++err_del_wq: ++ destroy_workqueue(nf_flow_offload_add_wq); ++ return -ENOMEM; + } + + void nf_flow_table_offload_exit(void) + { +- destroy_workqueue(nf_flow_offload_wq); ++ destroy_workqueue(nf_flow_offload_add_wq); ++ destroy_workqueue(nf_flow_offload_del_wq); ++ destroy_workqueue(nf_flow_offload_stats_wq); + } diff --git a/target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch b/target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch new file mode 100644 index 0000000000..37e80d989d --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch @@ -0,0 +1,22 @@ +From: YueHaibing +Date: Tue, 23 Mar 2021 00:56:21 +0100 +Subject: [PATCH] netfilter: conntrack: Remove unused variable + declaration + +commit e97c3e278e95 ("tproxy: split off ipv6 defragmentation to a separate +module") left behind this. + +Signed-off-by: YueHaibing +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h ++++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h +@@ -4,7 +4,4 @@ + + extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; + +-#include +-extern struct ctl_table nf_ct_ipv6_sysctl_table[]; +- + #endif /* _NF_CONNTRACK_IPV6_H*/ diff --git a/target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch b/target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch new file mode 100644 index 0000000000..9fd01b465e --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch @@ -0,0 +1,291 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:22 +0100 +Subject: [PATCH] netfilter: flowtable: consolidate + skb_try_make_writable() call + +Fetch the layer 4 header size to be mangled by NAT when building the +tuple, then use it to make writable the network and the transport +headers. After this update, the NAT routines now assumes that the skbuff +area is writable. Do the pointer refetch only after the single +skb_try_make_writable() call. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -394,9 +394,6 @@ static int nf_flow_nat_port_tcp(struct s + { + struct tcphdr *tcph; + +- if (skb_try_make_writable(skb, thoff + sizeof(*tcph))) +- return -1; +- + tcph = (void *)(skb_network_header(skb) + thoff); + inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false); + +@@ -408,9 +405,6 @@ static int nf_flow_nat_port_udp(struct s + { + struct udphdr *udph; + +- if (skb_try_make_writable(skb, thoff + sizeof(*udph))) +- return -1; +- + udph = (void *)(skb_network_header(skb) + thoff); + if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { + inet_proto_csum_replace2(&udph->check, skb, port, +@@ -446,9 +440,6 @@ int nf_flow_snat_port(const struct flow_ + struct flow_ports *hdr; + __be16 port, new_port; + +- if (skb_try_make_writable(skb, thoff + sizeof(*hdr))) +- return -1; +- + hdr = (void *)(skb_network_header(skb) + thoff); + + switch (dir) { +@@ -477,9 +468,6 @@ int nf_flow_dnat_port(const struct flow_ + struct flow_ports *hdr; + __be16 port, new_port; + +- if (skb_try_make_writable(skb, thoff + sizeof(*hdr))) +- return -1; +- + hdr = (void *)(skb_network_header(skb) + thoff); + + switch (dir) { +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -39,9 +39,6 @@ static int nf_flow_nat_ip_tcp(struct sk_ + { + struct tcphdr *tcph; + +- if (skb_try_make_writable(skb, thoff + sizeof(*tcph))) +- return -1; +- + tcph = (void *)(skb_network_header(skb) + thoff); + inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); + +@@ -53,9 +50,6 @@ static int nf_flow_nat_ip_udp(struct sk_ + { + struct udphdr *udph; + +- if (skb_try_make_writable(skb, thoff + sizeof(*udph))) +- return -1; +- + udph = (void *)(skb_network_header(skb) + thoff); + if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { + inet_proto_csum_replace4(&udph->check, skb, addr, +@@ -136,19 +130,17 @@ static int nf_flow_dnat_ip(const struct + } + + static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- unsigned int thoff, enum flow_offload_tuple_dir dir) ++ unsigned int thoff, enum flow_offload_tuple_dir dir, ++ struct iphdr *iph) + { +- struct iphdr *iph = ip_hdr(skb); +- + if (test_bit(NF_FLOW_SNAT, &flow->flags) && + (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +- nf_flow_snat_ip(flow, skb, ip_hdr(skb), thoff, dir) < 0)) ++ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) + return -1; + +- iph = ip_hdr(skb); + if (test_bit(NF_FLOW_DNAT, &flow->flags) && + (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +- nf_flow_dnat_ip(flow, skb, ip_hdr(skb), thoff, dir) < 0)) ++ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) + return -1; + + return 0; +@@ -160,10 +152,10 @@ static bool ip_has_options(unsigned int + } + + static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple) ++ struct flow_offload_tuple *tuple, u32 *hdrsize) + { +- unsigned int thoff, hdrsize; + struct flow_ports *ports; ++ unsigned int thoff; + struct iphdr *iph; + + if (!pskb_may_pull(skb, sizeof(*iph))) +@@ -178,10 +170,10 @@ static int nf_flow_tuple_ip(struct sk_bu + + switch (iph->protocol) { + case IPPROTO_TCP: +- hdrsize = sizeof(struct tcphdr); ++ *hdrsize = sizeof(struct tcphdr); + break; + case IPPROTO_UDP: +- hdrsize = sizeof(struct udphdr); ++ *hdrsize = sizeof(struct udphdr); + break; + default: + return -1; +@@ -191,7 +183,7 @@ static int nf_flow_tuple_ip(struct sk_bu + return -1; + + thoff = iph->ihl * 4; +- if (!pskb_may_pull(skb, thoff + hdrsize)) ++ if (!pskb_may_pull(skb, thoff + *hdrsize)) + return -1; + + iph = ip_hdr(skb); +@@ -252,11 +244,12 @@ nf_flow_offload_ip_hook(void *priv, stru + unsigned int thoff; + struct iphdr *iph; + __be32 nexthop; ++ u32 hdrsize; + + if (skb->protocol != htons(ETH_P_IP)) + return NF_ACCEPT; + +- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) ++ if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize) < 0) + return NF_ACCEPT; + + tuplehash = flow_offload_lookup(flow_table, &tuple); +@@ -271,11 +264,13 @@ nf_flow_offload_ip_hook(void *priv, stru + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; + +- if (skb_try_make_writable(skb, sizeof(*iph))) ++ iph = ip_hdr(skb); ++ thoff = iph->ihl * 4; ++ if (skb_try_make_writable(skb, thoff + hdrsize)) + return NF_DROP; + +- thoff = ip_hdr(skb)->ihl * 4; +- if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) ++ iph = ip_hdr(skb); ++ if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) + return NF_ACCEPT; + + flow_offload_refresh(flow_table, flow); +@@ -285,10 +280,9 @@ nf_flow_offload_ip_hook(void *priv, stru + return NF_ACCEPT; + } + +- if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) ++ if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0) + return NF_DROP; + +- iph = ip_hdr(skb); + ip_decrease_ttl(iph); + skb->tstamp = 0; + +@@ -317,9 +311,6 @@ static int nf_flow_nat_ipv6_tcp(struct s + { + struct tcphdr *tcph; + +- if (skb_try_make_writable(skb, thoff + sizeof(*tcph))) +- return -1; +- + tcph = (void *)(skb_network_header(skb) + thoff); + inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, + new_addr->s6_addr32, true); +@@ -333,9 +324,6 @@ static int nf_flow_nat_ipv6_udp(struct s + { + struct udphdr *udph; + +- if (skb_try_make_writable(skb, thoff + sizeof(*udph))) +- return -1; +- + udph = (void *)(skb_network_header(skb) + thoff); + if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { + inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, +@@ -417,31 +405,30 @@ static int nf_flow_dnat_ipv6(const struc + + static int nf_flow_nat_ipv6(const struct flow_offload *flow, + struct sk_buff *skb, +- enum flow_offload_tuple_dir dir) ++ enum flow_offload_tuple_dir dir, ++ struct ipv6hdr *ip6h) + { +- struct ipv6hdr *ip6h = ipv6_hdr(skb); + unsigned int thoff = sizeof(*ip6h); + + if (test_bit(NF_FLOW_SNAT, &flow->flags) && + (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +- nf_flow_snat_ipv6(flow, skb, ipv6_hdr(skb), thoff, dir) < 0)) ++ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) + return -1; + +- ip6h = ipv6_hdr(skb); + if (test_bit(NF_FLOW_DNAT, &flow->flags) && + (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +- nf_flow_dnat_ipv6(flow, skb, ipv6_hdr(skb), thoff, dir) < 0)) ++ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) + return -1; + + return 0; + } + + static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple) ++ struct flow_offload_tuple *tuple, u32 *hdrsize) + { +- unsigned int thoff, hdrsize; + struct flow_ports *ports; + struct ipv6hdr *ip6h; ++ unsigned int thoff; + + if (!pskb_may_pull(skb, sizeof(*ip6h))) + return -1; +@@ -450,10 +437,10 @@ static int nf_flow_tuple_ipv6(struct sk_ + + switch (ip6h->nexthdr) { + case IPPROTO_TCP: +- hdrsize = sizeof(struct tcphdr); ++ *hdrsize = sizeof(struct tcphdr); + break; + case IPPROTO_UDP: +- hdrsize = sizeof(struct udphdr); ++ *hdrsize = sizeof(struct udphdr); + break; + default: + return -1; +@@ -463,7 +450,7 @@ static int nf_flow_tuple_ipv6(struct sk_ + return -1; + + thoff = sizeof(*ip6h); +- if (!pskb_may_pull(skb, thoff + hdrsize)) ++ if (!pskb_may_pull(skb, thoff + *hdrsize)) + return -1; + + ip6h = ipv6_hdr(skb); +@@ -493,11 +480,12 @@ nf_flow_offload_ipv6_hook(void *priv, st + struct net_device *outdev; + struct ipv6hdr *ip6h; + struct rt6_info *rt; ++ u32 hdrsize; + + if (skb->protocol != htons(ETH_P_IPV6)) + return NF_ACCEPT; + +- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) ++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize) < 0) + return NF_ACCEPT; + + tuplehash = flow_offload_lookup(flow_table, &tuple); +@@ -523,13 +511,13 @@ nf_flow_offload_ipv6_hook(void *priv, st + return NF_ACCEPT; + } + +- if (skb_try_make_writable(skb, sizeof(*ip6h))) ++ if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) + return NF_DROP; + +- if (nf_flow_nat_ipv6(flow, skb, dir) < 0) ++ ip6h = ipv6_hdr(skb); ++ if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0) + return NF_DROP; + +- ip6h = ipv6_hdr(skb); + ip6h->hop_limit--; + skb->tstamp = 0; + diff --git a/target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch b/target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch new file mode 100644 index 0000000000..84e294de7a --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch @@ -0,0 +1,35 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:23 +0100 +Subject: [PATCH] netfilter: flowtable: move skb_try_make_writable() + before NAT in IPv4 + +For consistency with the IPv6 flowtable datapath and to make sure the +skbuff is writable right before the NAT header updates. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -266,10 +266,6 @@ nf_flow_offload_ip_hook(void *priv, stru + + iph = ip_hdr(skb); + thoff = iph->ihl * 4; +- if (skb_try_make_writable(skb, thoff + hdrsize)) +- return NF_DROP; +- +- iph = ip_hdr(skb); + if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) + return NF_ACCEPT; + +@@ -280,6 +276,10 @@ nf_flow_offload_ip_hook(void *priv, stru + return NF_ACCEPT; + } + ++ if (skb_try_make_writable(skb, thoff + hdrsize)) ++ return NF_DROP; ++ ++ iph = ip_hdr(skb); + if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0) + return NF_DROP; + diff --git a/target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch b/target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch new file mode 100644 index 0000000000..64a0e42079 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch @@ -0,0 +1,82 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:24 +0100 +Subject: [PATCH] netfilter: flowtable: move FLOW_OFFLOAD_DIR_MAX away + from enumeration + +This allows to remove the default case which should not ever happen and +that was added to avoid gcc warnings on unhandled FLOW_OFFLOAD_DIR_MAX +enumeration case. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -86,8 +86,8 @@ static inline bool nf_flowtable_hw_offlo + enum flow_offload_tuple_dir { + FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL, + FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY, +- FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX + }; ++#define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX + + struct flow_offload_tuple { + union { +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -453,8 +453,6 @@ int nf_flow_snat_port(const struct flow_ + new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; + hdr->dest = new_port; + break; +- default: +- return -1; + } + + return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +@@ -481,8 +479,6 @@ int nf_flow_dnat_port(const struct flow_ + new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; + hdr->source = new_port; + break; +- default: +- return -1; + } + + return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -96,8 +96,6 @@ static int nf_flow_snat_ip(const struct + new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; + iph->daddr = new_addr; + break; +- default: +- return -1; + } + csum_replace4(&iph->check, addr, new_addr); + +@@ -121,8 +119,6 @@ static int nf_flow_dnat_ip(const struct + new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; + iph->saddr = new_addr; + break; +- default: +- return -1; + } + csum_replace4(&iph->check, addr, new_addr); + +@@ -371,8 +367,6 @@ static int nf_flow_snat_ipv6(const struc + new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; + ip6h->daddr = new_addr; + break; +- default: +- return -1; + } + + return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +@@ -396,8 +390,6 @@ static int nf_flow_dnat_ipv6(const struc + new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; + ip6h->saddr = new_addr; + break; +- default: +- return -1; + } + + return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); diff --git a/target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch b/target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch new file mode 100644 index 0000000000..2224e095c9 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch @@ -0,0 +1,394 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:25 +0100 +Subject: [PATCH] netfilter: flowtable: fast NAT functions never fail + +Simplify existing fast NAT routines by returning void. After the +skb_try_make_writable() call consolidation, these routines cannot ever +fail. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -228,12 +228,12 @@ void nf_flow_table_free(struct nf_flowta + + void flow_offload_teardown(struct flow_offload *flow); + +-int nf_flow_snat_port(const struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff, +- u8 protocol, enum flow_offload_tuple_dir dir); +-int nf_flow_dnat_port(const struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff, +- u8 protocol, enum flow_offload_tuple_dir dir); ++void nf_flow_snat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir); ++void nf_flow_dnat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir); + + struct flow_ports { + __be16 source, dest; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -388,20 +388,17 @@ static void nf_flow_offload_work_gc(stru + queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); + } + +- +-static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, +- __be16 port, __be16 new_port) ++static void nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) + { + struct tcphdr *tcph; + + tcph = (void *)(skb_network_header(skb) + thoff); + inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false); +- +- return 0; + } + +-static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, +- __be16 port, __be16 new_port) ++static void nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) + { + struct udphdr *udph; + +@@ -412,30 +409,24 @@ static int nf_flow_nat_port_udp(struct s + if (!udph->check) + udph->check = CSUM_MANGLED_0; + } +- +- return 0; + } + +-static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, +- u8 protocol, __be16 port, __be16 new_port) ++static void nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, __be16 port, __be16 new_port) + { + switch (protocol) { + case IPPROTO_TCP: +- if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) +- return NF_DROP; ++ nf_flow_nat_port_tcp(skb, thoff, port, new_port); + break; + case IPPROTO_UDP: +- if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) +- return NF_DROP; ++ nf_flow_nat_port_udp(skb, thoff, port, new_port); + break; + } +- +- return 0; + } + +-int nf_flow_snat_port(const struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff, +- u8 protocol, enum flow_offload_tuple_dir dir) ++void nf_flow_snat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir) + { + struct flow_ports *hdr; + __be16 port, new_port; +@@ -455,13 +446,13 @@ int nf_flow_snat_port(const struct flow_ + break; + } + +- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++ nf_flow_nat_port(skb, thoff, protocol, port, new_port); + } + EXPORT_SYMBOL_GPL(nf_flow_snat_port); + +-int nf_flow_dnat_port(const struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff, +- u8 protocol, enum flow_offload_tuple_dir dir) ++void nf_flow_dnat_port(const struct flow_offload *flow, struct sk_buff *skb, ++ unsigned int thoff, u8 protocol, ++ enum flow_offload_tuple_dir dir) + { + struct flow_ports *hdr; + __be16 port, new_port; +@@ -481,7 +472,7 @@ int nf_flow_dnat_port(const struct flow_ + break; + } + +- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++ nf_flow_nat_port(skb, thoff, protocol, port, new_port); + } + EXPORT_SYMBOL_GPL(nf_flow_dnat_port); + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -34,19 +34,17 @@ static int nf_flow_state_check(struct fl + return 0; + } + +-static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, +- __be32 addr, __be32 new_addr) ++static void nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) + { + struct tcphdr *tcph; + + tcph = (void *)(skb_network_header(skb) + thoff); + inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); +- +- return 0; + } + +-static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, +- __be32 addr, __be32 new_addr) ++static void nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) + { + struct udphdr *udph; + +@@ -57,31 +55,25 @@ static int nf_flow_nat_ip_udp(struct sk_ + if (!udph->check) + udph->check = CSUM_MANGLED_0; + } +- +- return 0; + } + +-static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, +- unsigned int thoff, __be32 addr, +- __be32 new_addr) ++static void nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, ++ unsigned int thoff, __be32 addr, ++ __be32 new_addr) + { + switch (iph->protocol) { + case IPPROTO_TCP: +- if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; ++ nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr); + break; + case IPPROTO_UDP: +- if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; ++ nf_flow_nat_ip_udp(skb, thoff, addr, new_addr); + break; + } +- +- return 0; + } + +-static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- struct iphdr *iph, unsigned int thoff, +- enum flow_offload_tuple_dir dir) ++static void nf_flow_snat_ip(const struct flow_offload *flow, ++ struct sk_buff *skb, struct iphdr *iph, ++ unsigned int thoff, enum flow_offload_tuple_dir dir) + { + __be32 addr, new_addr; + +@@ -99,12 +91,12 @@ static int nf_flow_snat_ip(const struct + } + csum_replace4(&iph->check, addr, new_addr); + +- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++ nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); + } + +-static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- struct iphdr *iph, unsigned int thoff, +- enum flow_offload_tuple_dir dir) ++static void nf_flow_dnat_ip(const struct flow_offload *flow, ++ struct sk_buff *skb, struct iphdr *iph, ++ unsigned int thoff, enum flow_offload_tuple_dir dir) + { + __be32 addr, new_addr; + +@@ -122,24 +114,21 @@ static int nf_flow_dnat_ip(const struct + } + csum_replace4(&iph->check, addr, new_addr); + +- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++ nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); + } + +-static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++static void nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, + unsigned int thoff, enum flow_offload_tuple_dir dir, + struct iphdr *iph) + { +- if (test_bit(NF_FLOW_SNAT, &flow->flags) && +- (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +- nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) +- return -1; +- +- if (test_bit(NF_FLOW_DNAT, &flow->flags) && +- (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +- nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) +- return -1; +- +- return 0; ++ if (test_bit(NF_FLOW_SNAT, &flow->flags)) { ++ nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir); ++ nf_flow_snat_ip(flow, skb, iph, thoff, dir); ++ } ++ if (test_bit(NF_FLOW_DNAT, &flow->flags)) { ++ nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir); ++ nf_flow_dnat_ip(flow, skb, iph, thoff, dir); ++ } + } + + static bool ip_has_options(unsigned int thoff) +@@ -276,8 +265,7 @@ nf_flow_offload_ip_hook(void *priv, stru + return NF_DROP; + + iph = ip_hdr(skb); +- if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0) +- return NF_DROP; ++ nf_flow_nat_ip(flow, skb, thoff, dir, iph); + + ip_decrease_ttl(iph); + skb->tstamp = 0; +@@ -301,22 +289,21 @@ nf_flow_offload_ip_hook(void *priv, stru + } + EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); + +-static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, +- struct in6_addr *addr, +- struct in6_addr *new_addr) ++static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, ++ struct in6_addr *addr, ++ struct in6_addr *new_addr, ++ struct ipv6hdr *ip6h) + { + struct tcphdr *tcph; + + tcph = (void *)(skb_network_header(skb) + thoff); + inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, + new_addr->s6_addr32, true); +- +- return 0; + } + +-static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, +- struct in6_addr *addr, +- struct in6_addr *new_addr) ++static void nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, ++ struct in6_addr *addr, ++ struct in6_addr *new_addr) + { + struct udphdr *udph; + +@@ -327,32 +314,26 @@ static int nf_flow_nat_ipv6_udp(struct s + if (!udph->check) + udph->check = CSUM_MANGLED_0; + } +- +- return 0; + } + +-static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, +- unsigned int thoff, struct in6_addr *addr, +- struct in6_addr *new_addr) ++static void nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, struct in6_addr *addr, ++ struct in6_addr *new_addr) + { + switch (ip6h->nexthdr) { + case IPPROTO_TCP: +- if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; ++ nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr, ip6h); + break; + case IPPROTO_UDP: +- if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; ++ nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr); + break; + } +- +- return 0; + } + +-static int nf_flow_snat_ipv6(const struct flow_offload *flow, +- struct sk_buff *skb, struct ipv6hdr *ip6h, +- unsigned int thoff, +- enum flow_offload_tuple_dir dir) ++static void nf_flow_snat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, ++ enum flow_offload_tuple_dir dir) + { + struct in6_addr addr, new_addr; + +@@ -369,13 +350,13 @@ static int nf_flow_snat_ipv6(const struc + break; + } + +- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++ nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); + } + +-static int nf_flow_dnat_ipv6(const struct flow_offload *flow, +- struct sk_buff *skb, struct ipv6hdr *ip6h, +- unsigned int thoff, +- enum flow_offload_tuple_dir dir) ++static void nf_flow_dnat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, ++ enum flow_offload_tuple_dir dir) + { + struct in6_addr addr, new_addr; + +@@ -392,27 +373,24 @@ static int nf_flow_dnat_ipv6(const struc + break; + } + +- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++ nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); + } + +-static int nf_flow_nat_ipv6(const struct flow_offload *flow, +- struct sk_buff *skb, +- enum flow_offload_tuple_dir dir, +- struct ipv6hdr *ip6h) ++static void nf_flow_nat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, ++ enum flow_offload_tuple_dir dir, ++ struct ipv6hdr *ip6h) + { + unsigned int thoff = sizeof(*ip6h); + +- if (test_bit(NF_FLOW_SNAT, &flow->flags) && +- (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +- nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +- return -1; +- +- if (test_bit(NF_FLOW_DNAT, &flow->flags) && +- (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +- nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +- return -1; +- +- return 0; ++ if (test_bit(NF_FLOW_SNAT, &flow->flags)) { ++ nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir); ++ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir); ++ } ++ if (test_bit(NF_FLOW_DNAT, &flow->flags)) { ++ nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir); ++ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir); ++ } + } + + static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +@@ -507,8 +485,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + return NF_DROP; + + ip6h = ipv6_hdr(skb); +- if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0) +- return NF_DROP; ++ nf_flow_nat_ipv6(flow, skb, dir, ip6h); + + ip6h->hop_limit--; + skb->tstamp = 0; diff --git a/target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch b/target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch new file mode 100644 index 0000000000..276785030d --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch @@ -0,0 +1,46 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:26 +0100 +Subject: [PATCH] netfilter: flowtable: call dst_check() to fall back to + classic forwarding + +In case the route is stale, pass up the packet to the classic forwarding +path for re-evaluation and schedule this flow entry for removal. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -197,14 +197,6 @@ static bool nf_flow_exceeds_mtu(const st + return true; + } + +-static int nf_flow_offload_dst_check(struct dst_entry *dst) +-{ +- if (unlikely(dst_xfrm(dst))) +- return dst_check(dst, 0) ? 0 : -1; +- +- return 0; +-} +- + static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, + const struct nf_hook_state *state, + struct dst_entry *dst) +@@ -256,7 +248,7 @@ nf_flow_offload_ip_hook(void *priv, stru + + flow_offload_refresh(flow_table, flow); + +- if (nf_flow_offload_dst_check(&rt->dst)) { ++ if (!dst_check(&rt->dst, 0)) { + flow_offload_teardown(flow); + return NF_ACCEPT; + } +@@ -476,7 +468,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + + flow_offload_refresh(flow_table, flow); + +- if (nf_flow_offload_dst_check(&rt->dst)) { ++ if (!dst_check(&rt->dst, 0)) { + flow_offload_teardown(flow); + return NF_ACCEPT; + } diff --git a/target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch b/target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch new file mode 100644 index 0000000000..14ac2ee295 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch @@ -0,0 +1,49 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:27 +0100 +Subject: [PATCH] netfilter: flowtable: refresh timeout after dst and + writable checks + +Refresh the timeout (and retry hardware offload) once the skbuff dst +is confirmed to be current and after the skbuff is made writable. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -246,8 +246,6 @@ nf_flow_offload_ip_hook(void *priv, stru + if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) + return NF_ACCEPT; + +- flow_offload_refresh(flow_table, flow); +- + if (!dst_check(&rt->dst, 0)) { + flow_offload_teardown(flow); + return NF_ACCEPT; +@@ -256,6 +254,8 @@ nf_flow_offload_ip_hook(void *priv, stru + if (skb_try_make_writable(skb, thoff + hdrsize)) + return NF_DROP; + ++ flow_offload_refresh(flow_table, flow); ++ + iph = ip_hdr(skb); + nf_flow_nat_ip(flow, skb, thoff, dir, iph); + +@@ -466,8 +466,6 @@ nf_flow_offload_ipv6_hook(void *priv, st + sizeof(*ip6h))) + return NF_ACCEPT; + +- flow_offload_refresh(flow_table, flow); +- + if (!dst_check(&rt->dst, 0)) { + flow_offload_teardown(flow); + return NF_ACCEPT; +@@ -476,6 +474,8 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) + return NF_DROP; + ++ flow_offload_refresh(flow_table, flow); ++ + ip6h = ipv6_hdr(skb); + nf_flow_nat_ipv6(flow, skb, dir, ip6h); + diff --git a/target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch b/target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch new file mode 100644 index 0000000000..fa6e0c4173 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch @@ -0,0 +1,103 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Mar 2021 00:56:28 +0100 +Subject: [PATCH] netfilter: nftables: update table flags from the commit + phase + +Do not update table flags from the preparation phase. Store the flags +update into the transaction, then update the flags from the commit +phase. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -1470,13 +1470,16 @@ struct nft_trans_chain { + + struct nft_trans_table { + bool update; +- bool enable; ++ u8 state; ++ u32 flags; + }; + + #define nft_trans_table_update(trans) \ + (((struct nft_trans_table *)trans->data)->update) +-#define nft_trans_table_enable(trans) \ +- (((struct nft_trans_table *)trans->data)->enable) ++#define nft_trans_table_state(trans) \ ++ (((struct nft_trans_table *)trans->data)->state) ++#define nft_trans_table_flags(trans) \ ++ (((struct nft_trans_table *)trans->data)->flags) + + struct nft_trans_elem { + struct nft_set *set; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -891,6 +891,12 @@ static void nf_tables_table_disable(stru + nft_table_disable(net, table, 0); + } + ++enum { ++ NFT_TABLE_STATE_UNCHANGED = 0, ++ NFT_TABLE_STATE_DORMANT, ++ NFT_TABLE_STATE_WAKEUP ++}; ++ + static int nf_tables_updtable(struct nft_ctx *ctx) + { + struct nft_trans *trans; +@@ -914,19 +920,17 @@ static int nf_tables_updtable(struct nft + + if ((flags & NFT_TABLE_F_DORMANT) && + !(ctx->table->flags & NFT_TABLE_F_DORMANT)) { +- nft_trans_table_enable(trans) = false; ++ nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT; + } else if (!(flags & NFT_TABLE_F_DORMANT) && + ctx->table->flags & NFT_TABLE_F_DORMANT) { +- ctx->table->flags &= ~NFT_TABLE_F_DORMANT; + ret = nf_tables_table_enable(ctx->net, ctx->table); + if (ret >= 0) +- nft_trans_table_enable(trans) = true; +- else +- ctx->table->flags |= NFT_TABLE_F_DORMANT; ++ nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP; + } + if (ret < 0) + goto err; + ++ nft_trans_table_flags(trans) = flags; + nft_trans_table_update(trans) = true; + list_add_tail(&trans->list, &ctx->net->nft.commit_list); + return 0; +@@ -7908,11 +7912,10 @@ static int nf_tables_commit(struct net * + switch (trans->msg_type) { + case NFT_MSG_NEWTABLE: + if (nft_trans_table_update(trans)) { +- if (!nft_trans_table_enable(trans)) { +- nf_tables_table_disable(net, +- trans->ctx.table); +- trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; +- } ++ if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT) ++ nf_tables_table_disable(net, trans->ctx.table); ++ ++ trans->ctx.table->flags = nft_trans_table_flags(trans); + } else { + nft_clear(net, trans->ctx.table); + } +@@ -8125,11 +8128,9 @@ static int __nf_tables_abort(struct net + switch (trans->msg_type) { + case NFT_MSG_NEWTABLE: + if (nft_trans_table_update(trans)) { +- if (nft_trans_table_enable(trans)) { +- nf_tables_table_disable(net, +- trans->ctx.table); +- trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; +- } ++ if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP) ++ nf_tables_table_disable(net, trans->ctx.table); ++ + nft_trans_destroy(trans); + } else { + list_del_rcu(&trans->ctx.table->list); diff --git a/target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch b/target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch new file mode 100644 index 0000000000..a8fc1cabe2 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch @@ -0,0 +1,170 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:32 +0100 +Subject: [PATCH] net: resolve forwarding path from virtual netdevice and + HW destination address + +This patch adds dev_fill_forward_path() which resolves the path to reach +the real netdevice from the IP forwarding side. This function takes as +input the netdevice and the destination hardware address and it walks +down the devices calling .ndo_fill_forward_path() for each device until +the real device is found. + +For instance, assuming the following topology: + + IP forwarding + / \ + br0 eth0 + / \ + eth1 eth2 + . + . + . + ethX + ab:cd:ef:ab:cd:ef + +where eth1 and eth2 are bridge ports and eth0 provides WAN connectivity. +ethX is the interface in another box which is connected to the eth1 +bridge port. + +For packets going through IP forwarding to br0 whose destination MAC +address is ab:cd:ef:ab:cd:ef, dev_fill_forward_path() provides the +following path: + + br0 -> eth1 + +.ndo_fill_forward_path for br0 looks up at the FDB for the bridge port +from the destination MAC address to get the bridge port eth1. + +This information allows to create a fast path that bypasses the classic +bridge and IP forwarding paths, so packets go directly from the bridge +port eth1 to eth0 (wan interface) and vice versa. + + fast path + .------------------------. + / \ + | IP forwarding | + | / \ \/ + | br0 eth0 + . / \ + -> eth1 eth2 + . + . + . + ethX + ab:cd:ef:ab:cd:ef + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -827,6 +827,27 @@ typedef u16 (*select_queue_fallback_t)(s + struct sk_buff *skb, + struct net_device *sb_dev); + ++enum net_device_path_type { ++ DEV_PATH_ETHERNET = 0, ++}; ++ ++struct net_device_path { ++ enum net_device_path_type type; ++ const struct net_device *dev; ++}; ++ ++#define NET_DEVICE_PATH_STACK_MAX 5 ++ ++struct net_device_path_stack { ++ int num_paths; ++ struct net_device_path path[NET_DEVICE_PATH_STACK_MAX]; ++}; ++ ++struct net_device_path_ctx { ++ const struct net_device *dev; ++ const u8 *daddr; ++}; ++ + enum tc_setup_type { + TC_SETUP_QDISC_MQPRIO, + TC_SETUP_CLSU32, +@@ -1273,6 +1294,8 @@ struct netdev_net_notifier { + * struct net_device *(*ndo_get_peer_dev)(struct net_device *dev); + * If a device is paired with a peer device, return the peer instance. + * The caller must be under RCU read context. ++ * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path); ++ * Get the forwarding path to reach the real device from the HW destination address + */ + struct net_device_ops { + int (*ndo_init)(struct net_device *dev); +@@ -1481,6 +1504,8 @@ struct net_device_ops { + int (*ndo_tunnel_ctl)(struct net_device *dev, + struct ip_tunnel_parm *p, int cmd); + struct net_device * (*ndo_get_peer_dev)(struct net_device *dev); ++ int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, ++ struct net_device_path *path); + }; + + /** +@@ -2828,6 +2853,8 @@ void dev_remove_offload(struct packet_of + + int dev_get_iflink(const struct net_device *dev); + int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); ++int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr, ++ struct net_device_path_stack *stack); + struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags, + unsigned short mask); + struct net_device *dev_get_by_name(struct net *net, const char *name); +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -847,6 +847,52 @@ int dev_fill_metadata_dst(struct net_dev + } + EXPORT_SYMBOL_GPL(dev_fill_metadata_dst); + ++static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack) ++{ ++ int k = stack->num_paths++; ++ ++ if (WARN_ON_ONCE(k >= NET_DEVICE_PATH_STACK_MAX)) ++ return NULL; ++ ++ return &stack->path[k]; ++} ++ ++int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr, ++ struct net_device_path_stack *stack) ++{ ++ const struct net_device *last_dev; ++ struct net_device_path_ctx ctx = { ++ .dev = dev, ++ .daddr = daddr, ++ }; ++ struct net_device_path *path; ++ int ret = 0; ++ ++ stack->num_paths = 0; ++ while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) { ++ last_dev = ctx.dev; ++ path = dev_fwd_path(stack); ++ if (!path) ++ return -1; ++ ++ memset(path, 0, sizeof(struct net_device_path)); ++ ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path); ++ if (ret < 0) ++ return -1; ++ ++ if (WARN_ON_ONCE(last_dev == ctx.dev)) ++ return -1; ++ } ++ path = dev_fwd_path(stack); ++ if (!path) ++ return -1; ++ path->type = DEV_PATH_ETHERNET; ++ path->dev = ctx.dev; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(dev_fill_forward_path); ++ + /** + * __dev_get_by_name - find a device by its name + * @net: the applicable net namespace diff --git a/target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch b/target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch new file mode 100644 index 0000000000..32c8c9bb78 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch @@ -0,0 +1,80 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:33 +0100 +Subject: [PATCH] net: 8021q: resolve forwarding path for vlan devices + +Add .ndo_fill_forward_path for vlan devices. + +For instance, assuming the following topology: + + IP forwarding + / \ + eth0.100 eth0 + | + eth0 + . + . + . + ethX + ab:cd:ef:ab:cd:ef + +For packets going through IP forwarding to eth0.100 whose destination +MAC address is ab:cd:ef:ab:cd:ef, dev_fill_forward_path() provides the +following path: + + eth0.100 -> eth0 + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -829,11 +829,18 @@ typedef u16 (*select_queue_fallback_t)(s + + enum net_device_path_type { + DEV_PATH_ETHERNET = 0, ++ DEV_PATH_VLAN, + }; + + struct net_device_path { + enum net_device_path_type type; + const struct net_device *dev; ++ union { ++ struct { ++ u16 id; ++ __be16 proto; ++ } encap; ++ }; + }; + + #define NET_DEVICE_PATH_STACK_MAX 5 +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -770,6 +770,20 @@ static int vlan_dev_get_iflink(const str + return real_dev->ifindex; + } + ++static int vlan_dev_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct vlan_dev_priv *vlan = vlan_dev_priv(ctx->dev); ++ ++ path->type = DEV_PATH_VLAN; ++ path->encap.id = vlan->vlan_id; ++ path->encap.proto = vlan->vlan_proto; ++ path->dev = ctx->dev; ++ ctx->dev = vlan->real_dev; ++ ++ return 0; ++} ++ + static const struct ethtool_ops vlan_ethtool_ops = { + .get_link_ksettings = vlan_ethtool_get_link_ksettings, + .get_drvinfo = vlan_ethtool_get_drvinfo, +@@ -808,6 +822,7 @@ static const struct net_device_ops vlan_ + #endif + .ndo_fix_features = vlan_dev_fix_features, + .ndo_get_iflink = vlan_dev_get_iflink, ++ .ndo_fill_forward_path = vlan_dev_fill_forward_path, + }; + + static void vlan_dev_free(struct net_device *dev) diff --git a/target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch b/target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch new file mode 100644 index 0000000000..bdb12b13a6 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch @@ -0,0 +1,62 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:34 +0100 +Subject: [PATCH] net: bridge: resolve forwarding path for bridge devices + +Add .ndo_fill_forward_path for bridge devices. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -830,6 +830,7 @@ typedef u16 (*select_queue_fallback_t)(s + enum net_device_path_type { + DEV_PATH_ETHERNET = 0, + DEV_PATH_VLAN, ++ DEV_PATH_BRIDGE, + }; + + struct net_device_path { +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -398,6 +398,32 @@ static int br_del_slave(struct net_devic + return br_del_if(br, slave_dev); + } + ++static int br_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct net_bridge_fdb_entry *f; ++ struct net_bridge_port *dst; ++ struct net_bridge *br; ++ ++ if (netif_is_bridge_port(ctx->dev)) ++ return -1; ++ ++ br = netdev_priv(ctx->dev); ++ f = br_fdb_find_rcu(br, ctx->daddr, 0); ++ if (!f || !f->dst) ++ return -1; ++ ++ dst = READ_ONCE(f->dst); ++ if (!dst) ++ return -1; ++ ++ path->type = DEV_PATH_BRIDGE; ++ path->dev = dst->br->dev; ++ ctx->dev = dst->dev; ++ ++ return 0; ++} ++ + static const struct ethtool_ops br_ethtool_ops = { + .get_drvinfo = br_getinfo, + .get_link = ethtool_op_get_link, +@@ -432,6 +458,7 @@ static const struct net_device_ops br_ne + .ndo_bridge_setlink = br_setlink, + .ndo_bridge_dellink = br_dellink, + .ndo_features_check = passthru_features_check, ++ .ndo_fill_forward_path = br_fill_forward_path, + }; + + static struct device_type br_type = { diff --git a/target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch b/target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch new file mode 100644 index 0000000000..ba2b1a2877 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch @@ -0,0 +1,207 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:35 +0100 +Subject: [PATCH] net: bridge: resolve forwarding path for VLAN tag + actions in bridge devices + +Depending on the VLAN settings of the bridge and the port, the bridge can +either add or remove a tag. When vlan filtering is enabled, the fdb lookup +also needs to know the VLAN tag/proto for the destination address +To provide this, keep track of the stack of VLAN tags for the path in the +lookup context + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -841,10 +841,20 @@ struct net_device_path { + u16 id; + __be16 proto; + } encap; ++ struct { ++ enum { ++ DEV_PATH_BR_VLAN_KEEP, ++ DEV_PATH_BR_VLAN_TAG, ++ DEV_PATH_BR_VLAN_UNTAG, ++ } vlan_mode; ++ u16 vlan_id; ++ __be16 vlan_proto; ++ } bridge; + }; + }; + + #define NET_DEVICE_PATH_STACK_MAX 5 ++#define NET_DEVICE_PATH_VLAN_MAX 2 + + struct net_device_path_stack { + int num_paths; +@@ -854,6 +864,12 @@ struct net_device_path_stack { + struct net_device_path_ctx { + const struct net_device *dev; + const u8 *daddr; ++ ++ int num_vlans; ++ struct { ++ u16 id; ++ __be16 proto; ++ } vlan[NET_DEVICE_PATH_VLAN_MAX]; + }; + + enum tc_setup_type { +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -780,6 +780,12 @@ static int vlan_dev_fill_forward_path(st + path->encap.proto = vlan->vlan_proto; + path->dev = ctx->dev; + ctx->dev = vlan->real_dev; ++ if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan)) ++ return -ENOSPC; ++ ++ ctx->vlan[ctx->num_vlans].id = vlan->vlan_id; ++ ctx->vlan[ctx->num_vlans].proto = vlan->vlan_proto; ++ ctx->num_vlans++; + + return 0; + } +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -409,7 +409,10 @@ static int br_fill_forward_path(struct n + return -1; + + br = netdev_priv(ctx->dev); +- f = br_fdb_find_rcu(br, ctx->daddr, 0); ++ ++ br_vlan_fill_forward_path_pvid(br, ctx, path); ++ ++ f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id); + if (!f || !f->dst) + return -1; + +@@ -417,10 +420,28 @@ static int br_fill_forward_path(struct n + if (!dst) + return -1; + ++ if (br_vlan_fill_forward_path_mode(br, dst, path)) ++ return -1; ++ + path->type = DEV_PATH_BRIDGE; + path->dev = dst->br->dev; + ctx->dev = dst->dev; + ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_TAG: ++ if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan)) ++ return -ENOSPC; ++ ctx->vlan[ctx->num_vlans].id = path->bridge.vlan_id; ++ ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto; ++ ctx->num_vlans++; ++ break; ++ case DEV_PATH_BR_VLAN_UNTAG: ++ ctx->num_vlans--; ++ break; ++ case DEV_PATH_BR_VLAN_KEEP: ++ break; ++ } ++ + return 0; + } + +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1093,6 +1093,13 @@ void br_vlan_notify(const struct net_bri + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, + const struct net_bridge_vlan *range_end); + ++void br_vlan_fill_forward_path_pvid(struct net_bridge *br, ++ struct net_device_path_ctx *ctx, ++ struct net_device_path *path); ++int br_vlan_fill_forward_path_mode(struct net_bridge *br, ++ struct net_bridge_port *dst, ++ struct net_device_path *path); ++ + static inline struct net_bridge_vlan_group *br_vlan_group( + const struct net_bridge *br) + { +@@ -1250,6 +1257,19 @@ static inline int nbp_get_num_vlan_infos + { + return 0; + } ++ ++static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br, ++ struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++} ++ ++static inline int br_vlan_fill_forward_path_mode(struct net_bridge *br, ++ struct net_bridge_port *dst, ++ struct net_device_path *path) ++{ ++ return 0; ++} + + static inline struct net_bridge_vlan_group *br_vlan_group( + const struct net_bridge *br) +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1327,6 +1327,59 @@ int br_vlan_get_pvid_rcu(const struct ne + } + EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu); + ++void br_vlan_fill_forward_path_pvid(struct net_bridge *br, ++ struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct net_bridge_vlan_group *vg; ++ int idx = ctx->num_vlans - 1; ++ u16 vid; ++ ++ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; ++ ++ if (!br_opt_get(br, BROPT_VLAN_ENABLED)) ++ return; ++ ++ vg = br_vlan_group(br); ++ ++ if (idx >= 0 && ++ ctx->vlan[idx].proto == br->vlan_proto) { ++ vid = ctx->vlan[idx].id; ++ } else { ++ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_TAG; ++ vid = br_get_pvid(vg); ++ } ++ ++ path->bridge.vlan_id = vid; ++ path->bridge.vlan_proto = br->vlan_proto; ++} ++ ++int br_vlan_fill_forward_path_mode(struct net_bridge *br, ++ struct net_bridge_port *dst, ++ struct net_device_path *path) ++{ ++ struct net_bridge_vlan_group *vg; ++ struct net_bridge_vlan *v; ++ ++ if (!br_opt_get(br, BROPT_VLAN_ENABLED)) ++ return 0; ++ ++ vg = nbp_vlan_group_rcu(dst); ++ v = br_vlan_find(vg, path->bridge.vlan_id); ++ if (!v || !br_vlan_should_use(v)) ++ return -EINVAL; ++ ++ if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) ++ return 0; ++ ++ if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) ++ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; ++ else ++ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; ++ ++ return 0; ++} ++ + int br_vlan_get_info(const struct net_device *dev, u16 vid, + struct bridge_vlan_info *p_vinfo) + { diff --git a/target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch b/target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch new file mode 100644 index 0000000000..712bb9ec97 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch @@ -0,0 +1,113 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:36 +0100 +Subject: [PATCH] net: ppp: resolve forwarding path for bridge pppoe + devices + +Pass on the PPPoE session ID, destination hardware address and the real +device. + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1466,12 +1466,34 @@ static void ppp_dev_priv_destructor(stru + ppp_destroy_interface(ppp); + } + ++static int ppp_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct ppp *ppp = netdev_priv(ctx->dev); ++ struct ppp_channel *chan; ++ struct channel *pch; ++ ++ if (ppp->flags & SC_MULTILINK) ++ return -EOPNOTSUPP; ++ ++ if (list_empty(&ppp->channels)) ++ return -ENODEV; ++ ++ pch = list_first_entry(&ppp->channels, struct channel, clist); ++ chan = pch->chan; ++ if (!chan->ops->fill_forward_path) ++ return -EOPNOTSUPP; ++ ++ return chan->ops->fill_forward_path(ctx, path, chan); ++} ++ + static const struct net_device_ops ppp_netdev_ops = { + .ndo_init = ppp_dev_init, + .ndo_uninit = ppp_dev_uninit, + .ndo_start_xmit = ppp_start_xmit, + .ndo_do_ioctl = ppp_net_ioctl, + .ndo_get_stats64 = ppp_get_stats64, ++ .ndo_fill_forward_path = ppp_fill_forward_path, + }; + + static struct device_type ppp_type = { +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -972,8 +972,31 @@ static int pppoe_xmit(struct ppp_channel + return __pppoe_xmit(sk, skb); + } + ++static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path, ++ const struct ppp_channel *chan) ++{ ++ struct sock *sk = (struct sock *)chan->private; ++ struct pppox_sock *po = pppox_sk(sk); ++ struct net_device *dev = po->pppoe_dev; ++ ++ if (sock_flag(sk, SOCK_DEAD) || ++ !(sk->sk_state & PPPOX_CONNECTED) || !dev) ++ return -1; ++ ++ path->type = DEV_PATH_PPPOE; ++ path->encap.proto = htons(ETH_P_PPP_SES); ++ path->encap.id = be16_to_cpu(po->num); ++ memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); ++ path->dev = ctx->dev; ++ ctx->dev = dev; ++ ++ return 0; ++} ++ + static const struct ppp_channel_ops pppoe_chan_ops = { + .start_xmit = pppoe_xmit, ++ .fill_forward_path = pppoe_fill_forward_path, + }; + + static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -831,6 +831,7 @@ enum net_device_path_type { + DEV_PATH_ETHERNET = 0, + DEV_PATH_VLAN, + DEV_PATH_BRIDGE, ++ DEV_PATH_PPPOE, + }; + + struct net_device_path { +@@ -840,6 +841,7 @@ struct net_device_path { + struct { + u16 id; + __be16 proto; ++ u8 h_dest[ETH_ALEN]; + } encap; + struct { + enum { +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -28,6 +28,9 @@ struct ppp_channel_ops { + int (*start_xmit)(struct ppp_channel *, struct sk_buff *); + /* Handle an ioctl call that has come in via /dev/ppp. */ + int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); ++ int (*fill_forward_path)(struct net_device_path_ctx *, ++ struct net_device_path *, ++ const struct ppp_channel *); + }; + + struct ppp_channel { diff --git a/target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch b/target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch new file mode 100644 index 0000000000..1d3021a575 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch @@ -0,0 +1,63 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:37 +0100 +Subject: [PATCH] net: dsa: resolve forwarding path for dsa slave ports + +Add .ndo_fill_forward_path for dsa slave port devices + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -832,6 +832,7 @@ enum net_device_path_type { + DEV_PATH_VLAN, + DEV_PATH_BRIDGE, + DEV_PATH_PPPOE, ++ DEV_PATH_DSA, + }; + + struct net_device_path { +@@ -852,6 +853,10 @@ struct net_device_path { + u16 vlan_id; + __be16 vlan_proto; + } bridge; ++ struct { ++ int port; ++ u16 proto; ++ } dsa; + }; + }; + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -1619,6 +1619,21 @@ static struct devlink_port *dsa_slave_ge + return dp->ds->devlink ? &dp->devlink_port : NULL; + } + ++static int dsa_slave_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct dsa_port *dp = dsa_slave_to_port(ctx->dev); ++ struct dsa_port *cpu_dp = dp->cpu_dp; ++ ++ path->dev = ctx->dev; ++ path->type = DEV_PATH_DSA; ++ path->dsa.proto = cpu_dp->tag_ops->proto; ++ path->dsa.port = dp->index; ++ ctx->dev = cpu_dp->master; ++ ++ return 0; ++} ++ + static const struct net_device_ops dsa_slave_netdev_ops = { + .ndo_open = dsa_slave_open, + .ndo_stop = dsa_slave_close, +@@ -1644,6 +1659,7 @@ static const struct net_device_ops dsa_s + .ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid, + .ndo_get_devlink_port = dsa_slave_get_devlink_port, + .ndo_change_mtu = dsa_slave_change_mtu, ++ .ndo_fill_forward_path = dsa_slave_fill_forward_path, + }; + + static struct device_type dsa_type = { diff --git a/target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch b/target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch new file mode 100644 index 0000000000..6052f67faa --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch @@ -0,0 +1,147 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:38 +0100 +Subject: [PATCH] netfilter: flowtable: add xmit path types + +Add the xmit_type field that defines the two supported xmit paths in the +flowtable data plane, which are the neighbour and the xfrm xmit paths. +This patch prepares for new flowtable xmit path types to come. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -89,6 +89,11 @@ enum flow_offload_tuple_dir { + }; + #define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX + ++enum flow_offload_xmit_type { ++ FLOW_OFFLOAD_XMIT_NEIGH = 0, ++ FLOW_OFFLOAD_XMIT_XFRM, ++}; ++ + struct flow_offload_tuple { + union { + struct in_addr src_v4; +@@ -111,7 +116,8 @@ struct flow_offload_tuple { + /* All members above are keys for lookups, see flow_offload_hash(). */ + struct { } __hash; + +- u8 dir; ++ u8 dir:6, ++ xmit_type:2; + + u16 mtu; + +@@ -157,7 +163,8 @@ static inline __s32 nf_flow_timeout_delt + + struct nf_flow_route { + struct { +- struct dst_entry *dst; ++ struct dst_entry *dst; ++ enum flow_offload_xmit_type xmit_type; + } tuple[FLOW_OFFLOAD_DIR_MAX]; + }; + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -95,6 +95,7 @@ static int flow_offload_fill_route(struc + } + + flow_tuple->iifidx = other_dst->dev->ifindex; ++ flow_tuple->xmit_type = route->tuple[dir].xmit_type; + flow_tuple->dst_cache = dst; + + return 0; +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -235,8 +235,6 @@ nf_flow_offload_ip_hook(void *priv, stru + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache; +- outdev = rt->dst.dev; + + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; +@@ -265,13 +263,16 @@ nf_flow_offload_ip_hook(void *priv, stru + if (flow_table->flags & NF_FLOWTABLE_COUNTER) + nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); + +- if (unlikely(dst_xfrm(&rt->dst))) { ++ rt = (struct rtable *)tuplehash->tuple.dst_cache; ++ ++ if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { + memset(skb->cb, 0, sizeof(struct inet_skb_parm)); + IPCB(skb)->iif = skb->dev->ifindex; + IPCB(skb)->flags = IPSKB_FORWARDED; + return nf_flow_xmit_xfrm(skb, state, &rt->dst); + } + ++ outdev = rt->dst.dev; + skb->dev = outdev; + nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); + skb_dst_set_noref(skb, &rt->dst); +@@ -456,8 +457,6 @@ nf_flow_offload_ipv6_hook(void *priv, st + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; +- outdev = rt->dst.dev; + + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; +@@ -485,13 +484,16 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (flow_table->flags & NF_FLOWTABLE_COUNTER) + nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); + +- if (unlikely(dst_xfrm(&rt->dst))) { ++ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; ++ ++ if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + IP6CB(skb)->iif = skb->dev->ifindex; + IP6CB(skb)->flags = IP6SKB_FORWARDED; + return nf_flow_xmit_xfrm(skb, state, &rt->dst); + } + ++ outdev = rt->dst.dev; + skb->dev = outdev; + nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); + skb_dst_set_noref(skb, &rt->dst); +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -19,6 +19,22 @@ struct nft_flow_offload { + struct nft_flowtable *flowtable; + }; + ++static enum flow_offload_xmit_type nft_xmit_type(struct dst_entry *dst) ++{ ++ if (dst_xfrm(dst)) ++ return FLOW_OFFLOAD_XMIT_XFRM; ++ ++ return FLOW_OFFLOAD_XMIT_NEIGH; ++} ++ ++static void nft_default_forward_path(struct nf_flow_route *route, ++ struct dst_entry *dst_cache, ++ enum ip_conntrack_dir dir) ++{ ++ route->tuple[dir].dst = dst_cache; ++ route->tuple[dir].xmit_type = nft_xmit_type(dst_cache); ++} ++ + static int nft_flow_route(const struct nft_pktinfo *pkt, + const struct nf_conn *ct, + struct nf_flow_route *route, +@@ -44,8 +60,8 @@ static int nft_flow_route(const struct n + if (!other_dst) + return -ENOENT; + +- route->tuple[dir].dst = this_dst; +- route->tuple[!dir].dst = other_dst; ++ nft_default_forward_path(route, this_dst, dir); ++ nft_default_forward_path(route, other_dst, !dir); + + return 0; + } diff --git a/target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch b/target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch new file mode 100644 index 0000000000..9541ce8867 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch @@ -0,0 +1,191 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:39 +0100 +Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to + obtain ingress device + +Obtain the ingress device in the tuple from the route in the reply +direction. Use dev_fill_forward_path() instead to get the real ingress +device for this flow. + +Fall back to use the ingress device that the IP forwarding route +provides if: + +- dev_fill_forward_path() finds no real ingress device. +- the ingress device that is obtained is not part of the flowtable + devices. +- this route has a xfrm policy. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -164,6 +164,9 @@ static inline __s32 nf_flow_timeout_delt + struct nf_flow_route { + struct { + struct dst_entry *dst; ++ struct { ++ u32 ifindex; ++ } in; + enum flow_offload_xmit_type xmit_type; + } tuple[FLOW_OFFLOAD_DIR_MAX]; + }; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -79,7 +79,6 @@ static int flow_offload_fill_route(struc + enum flow_offload_tuple_dir dir) + { + struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; +- struct dst_entry *other_dst = route->tuple[!dir].dst; + struct dst_entry *dst = route->tuple[dir].dst; + + if (!dst_hold_safe(route->tuple[dir].dst)) +@@ -94,7 +93,7 @@ static int flow_offload_fill_route(struc + break; + } + +- flow_tuple->iifidx = other_dst->dev->ifindex; ++ flow_tuple->iifidx = route->tuple[dir].in.ifindex; + flow_tuple->xmit_type = route->tuple[dir].xmit_type; + flow_tuple->dst_cache = dst; + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -31,14 +31,104 @@ static void nft_default_forward_path(str + struct dst_entry *dst_cache, + enum ip_conntrack_dir dir) + { ++ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex; + route->tuple[dir].dst = dst_cache; + route->tuple[dir].xmit_type = nft_xmit_type(dst_cache); + } + ++static int nft_dev_fill_forward_path(const struct nf_flow_route *route, ++ const struct dst_entry *dst_cache, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct net_device_path_stack *stack) ++{ ++ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; ++ struct net_device *dev = dst_cache->dev; ++ unsigned char ha[ETH_ALEN]; ++ struct neighbour *n; ++ u8 nud_state; ++ ++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return -1; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ ether_addr_copy(ha, n->ha); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); ++ ++ if (!(nud_state & NUD_VALID)) ++ return -1; ++ ++ return dev_fill_forward_path(dev, ha, stack); ++} ++ ++struct nft_forward_info { ++ const struct net_device *indev; ++}; ++ ++static void nft_dev_path_info(const struct net_device_path_stack *stack, ++ struct nft_forward_info *info) ++{ ++ const struct net_device_path *path; ++ int i; ++ ++ for (i = 0; i < stack->num_paths; i++) { ++ path = &stack->path[i]; ++ switch (path->type) { ++ case DEV_PATH_ETHERNET: ++ info->indev = path->dev; ++ break; ++ case DEV_PATH_VLAN: ++ case DEV_PATH_BRIDGE: ++ default: ++ info->indev = NULL; ++ break; ++ } ++ } ++} ++ ++static bool nft_flowtable_find_dev(const struct net_device *dev, ++ struct nft_flowtable *ft) ++{ ++ struct nft_hook *hook; ++ bool found = false; ++ ++ list_for_each_entry_rcu(hook, &ft->hook_list, list) { ++ if (hook->ops.dev != dev) ++ continue; ++ ++ found = true; ++ break; ++ } ++ ++ return found; ++} ++ ++static void nft_dev_forward_path(struct nf_flow_route *route, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct nft_flowtable *ft) ++{ ++ const struct dst_entry *dst = route->tuple[dir].dst; ++ struct net_device_path_stack stack; ++ struct nft_forward_info info = {}; ++ ++ if (nft_dev_fill_forward_path(route, dst, ct, dir, &stack) >= 0) ++ nft_dev_path_info(&stack, &info); ++ ++ if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) ++ return; ++ ++ route->tuple[!dir].in.ifindex = info.indev->ifindex; ++} ++ + static int nft_flow_route(const struct nft_pktinfo *pkt, + const struct nf_conn *ct, + struct nf_flow_route *route, +- enum ip_conntrack_dir dir) ++ enum ip_conntrack_dir dir, ++ struct nft_flowtable *ft) + { + struct dst_entry *this_dst = skb_dst(pkt->skb); + struct dst_entry *other_dst = NULL; +@@ -63,6 +153,12 @@ static int nft_flow_route(const struct n + nft_default_forward_path(route, this_dst, dir); + nft_default_forward_path(route, other_dst, !dir); + ++ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH && ++ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) { ++ nft_dev_forward_path(route, ct, dir, ft); ++ nft_dev_forward_path(route, ct, !dir, ft); ++ } ++ + return 0; + } + +@@ -90,8 +186,8 @@ static void nft_flow_offload_eval(const + struct nft_flow_offload *priv = nft_expr_priv(expr); + struct nf_flowtable *flowtable = &priv->flowtable->data; + struct tcphdr _tcph, *tcph = NULL; ++ struct nf_flow_route route = {}; + enum ip_conntrack_info ctinfo; +- struct nf_flow_route route; + struct flow_offload *flow; + enum ip_conntrack_dir dir; + struct nf_conn *ct; +@@ -128,7 +224,7 @@ static void nft_flow_offload_eval(const + goto out; + + dir = CTINFO2DIR(ctinfo); +- if (nft_flow_route(pkt, ct, &route, dir) < 0) ++ if (nft_flow_route(pkt, ct, &route, dir, priv->flowtable) < 0) + goto err_flow_route; + + flow = flow_offload_alloc(ct); diff --git a/target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch b/target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch new file mode 100644 index 0000000000..457e218d9b --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch @@ -0,0 +1,374 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:40 +0100 +Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to + obtain egress device + +The egress device in the tuple is obtained from route. Use +dev_fill_forward_path() instead to provide the real egress device for +this flow whenever this is available. + +The new FLOW_OFFLOAD_XMIT_DIRECT type uses dev_queue_xmit() to transmit +ethernet frames. Cache the source and destination hardware address to +use dev_queue_xmit() to transfer packets. + +The FLOW_OFFLOAD_XMIT_DIRECT replaces FLOW_OFFLOAD_XMIT_NEIGH if +dev_fill_forward_path() finds a direct transmit path. + +In case of topology updates, if peer is moved to different bridge port, +the connection will time out, reconnect will result in a new entry with +the correct path. Snooping fdb updates would allow for cleaning up stale +flowtable entries. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -92,6 +92,7 @@ enum flow_offload_tuple_dir { + enum flow_offload_xmit_type { + FLOW_OFFLOAD_XMIT_NEIGH = 0, + FLOW_OFFLOAD_XMIT_XFRM, ++ FLOW_OFFLOAD_XMIT_DIRECT, + }; + + struct flow_offload_tuple { +@@ -120,8 +121,14 @@ struct flow_offload_tuple { + xmit_type:2; + + u16 mtu; +- +- struct dst_entry *dst_cache; ++ union { ++ struct dst_entry *dst_cache; ++ struct { ++ u32 ifidx; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ } out; ++ }; + }; + + struct flow_offload_tuple_rhash { +@@ -167,6 +174,11 @@ struct nf_flow_route { + struct { + u32 ifindex; + } in; ++ struct { ++ u32 ifindex; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ } out; + enum flow_offload_xmit_type xmit_type; + } tuple[FLOW_OFFLOAD_DIR_MAX]; + }; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -81,9 +81,6 @@ static int flow_offload_fill_route(struc + struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; + struct dst_entry *dst = route->tuple[dir].dst; + +- if (!dst_hold_safe(route->tuple[dir].dst)) +- return -1; +- + switch (flow_tuple->l3proto) { + case NFPROTO_IPV4: + flow_tuple->mtu = ip_dst_mtu_maybe_forward(dst, true); +@@ -94,12 +91,36 @@ static int flow_offload_fill_route(struc + } + + flow_tuple->iifidx = route->tuple[dir].in.ifindex; ++ ++ switch (route->tuple[dir].xmit_type) { ++ case FLOW_OFFLOAD_XMIT_DIRECT: ++ memcpy(flow_tuple->out.h_dest, route->tuple[dir].out.h_dest, ++ ETH_ALEN); ++ memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source, ++ ETH_ALEN); ++ flow_tuple->out.ifidx = route->tuple[dir].out.ifindex; ++ break; ++ case FLOW_OFFLOAD_XMIT_XFRM: ++ case FLOW_OFFLOAD_XMIT_NEIGH: ++ if (!dst_hold_safe(route->tuple[dir].dst)) ++ return -1; ++ ++ flow_tuple->dst_cache = dst; ++ break; ++ } + flow_tuple->xmit_type = route->tuple[dir].xmit_type; +- flow_tuple->dst_cache = dst; + + return 0; + } + ++static void nft_flow_dst_release(struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir) ++{ ++ if (flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || ++ flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) ++ dst_release(flow->tuplehash[dir].tuple.dst_cache); ++} ++ + int flow_offload_route_init(struct flow_offload *flow, + const struct nf_flow_route *route) + { +@@ -118,7 +139,7 @@ int flow_offload_route_init(struct flow_ + return 0; + + err_route_reply: +- dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); ++ nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_ORIGINAL); + + return err; + } +@@ -169,8 +190,8 @@ static void flow_offload_fixup_ct(struct + + static void flow_offload_route_release(struct flow_offload *flow) + { +- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); +- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); ++ nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_ORIGINAL); ++ nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_REPLY); + } + + void flow_offload_free(struct flow_offload *flow) +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -207,6 +207,24 @@ static unsigned int nf_flow_xmit_xfrm(st + return NF_STOLEN; + } + ++static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, ++ const struct flow_offload_tuple_rhash *tuplehash, ++ unsigned short type) ++{ ++ struct net_device *outdev; ++ ++ outdev = dev_get_by_index_rcu(net, tuplehash->tuple.out.ifidx); ++ if (!outdev) ++ return NF_DROP; ++ ++ skb->dev = outdev; ++ dev_hard_header(skb, skb->dev, type, tuplehash->tuple.out.h_dest, ++ tuplehash->tuple.out.h_source, skb->len); ++ dev_queue_xmit(skb); ++ ++ return NF_STOLEN; ++} ++ + unsigned int + nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +@@ -222,6 +240,7 @@ nf_flow_offload_ip_hook(void *priv, stru + struct iphdr *iph; + __be32 nexthop; + u32 hdrsize; ++ int ret; + + if (skb->protocol != htons(ETH_P_IP)) + return NF_ACCEPT; +@@ -244,9 +263,13 @@ nf_flow_offload_ip_hook(void *priv, stru + if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) + return NF_ACCEPT; + +- if (!dst_check(&rt->dst, 0)) { +- flow_offload_teardown(flow); +- return NF_ACCEPT; ++ if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || ++ tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { ++ rt = (struct rtable *)tuplehash->tuple.dst_cache; ++ if (!dst_check(&rt->dst, 0)) { ++ flow_offload_teardown(flow); ++ return NF_ACCEPT; ++ } + } + + if (skb_try_make_writable(skb, thoff + hdrsize)) +@@ -263,8 +286,6 @@ nf_flow_offload_ip_hook(void *priv, stru + if (flow_table->flags & NF_FLOWTABLE_COUNTER) + nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); + +- rt = (struct rtable *)tuplehash->tuple.dst_cache; +- + if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { + memset(skb->cb, 0, sizeof(struct inet_skb_parm)); + IPCB(skb)->iif = skb->dev->ifindex; +@@ -272,13 +293,23 @@ nf_flow_offload_ip_hook(void *priv, stru + return nf_flow_xmit_xfrm(skb, state, &rt->dst); + } + +- outdev = rt->dst.dev; +- skb->dev = outdev; +- nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +- skb_dst_set_noref(skb, &rt->dst); +- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++ switch (tuplehash->tuple.xmit_type) { ++ case FLOW_OFFLOAD_XMIT_NEIGH: ++ outdev = rt->dst.dev; ++ skb->dev = outdev; ++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); ++ skb_dst_set_noref(skb, &rt->dst); ++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++ ret = NF_STOLEN; ++ break; ++ case FLOW_OFFLOAD_XMIT_DIRECT: ++ ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IP); ++ if (ret == NF_DROP) ++ flow_offload_teardown(flow); ++ break; ++ } + +- return NF_STOLEN; ++ return ret; + } + EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); + +@@ -444,6 +475,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + struct ipv6hdr *ip6h; + struct rt6_info *rt; + u32 hdrsize; ++ int ret; + + if (skb->protocol != htons(ETH_P_IPV6)) + return NF_ACCEPT; +@@ -465,9 +497,13 @@ nf_flow_offload_ipv6_hook(void *priv, st + sizeof(*ip6h))) + return NF_ACCEPT; + +- if (!dst_check(&rt->dst, 0)) { +- flow_offload_teardown(flow); +- return NF_ACCEPT; ++ if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || ++ tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { ++ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; ++ if (!dst_check(&rt->dst, 0)) { ++ flow_offload_teardown(flow); ++ return NF_ACCEPT; ++ } + } + + if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) +@@ -484,8 +520,6 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (flow_table->flags & NF_FLOWTABLE_COUNTER) + nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); + +- rt = (struct rt6_info *)tuplehash->tuple.dst_cache; +- + if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + IP6CB(skb)->iif = skb->dev->ifindex; +@@ -493,12 +527,22 @@ nf_flow_offload_ipv6_hook(void *priv, st + return nf_flow_xmit_xfrm(skb, state, &rt->dst); + } + +- outdev = rt->dst.dev; +- skb->dev = outdev; +- nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); +- skb_dst_set_noref(skb, &rt->dst); +- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++ switch (tuplehash->tuple.xmit_type) { ++ case FLOW_OFFLOAD_XMIT_NEIGH: ++ outdev = rt->dst.dev; ++ skb->dev = outdev; ++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); ++ skb_dst_set_noref(skb, &rt->dst); ++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++ ret = NF_STOLEN; ++ break; ++ case FLOW_OFFLOAD_XMIT_DIRECT: ++ ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IPV6); ++ if (ret == NF_DROP) ++ flow_offload_teardown(flow); ++ break; ++ } + +- return NF_STOLEN; ++ return ret; + } + EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -39,12 +39,11 @@ static void nft_default_forward_path(str + static int nft_dev_fill_forward_path(const struct nf_flow_route *route, + const struct dst_entry *dst_cache, + const struct nf_conn *ct, +- enum ip_conntrack_dir dir, ++ enum ip_conntrack_dir dir, u8 *ha, + struct net_device_path_stack *stack) + { + const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; + struct net_device *dev = dst_cache->dev; +- unsigned char ha[ETH_ALEN]; + struct neighbour *n; + u8 nud_state; + +@@ -66,27 +65,43 @@ static int nft_dev_fill_forward_path(con + + struct nft_forward_info { + const struct net_device *indev; ++ const struct net_device *outdev; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ enum flow_offload_xmit_type xmit_type; + }; + + static void nft_dev_path_info(const struct net_device_path_stack *stack, +- struct nft_forward_info *info) ++ struct nft_forward_info *info, ++ unsigned char *ha) + { + const struct net_device_path *path; + int i; + ++ memcpy(info->h_dest, ha, ETH_ALEN); ++ + for (i = 0; i < stack->num_paths; i++) { + path = &stack->path[i]; + switch (path->type) { + case DEV_PATH_ETHERNET: + info->indev = path->dev; ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + break; +- case DEV_PATH_VLAN: + case DEV_PATH_BRIDGE: ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; ++ break; ++ case DEV_PATH_VLAN: + default: + info->indev = NULL; + break; + } + } ++ if (!info->outdev) ++ info->outdev = info->indev; + } + + static bool nft_flowtable_find_dev(const struct net_device *dev, +@@ -114,14 +129,22 @@ static void nft_dev_forward_path(struct + const struct dst_entry *dst = route->tuple[dir].dst; + struct net_device_path_stack stack; + struct nft_forward_info info = {}; ++ unsigned char ha[ETH_ALEN]; + +- if (nft_dev_fill_forward_path(route, dst, ct, dir, &stack) >= 0) +- nft_dev_path_info(&stack, &info); ++ if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) ++ nft_dev_path_info(&stack, &info, ha); + + if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) + return; + + route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ ++ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { ++ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); ++ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); ++ route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].xmit_type = info.xmit_type; ++ } + } + + static int nft_flow_route(const struct nft_pktinfo *pkt, diff --git a/target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch b/target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch new file mode 100644 index 0000000000..86a1129880 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch @@ -0,0 +1,410 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:41 +0100 +Subject: [PATCH] netfilter: flowtable: add vlan support + +Add the vlan id and protocol to the flow tuple to uniquely identify +flows from the receive path. For the transmit path, dev_hard_header() on +the vlan device push the headers. This patch includes support for two +vlan headers (QinQ) from the ingress path. + +Add a generic encap field to the flowtable entry which stores the +protocol and the tag id. This allows to reuse these fields in the PPPoE +support coming in a later patch. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -95,6 +95,8 @@ enum flow_offload_xmit_type { + FLOW_OFFLOAD_XMIT_DIRECT, + }; + ++#define NF_FLOW_TABLE_ENCAP_MAX 2 ++ + struct flow_offload_tuple { + union { + struct in_addr src_v4; +@@ -113,13 +115,17 @@ struct flow_offload_tuple { + + u8 l3proto; + u8 l4proto; ++ struct { ++ u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; + + /* All members above are keys for lookups, see flow_offload_hash(). */ + struct { } __hash; + +- u8 dir:6, +- xmit_type:2; +- ++ u8 dir:4, ++ xmit_type:2, ++ encap_num:2; + u16 mtu; + union { + struct dst_entry *dst_cache; +@@ -173,6 +179,11 @@ struct nf_flow_route { + struct dst_entry *dst; + struct { + u32 ifindex; ++ struct { ++ u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; + } in; + struct { + u32 ifindex; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -80,6 +80,7 @@ static int flow_offload_fill_route(struc + { + struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; + struct dst_entry *dst = route->tuple[dir].dst; ++ int i, j = 0; + + switch (flow_tuple->l3proto) { + case NFPROTO_IPV4: +@@ -91,6 +92,12 @@ static int flow_offload_fill_route(struc + } + + flow_tuple->iifidx = route->tuple[dir].in.ifindex; ++ for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) { ++ flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id; ++ flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto; ++ j++; ++ } ++ flow_tuple->encap_num = route->tuple[dir].in.num_encaps; + + switch (route->tuple[dir].xmit_type) { + case FLOW_OFFLOAD_XMIT_DIRECT: +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -136,23 +136,44 @@ static bool ip_has_options(unsigned int + return thoff != sizeof(struct iphdr); + } + ++static void nf_flow_tuple_encap(struct sk_buff *skb, ++ struct flow_offload_tuple *tuple) ++{ ++ int i = 0; ++ ++ if (skb_vlan_tag_present(skb)) { ++ tuple->encap[i].id = skb_vlan_tag_get(skb); ++ tuple->encap[i].proto = skb->vlan_proto; ++ i++; ++ } ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); ++ ++ tuple->encap[i].id = ntohs(veth->h_vlan_TCI); ++ tuple->encap[i].proto = skb->protocol; ++ } ++} ++ + static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple, u32 *hdrsize) ++ struct flow_offload_tuple *tuple, u32 *hdrsize, ++ u32 offset) + { + struct flow_ports *ports; + unsigned int thoff; + struct iphdr *iph; + +- if (!pskb_may_pull(skb, sizeof(*iph))) ++ if (!pskb_may_pull(skb, sizeof(*iph) + offset)) + return -1; + +- iph = ip_hdr(skb); +- thoff = iph->ihl * 4; ++ iph = (struct iphdr *)(skb_network_header(skb) + offset); ++ thoff = (iph->ihl * 4); + + if (ip_is_fragment(iph) || + unlikely(ip_has_options(thoff))) + return -1; + ++ thoff += offset; ++ + switch (iph->protocol) { + case IPPROTO_TCP: + *hdrsize = sizeof(struct tcphdr); +@@ -167,11 +188,10 @@ static int nf_flow_tuple_ip(struct sk_bu + if (iph->ttl <= 1) + return -1; + +- thoff = iph->ihl * 4; + if (!pskb_may_pull(skb, thoff + *hdrsize)) + return -1; + +- iph = ip_hdr(skb); ++ iph = (struct iphdr *)(skb_network_header(skb) + offset); + ports = (struct flow_ports *)(skb_network_header(skb) + thoff); + + tuple->src_v4.s_addr = iph->saddr; +@@ -181,6 +201,7 @@ static int nf_flow_tuple_ip(struct sk_bu + tuple->l3proto = AF_INET; + tuple->l4proto = iph->protocol; + tuple->iifidx = dev->ifindex; ++ nf_flow_tuple_encap(skb, tuple); + + return 0; + } +@@ -207,6 +228,43 @@ static unsigned int nf_flow_xmit_xfrm(st + return NF_STOLEN; + } + ++static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto, ++ u32 *offset) ++{ ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ struct vlan_ethhdr *veth; ++ ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); ++ if (veth->h_vlan_encapsulated_proto == proto) { ++ *offset += VLAN_HLEN; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static void nf_flow_encap_pop(struct sk_buff *skb, ++ struct flow_offload_tuple_rhash *tuplehash) ++{ ++ struct vlan_hdr *vlan_hdr; ++ int i; ++ ++ for (i = 0; i < tuplehash->tuple.encap_num; i++) { ++ if (skb_vlan_tag_present(skb)) { ++ __vlan_hwaccel_clear_tag(skb); ++ continue; ++ } ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ vlan_hdr = (struct vlan_hdr *)skb->data; ++ __skb_pull(skb, VLAN_HLEN); ++ vlan_set_encap_proto(skb, vlan_hdr); ++ skb_reset_network_header(skb); ++ break; ++ } ++ } ++} ++ + static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, + const struct flow_offload_tuple_rhash *tuplehash, + unsigned short type) +@@ -235,17 +293,18 @@ nf_flow_offload_ip_hook(void *priv, stru + enum flow_offload_tuple_dir dir; + struct flow_offload *flow; + struct net_device *outdev; ++ u32 hdrsize, offset = 0; ++ unsigned int thoff, mtu; + struct rtable *rt; +- unsigned int thoff; + struct iphdr *iph; + __be32 nexthop; +- u32 hdrsize; + int ret; + +- if (skb->protocol != htons(ETH_P_IP)) ++ if (skb->protocol != htons(ETH_P_IP) && ++ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP), &offset)) + return NF_ACCEPT; + +- if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize) < 0) ++ if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize, offset) < 0) + return NF_ACCEPT; + + tuplehash = flow_offload_lookup(flow_table, &tuple); +@@ -255,11 +314,12 @@ nf_flow_offload_ip_hook(void *priv, stru + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ mtu = flow->tuplehash[dir].tuple.mtu + offset; ++ if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) + return NF_ACCEPT; + +- iph = ip_hdr(skb); +- thoff = iph->ihl * 4; ++ iph = (struct iphdr *)(skb_network_header(skb) + offset); ++ thoff = (iph->ihl * 4) + offset; + if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) + return NF_ACCEPT; + +@@ -277,6 +337,9 @@ nf_flow_offload_ip_hook(void *priv, stru + + flow_offload_refresh(flow_table, flow); + ++ nf_flow_encap_pop(skb, tuplehash); ++ thoff -= offset; ++ + iph = ip_hdr(skb); + nf_flow_nat_ip(flow, skb, thoff, dir, iph); + +@@ -418,16 +481,18 @@ static void nf_flow_nat_ipv6(const struc + } + + static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple, u32 *hdrsize) ++ struct flow_offload_tuple *tuple, u32 *hdrsize, ++ u32 offset) + { + struct flow_ports *ports; + struct ipv6hdr *ip6h; + unsigned int thoff; + +- if (!pskb_may_pull(skb, sizeof(*ip6h))) ++ thoff = sizeof(*ip6h) + offset; ++ if (!pskb_may_pull(skb, thoff)) + return -1; + +- ip6h = ipv6_hdr(skb); ++ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); + + switch (ip6h->nexthdr) { + case IPPROTO_TCP: +@@ -443,11 +508,10 @@ static int nf_flow_tuple_ipv6(struct sk_ + if (ip6h->hop_limit <= 1) + return -1; + +- thoff = sizeof(*ip6h); + if (!pskb_may_pull(skb, thoff + *hdrsize)) + return -1; + +- ip6h = ipv6_hdr(skb); ++ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); + ports = (struct flow_ports *)(skb_network_header(skb) + thoff); + + tuple->src_v6 = ip6h->saddr; +@@ -457,6 +521,7 @@ static int nf_flow_tuple_ipv6(struct sk_ + tuple->l3proto = AF_INET6; + tuple->l4proto = ip6h->nexthdr; + tuple->iifidx = dev->ifindex; ++ nf_flow_tuple_encap(skb, tuple); + + return 0; + } +@@ -472,15 +537,17 @@ nf_flow_offload_ipv6_hook(void *priv, st + const struct in6_addr *nexthop; + struct flow_offload *flow; + struct net_device *outdev; ++ unsigned int thoff, mtu; ++ u32 hdrsize, offset = 0; + struct ipv6hdr *ip6h; + struct rt6_info *rt; +- u32 hdrsize; + int ret; + +- if (skb->protocol != htons(ETH_P_IPV6)) ++ if (skb->protocol != htons(ETH_P_IPV6) && ++ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6), &offset)) + return NF_ACCEPT; + +- if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize) < 0) ++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize, offset) < 0) + return NF_ACCEPT; + + tuplehash = flow_offload_lookup(flow_table, &tuple); +@@ -490,11 +557,13 @@ nf_flow_offload_ipv6_hook(void *priv, st + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ mtu = flow->tuplehash[dir].tuple.mtu + offset; ++ if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) + return NF_ACCEPT; + +- if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb, +- sizeof(*ip6h))) ++ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); ++ thoff = sizeof(*ip6h) + offset; ++ if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff)) + return NF_ACCEPT; + + if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || +@@ -506,11 +575,13 @@ nf_flow_offload_ipv6_hook(void *priv, st + } + } + +- if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) ++ if (skb_try_make_writable(skb, thoff + hdrsize)) + return NF_DROP; + + flow_offload_refresh(flow_table, flow); + ++ nf_flow_encap_pop(skb, tuplehash); ++ + ip6h = ipv6_hdr(skb); + nf_flow_nat_ipv6(flow, skb, dir, ip6h); + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -66,6 +66,11 @@ static int nft_dev_fill_forward_path(con + struct nft_forward_info { + const struct net_device *indev; + const struct net_device *outdev; ++ struct id { ++ __u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + enum flow_offload_xmit_type xmit_type; +@@ -84,9 +89,23 @@ static void nft_dev_path_info(const stru + path = &stack->path[i]; + switch (path->type) { + case DEV_PATH_ETHERNET: ++ case DEV_PATH_VLAN: + info->indev = path->dev; + if (is_zero_ether_addr(info->h_source)) + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ if (path->type == DEV_PATH_ETHERNET) ++ break; ++ ++ /* DEV_PATH_VLAN */ ++ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { ++ info->indev = NULL; ++ break; ++ } ++ info->outdev = path->dev; ++ info->encap[info->num_encaps].id = path->encap.id; ++ info->encap[info->num_encaps].proto = path->encap.proto; ++ info->num_encaps++; + break; + case DEV_PATH_BRIDGE: + if (is_zero_ether_addr(info->h_source)) +@@ -94,7 +113,6 @@ static void nft_dev_path_info(const stru + + info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; + break; +- case DEV_PATH_VLAN: + default: + info->indev = NULL; + break; +@@ -130,6 +148,7 @@ static void nft_dev_forward_path(struct + struct net_device_path_stack stack; + struct nft_forward_info info = {}; + unsigned char ha[ETH_ALEN]; ++ int i; + + if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) + nft_dev_path_info(&stack, &info, ha); +@@ -138,6 +157,11 @@ static void nft_dev_forward_path(struct + return; + + route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ for (i = 0; i < info.num_encaps; i++) { ++ route->tuple[!dir].in.encap[i].id = info.encap[i].id; ++ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; ++ } ++ route->tuple[!dir].in.num_encaps = info.num_encaps; + + if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { + memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); diff --git a/target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch b/target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch new file mode 100644 index 0000000000..cb3ef99029 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch @@ -0,0 +1,30 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:42 +0100 +Subject: [PATCH] netfilter: flowtable: add bridge vlan filtering support + +Add the vlan tag based when PVID is set on. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -111,6 +111,18 @@ static void nft_dev_path_info(const stru + if (is_zero_ether_addr(info->h_source)) + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_TAG: ++ info->encap[info->num_encaps].id = path->bridge.vlan_id; ++ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; ++ info->num_encaps++; ++ break; ++ case DEV_PATH_BR_VLAN_UNTAG: ++ info->num_encaps--; ++ break; ++ case DEV_PATH_BR_VLAN_KEEP: ++ break; ++ } + info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; + break; + default: diff --git a/target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch b/target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch new file mode 100644 index 0000000000..d5789cbad2 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch @@ -0,0 +1,145 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:43 +0100 +Subject: [PATCH] netfilter: flowtable: add pppoe support + +Add the PPPoE protocol and session id to the flow tuple using the encap +fields to uniquely identify flows from the receive path. For the +transmit path, dev_hard_header() on the vlan device push the headers. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -7,6 +7,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -139,6 +142,8 @@ static bool ip_has_options(unsigned int + static void nf_flow_tuple_encap(struct sk_buff *skb, + struct flow_offload_tuple *tuple) + { ++ struct vlan_ethhdr *veth; ++ struct pppoe_hdr *phdr; + int i = 0; + + if (skb_vlan_tag_present(skb)) { +@@ -146,11 +151,17 @@ static void nf_flow_tuple_encap(struct s + tuple->encap[i].proto = skb->vlan_proto; + i++; + } +- if (skb->protocol == htons(ETH_P_8021Q)) { +- struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); +- ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); + tuple->encap[i].id = ntohs(veth->h_vlan_TCI); + tuple->encap[i].proto = skb->protocol; ++ break; ++ case htons(ETH_P_PPP_SES): ++ phdr = (struct pppoe_hdr *)skb_mac_header(skb); ++ tuple->encap[i].id = ntohs(phdr->sid); ++ tuple->encap[i].proto = skb->protocol; ++ break; + } + } + +@@ -228,17 +239,41 @@ static unsigned int nf_flow_xmit_xfrm(st + return NF_STOLEN; + } + ++static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) ++{ ++ __be16 proto; ++ ++ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN + ++ sizeof(struct pppoe_hdr))); ++ switch (proto) { ++ case htons(PPP_IP): ++ return htons(ETH_P_IP); ++ case htons(PPP_IPV6): ++ return htons(ETH_P_IPV6); ++ } ++ ++ return 0; ++} ++ + static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto, + u32 *offset) + { +- if (skb->protocol == htons(ETH_P_8021Q)) { +- struct vlan_ethhdr *veth; ++ struct vlan_ethhdr *veth; + ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + if (veth->h_vlan_encapsulated_proto == proto) { + *offset += VLAN_HLEN; + return true; + } ++ break; ++ case htons(ETH_P_PPP_SES): ++ if (nf_flow_pppoe_proto(skb) == proto) { ++ *offset += PPPOE_SES_HLEN; ++ return true; ++ } ++ break; + } + + return false; +@@ -255,12 +290,18 @@ static void nf_flow_encap_pop(struct sk_ + __vlan_hwaccel_clear_tag(skb); + continue; + } +- if (skb->protocol == htons(ETH_P_8021Q)) { ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): + vlan_hdr = (struct vlan_hdr *)skb->data; + __skb_pull(skb, VLAN_HLEN); + vlan_set_encap_proto(skb, vlan_hdr); + skb_reset_network_header(skb); + break; ++ case htons(ETH_P_PPP_SES): ++ skb->protocol = nf_flow_pppoe_proto(skb); ++ skb_pull(skb, PPPOE_SES_HLEN); ++ skb_reset_network_header(skb); ++ break; + } + } + } +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -90,6 +90,7 @@ static void nft_dev_path_info(const stru + switch (path->type) { + case DEV_PATH_ETHERNET: + case DEV_PATH_VLAN: ++ case DEV_PATH_PPPOE: + info->indev = path->dev; + if (is_zero_ether_addr(info->h_source)) + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); +@@ -97,7 +98,7 @@ static void nft_dev_path_info(const stru + if (path->type == DEV_PATH_ETHERNET) + break; + +- /* DEV_PATH_VLAN */ ++ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ + if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { + info->indev = NULL; + break; +@@ -106,6 +107,8 @@ static void nft_dev_path_info(const stru + info->encap[info->num_encaps].id = path->encap.id; + info->encap[info->num_encaps].proto = path->encap.proto; + info->num_encaps++; ++ if (path->type == DEV_PATH_PPPOE) ++ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); + break; + case DEV_PATH_BRIDGE: + if (is_zero_ether_addr(info->h_source)) diff --git a/target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch b/target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch new file mode 100644 index 0000000000..b4931830d3 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch @@ -0,0 +1,32 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:44 +0100 +Subject: [PATCH] netfilter: flowtable: add dsa support + +Replace the master ethernet device by the dsa slave port. Packets coming +in from the software ingress path use the dsa slave port as input +device. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -89,6 +89,7 @@ static void nft_dev_path_info(const stru + path = &stack->path[i]; + switch (path->type) { + case DEV_PATH_ETHERNET: ++ case DEV_PATH_DSA: + case DEV_PATH_VLAN: + case DEV_PATH_PPPOE: + info->indev = path->dev; +@@ -97,6 +98,10 @@ static void nft_dev_path_info(const stru + + if (path->type == DEV_PATH_ETHERNET) + break; ++ if (path->type == DEV_PATH_DSA) { ++ i = stack->num_paths; ++ break; ++ } + + /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ + if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { diff --git a/target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch b/target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch new file mode 100644 index 0000000000..3f332c70d3 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch @@ -0,0 +1,107 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:45 +0100 +Subject: [PATCH] selftests: netfilter: flowtable bridge and vlan support + +This patch adds two new tests to cover bridge and vlan support: + +- Add a bridge device to the Router1 (nsr1) container and attach the + veth0 device to the bridge. Set the IP address to the bridge device + to exercise the bridge forwarding path. + +- Add vlan encapsulation between to the bridge device in the Router1 and + one of the sender containers (ns1). + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/tools/testing/selftests/netfilter/nft_flowtable.sh ++++ b/tools/testing/selftests/netfilter/nft_flowtable.sh +@@ -370,6 +370,88 @@ else + ip netns exec nsr1 nft list ruleset + fi + ++# Another test: ++# Add bridge interface br0 to Router1, with NAT enabled. ++ip -net nsr1 link add name br0 type bridge ++ip -net nsr1 addr flush dev veth0 ++ip -net nsr1 link set up dev veth0 ++ip -net nsr1 link set veth0 master br0 ++ip -net nsr1 addr add 10.0.1.1/24 dev br0 ++ip -net nsr1 addr add dead:1::1/64 dev br0 ++ip -net nsr1 link set up dev br0 ++ ++ip netns exec nsr1 sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null ++ ++# br0 with NAT enabled. ++ip netns exec nsr1 nft -f - <&2 ++ ip netns exec nsr1 nft list ruleset ++ ret=1 ++fi ++ ++# Another test: ++# Add bridge interface br0 to Router1, with NAT and VLAN. ++ip -net nsr1 link set veth0 nomaster ++ip -net nsr1 link set down dev veth0 ++ip -net nsr1 link add link veth0 name veth0.10 type vlan id 10 ++ip -net nsr1 link set up dev veth0 ++ip -net nsr1 link set up dev veth0.10 ++ip -net nsr1 link set veth0.10 master br0 ++ ++ip -net ns1 addr flush dev eth0 ++ip -net ns1 link add link eth0 name eth0.10 type vlan id 10 ++ip -net ns1 link set eth0 up ++ip -net ns1 link set eth0.10 up ++ip -net ns1 addr add 10.0.1.99/24 dev eth0.10 ++ip -net ns1 route add default via 10.0.1.1 ++ip -net ns1 addr add dead:1::99/64 dev eth0.10 ++ ++if test_tcp_forwarding_nat ns1 ns2; then ++ echo "PASS: flow offloaded for ns1/ns2 with bridge NAT and VLAN" ++else ++ echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2 ++ ip netns exec nsr1 nft list ruleset ++ ret=1 ++fi ++ ++# restore test topology (remove bridge and VLAN) ++ip -net nsr1 link set veth0 nomaster ++ip -net nsr1 link set veth0 down ++ip -net nsr1 link set veth0.10 down ++ip -net nsr1 link delete veth0.10 type vlan ++ip -net nsr1 link delete br0 type bridge ++ip -net ns1 addr flush dev eth0.10 ++ip -net ns1 link set eth0.10 down ++ip -net ns1 link set eth0 down ++ip -net ns1 link delete eth0.10 type vlan ++ ++# restore address in ns1 and nsr1 ++ip -net ns1 link set eth0 up ++ip -net ns1 addr add 10.0.1.99/24 dev eth0 ++ip -net ns1 route add default via 10.0.1.1 ++ip -net ns1 addr add dead:1::99/64 dev eth0 ++ip -net ns1 route add default via dead:1::1 ++ip -net nsr1 addr add 10.0.1.1/24 dev veth0 ++ip -net nsr1 addr add dead:1::1/64 dev veth0 ++ip -net nsr1 link set up dev veth0 ++ + KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1) + KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1) + SPI1=$RANDOM diff --git a/target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch b/target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch new file mode 100644 index 0000000000..7b6ec68d55 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch @@ -0,0 +1,310 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:46 +0100 +Subject: [PATCH] netfilter: flowtable: add offload support for xmit path + types + +When the flow tuple xmit_type is set to FLOW_OFFLOAD_XMIT_DIRECT, the +dst_cache pointer is not valid, and the h_source/h_dest/ifidx out fields +need to be used. + +This patch also adds the FLOW_ACTION_VLAN_PUSH action to pass the VLAN +tag to the driver. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -177,28 +177,45 @@ static int flow_offload_eth_src(struct n + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) + { +- const struct flow_offload_tuple *tuple = &flow->tuplehash[!dir].tuple; + struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule); + struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule); +- struct net_device *dev; ++ const struct flow_offload_tuple *other_tuple, *this_tuple; ++ struct net_device *dev = NULL; ++ const unsigned char *addr; + u32 mask, val; + u16 val16; + +- dev = dev_get_by_index(net, tuple->iifidx); +- if (!dev) +- return -ENOENT; ++ this_tuple = &flow->tuplehash[dir].tuple; ++ ++ switch (this_tuple->xmit_type) { ++ case FLOW_OFFLOAD_XMIT_DIRECT: ++ addr = this_tuple->out.h_source; ++ break; ++ case FLOW_OFFLOAD_XMIT_NEIGH: ++ other_tuple = &flow->tuplehash[!dir].tuple; ++ dev = dev_get_by_index(net, other_tuple->iifidx); ++ if (!dev) ++ return -ENOENT; ++ ++ addr = dev->dev_addr; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } + + mask = ~0xffff0000; +- memcpy(&val16, dev->dev_addr, 2); ++ memcpy(&val16, addr, 2); + val = val16 << 16; + flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4, + &val, &mask); + + mask = ~0xffffffff; +- memcpy(&val, dev->dev_addr + 2, 4); ++ memcpy(&val, addr + 2, 4); + flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 8, + &val, &mask); +- dev_put(dev); ++ ++ if (dev) ++ dev_put(dev); + + return 0; + } +@@ -210,27 +227,40 @@ static int flow_offload_eth_dst(struct n + { + struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule); + struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule); +- const void *daddr = &flow->tuplehash[!dir].tuple.src_v4; ++ const struct flow_offload_tuple *other_tuple, *this_tuple; + const struct dst_entry *dst_cache; + unsigned char ha[ETH_ALEN]; + struct neighbour *n; ++ const void *daddr; + u32 mask, val; + u8 nud_state; + u16 val16; + +- dst_cache = flow->tuplehash[dir].tuple.dst_cache; +- n = dst_neigh_lookup(dst_cache, daddr); +- if (!n) +- return -ENOENT; +- +- read_lock_bh(&n->lock); +- nud_state = n->nud_state; +- ether_addr_copy(ha, n->ha); +- read_unlock_bh(&n->lock); ++ this_tuple = &flow->tuplehash[dir].tuple; + +- if (!(nud_state & NUD_VALID)) { ++ switch (this_tuple->xmit_type) { ++ case FLOW_OFFLOAD_XMIT_DIRECT: ++ ether_addr_copy(ha, this_tuple->out.h_dest); ++ break; ++ case FLOW_OFFLOAD_XMIT_NEIGH: ++ other_tuple = &flow->tuplehash[!dir].tuple; ++ daddr = &other_tuple->src_v4; ++ dst_cache = this_tuple->dst_cache; ++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return -ENOENT; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ ether_addr_copy(ha, n->ha); ++ read_unlock_bh(&n->lock); + neigh_release(n); +- return -ENOENT; ++ ++ if (!(nud_state & NUD_VALID)) ++ return -ENOENT; ++ break; ++ default: ++ return -EOPNOTSUPP; + } + + mask = ~0xffffffff; +@@ -243,7 +273,6 @@ static int flow_offload_eth_dst(struct n + val = val16; + flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4, + &val, &mask); +- neigh_release(n); + + return 0; + } +@@ -465,27 +494,52 @@ static void flow_offload_ipv4_checksum(s + } + } + +-static void flow_offload_redirect(const struct flow_offload *flow, ++static void flow_offload_redirect(struct net *net, ++ const struct flow_offload *flow, + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) + { +- struct flow_action_entry *entry = flow_action_entry_next(flow_rule); +- struct rtable *rt; ++ const struct flow_offload_tuple *this_tuple, *other_tuple; ++ struct flow_action_entry *entry; ++ struct net_device *dev; ++ int ifindex; ++ ++ this_tuple = &flow->tuplehash[dir].tuple; ++ switch (this_tuple->xmit_type) { ++ case FLOW_OFFLOAD_XMIT_DIRECT: ++ this_tuple = &flow->tuplehash[dir].tuple; ++ ifindex = this_tuple->out.ifidx; ++ break; ++ case FLOW_OFFLOAD_XMIT_NEIGH: ++ other_tuple = &flow->tuplehash[!dir].tuple; ++ ifindex = other_tuple->iifidx; ++ break; ++ default: ++ return; ++ } + +- rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++ dev = dev_get_by_index(net, ifindex); ++ if (!dev) ++ return; ++ ++ entry = flow_action_entry_next(flow_rule); + entry->id = FLOW_ACTION_REDIRECT; +- entry->dev = rt->dst.dev; +- dev_hold(rt->dst.dev); ++ entry->dev = dev; + } + + static void flow_offload_encap_tunnel(const struct flow_offload *flow, + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) + { ++ const struct flow_offload_tuple *this_tuple; + struct flow_action_entry *entry; + struct dst_entry *dst; + +- dst = flow->tuplehash[dir].tuple.dst_cache; ++ this_tuple = &flow->tuplehash[dir].tuple; ++ if (this_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) ++ return; ++ ++ dst = this_tuple->dst_cache; + if (dst && dst->lwtstate) { + struct ip_tunnel_info *tun_info; + +@@ -502,10 +556,15 @@ static void flow_offload_decap_tunnel(co + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) + { ++ const struct flow_offload_tuple *other_tuple; + struct flow_action_entry *entry; + struct dst_entry *dst; + +- dst = flow->tuplehash[!dir].tuple.dst_cache; ++ other_tuple = &flow->tuplehash[!dir].tuple; ++ if (other_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) ++ return; ++ ++ dst = other_tuple->dst_cache; + if (dst && dst->lwtstate) { + struct ip_tunnel_info *tun_info; + +@@ -517,10 +576,14 @@ static void flow_offload_decap_tunnel(co + } + } + +-int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow, +- enum flow_offload_tuple_dir dir, +- struct nf_flow_rule *flow_rule) ++static int ++nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir, ++ struct nf_flow_rule *flow_rule) + { ++ const struct flow_offload_tuple *other_tuple; ++ int i; ++ + flow_offload_decap_tunnel(flow, dir, flow_rule); + flow_offload_encap_tunnel(flow, dir, flow_rule); + +@@ -528,6 +591,26 @@ int nf_flow_rule_route_ipv4(struct net * + flow_offload_eth_dst(net, flow, dir, flow_rule) < 0) + return -1; + ++ other_tuple = &flow->tuplehash[!dir].tuple; ++ ++ for (i = 0; i < other_tuple->encap_num; i++) { ++ struct flow_action_entry *entry = flow_action_entry_next(flow_rule); ++ ++ entry->id = FLOW_ACTION_VLAN_PUSH; ++ entry->vlan.vid = other_tuple->encap[i].id; ++ entry->vlan.proto = other_tuple->encap[i].proto; ++ } ++ ++ return 0; ++} ++ ++int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir, ++ struct nf_flow_rule *flow_rule) ++{ ++ if (nf_flow_rule_route_common(net, flow, dir, flow_rule) < 0) ++ return -1; ++ + if (test_bit(NF_FLOW_SNAT, &flow->flags)) { + flow_offload_ipv4_snat(net, flow, dir, flow_rule); + flow_offload_port_snat(net, flow, dir, flow_rule); +@@ -540,7 +623,7 @@ int nf_flow_rule_route_ipv4(struct net * + test_bit(NF_FLOW_DNAT, &flow->flags)) + flow_offload_ipv4_checksum(net, flow, flow_rule); + +- flow_offload_redirect(flow, dir, flow_rule); ++ flow_offload_redirect(net, flow, dir, flow_rule); + + return 0; + } +@@ -550,11 +633,7 @@ int nf_flow_rule_route_ipv6(struct net * + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) + { +- flow_offload_decap_tunnel(flow, dir, flow_rule); +- flow_offload_encap_tunnel(flow, dir, flow_rule); +- +- if (flow_offload_eth_src(net, flow, dir, flow_rule) < 0 || +- flow_offload_eth_dst(net, flow, dir, flow_rule) < 0) ++ if (nf_flow_rule_route_common(net, flow, dir, flow_rule) < 0) + return -1; + + if (test_bit(NF_FLOW_SNAT, &flow->flags)) { +@@ -566,7 +645,7 @@ int nf_flow_rule_route_ipv6(struct net * + flow_offload_port_dnat(net, flow, dir, flow_rule); + } + +- flow_offload_redirect(flow, dir, flow_rule); ++ flow_offload_redirect(net, flow, dir, flow_rule); + + return 0; + } +@@ -580,10 +659,10 @@ nf_flow_offload_rule_alloc(struct net *n + enum flow_offload_tuple_dir dir) + { + const struct nf_flowtable *flowtable = offload->flowtable; ++ const struct flow_offload_tuple *tuple, *other_tuple; + const struct flow_offload *flow = offload->flow; +- const struct flow_offload_tuple *tuple; ++ struct dst_entry *other_dst = NULL; + struct nf_flow_rule *flow_rule; +- struct dst_entry *other_dst; + int err = -ENOMEM; + + flow_rule = kzalloc(sizeof(*flow_rule), GFP_KERNEL); +@@ -599,7 +678,10 @@ nf_flow_offload_rule_alloc(struct net *n + flow_rule->rule->match.key = &flow_rule->match.key; + + tuple = &flow->tuplehash[dir].tuple; +- other_dst = flow->tuplehash[!dir].tuple.dst_cache; ++ other_tuple = &flow->tuplehash[!dir].tuple; ++ if (other_tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) ++ other_dst = other_tuple->dst_cache; ++ + err = nf_flow_rule_match(&flow_rule->match, tuple, other_dst); + if (err < 0) + goto err_flow_match; diff --git a/target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch b/target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch new file mode 100644 index 0000000000..56bb9fd56b --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch @@ -0,0 +1,114 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:47 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if + hardware offload is enabled + +If there is a forward path to reach an ethernet device and hardware +offload is enabled, then use the direct xmit path. + +Moreover, store the real device in the direct xmit path info since +software datapath uses dev_hard_header() to push the layer encapsulation +headers while hardware offload refers to the real device. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -131,6 +131,7 @@ struct flow_offload_tuple { + struct dst_entry *dst_cache; + struct { + u32 ifidx; ++ u32 hw_ifidx; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + } out; +@@ -187,6 +188,7 @@ struct nf_flow_route { + } in; + struct { + u32 ifindex; ++ u32 hw_ifindex; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + } out; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -106,6 +106,7 @@ static int flow_offload_fill_route(struc + memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source, + ETH_ALEN); + flow_tuple->out.ifidx = route->tuple[dir].out.ifindex; ++ flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex; + break; + case FLOW_OFFLOAD_XMIT_XFRM: + case FLOW_OFFLOAD_XMIT_NEIGH: +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -508,7 +508,7 @@ static void flow_offload_redirect(struct + switch (this_tuple->xmit_type) { + case FLOW_OFFLOAD_XMIT_DIRECT: + this_tuple = &flow->tuplehash[dir].tuple; +- ifindex = this_tuple->out.ifidx; ++ ifindex = this_tuple->out.hw_ifidx; + break; + case FLOW_OFFLOAD_XMIT_NEIGH: + other_tuple = &flow->tuplehash[!dir].tuple; +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -66,6 +66,7 @@ static int nft_dev_fill_forward_path(con + struct nft_forward_info { + const struct net_device *indev; + const struct net_device *outdev; ++ const struct net_device *hw_outdev; + struct id { + __u16 id; + __be16 proto; +@@ -76,9 +77,18 @@ struct nft_forward_info { + enum flow_offload_xmit_type xmit_type; + }; + ++static bool nft_is_valid_ether_device(const struct net_device *dev) ++{ ++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || ++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) ++ return false; ++ ++ return true; ++} ++ + static void nft_dev_path_info(const struct net_device_path_stack *stack, + struct nft_forward_info *info, +- unsigned char *ha) ++ unsigned char *ha, struct nf_flowtable *flowtable) + { + const struct net_device_path *path; + int i; +@@ -140,6 +150,12 @@ static void nft_dev_path_info(const stru + } + if (!info->outdev) + info->outdev = info->indev; ++ ++ info->hw_outdev = info->indev; ++ ++ if (nf_flowtable_hw_offload(flowtable) && ++ nft_is_valid_ether_device(info->indev)) ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; + } + + static bool nft_flowtable_find_dev(const struct net_device *dev, +@@ -171,7 +187,7 @@ static void nft_dev_forward_path(struct + int i; + + if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) +- nft_dev_path_info(&stack, &info, ha); ++ nft_dev_path_info(&stack, &info, ha, &ft->data); + + if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) + return; +@@ -187,6 +203,7 @@ static void nft_dev_forward_path(struct + memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); + memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); + route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; + route->tuple[dir].xmit_type = info.xmit_type; + } + } diff --git a/target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch b/target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch new file mode 100644 index 0000000000..7fa58ba844 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch @@ -0,0 +1,123 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:48 +0100 +Subject: [PATCH] netfilter: flowtable: bridge vlan hardware offload and + switchdev + +The switch might have already added the VLAN tag through PVID hardware +offload. Keep this extra VLAN in the flowtable but skip it on egress. + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -849,6 +849,7 @@ struct net_device_path { + DEV_PATH_BR_VLAN_KEEP, + DEV_PATH_BR_VLAN_TAG, + DEV_PATH_BR_VLAN_UNTAG, ++ DEV_PATH_BR_VLAN_UNTAG_HW, + } vlan_mode; + u16 vlan_id; + __be16 vlan_proto; +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -123,9 +123,10 @@ struct flow_offload_tuple { + /* All members above are keys for lookups, see flow_offload_hash(). */ + struct { } __hash; + +- u8 dir:4, ++ u8 dir:2, + xmit_type:2, +- encap_num:2; ++ encap_num:2, ++ in_vlan_ingress:2; + u16 mtu; + union { + struct dst_entry *dst_cache; +@@ -184,7 +185,8 @@ struct nf_flow_route { + u16 id; + __be16 proto; + } encap[NF_FLOW_TABLE_ENCAP_MAX]; +- u8 num_encaps; ++ u8 num_encaps:2, ++ ingress_vlans:2; + } in; + struct { + u32 ifindex; +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n + ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto; + ctx->num_vlans++; + break; ++ case DEV_PATH_BR_VLAN_UNTAG_HW: + case DEV_PATH_BR_VLAN_UNTAG: + ctx->num_vlans--; + break; +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc + + if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; ++ else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV) ++ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW; + else + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -95,6 +95,8 @@ static int flow_offload_fill_route(struc + for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) { + flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id; + flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto; ++ if (route->tuple[dir].in.ingress_vlans & BIT(i)) ++ flow_tuple->in_vlan_ingress |= BIT(j); + j++; + } + flow_tuple->encap_num = route->tuple[dir].in.num_encaps; +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -594,8 +594,12 @@ nf_flow_rule_route_common(struct net *ne + other_tuple = &flow->tuplehash[!dir].tuple; + + for (i = 0; i < other_tuple->encap_num; i++) { +- struct flow_action_entry *entry = flow_action_entry_next(flow_rule); ++ struct flow_action_entry *entry; + ++ if (other_tuple->in_vlan_ingress & BIT(i)) ++ continue; ++ ++ entry = flow_action_entry_next(flow_rule); + entry->id = FLOW_ACTION_VLAN_PUSH; + entry->vlan.vid = other_tuple->encap[i].id; + entry->vlan.proto = other_tuple->encap[i].proto; +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -72,6 +72,7 @@ struct nft_forward_info { + __be16 proto; + } encap[NF_FLOW_TABLE_ENCAP_MAX]; + u8 num_encaps; ++ u8 ingress_vlans; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + enum flow_offload_xmit_type xmit_type; +@@ -130,6 +131,9 @@ static void nft_dev_path_info(const stru + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + + switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ info->ingress_vlans |= BIT(info->num_encaps - 1); ++ break; + case DEV_PATH_BR_VLAN_TAG: + info->encap[info->num_encaps].id = path->bridge.vlan_id; + info->encap[info->num_encaps].proto = path->bridge.vlan_proto; +@@ -198,6 +202,7 @@ static void nft_dev_forward_path(struct + route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; + } + route->tuple[!dir].in.num_encaps = info.num_encaps; ++ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; + + if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { + memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); diff --git a/target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch b/target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch new file mode 100644 index 0000000000..64eae6871f --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch @@ -0,0 +1,30 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:49 +0100 +Subject: [PATCH] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH + +Add an action to represent the PPPoE hardware offload support that +includes the session ID. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/flow_offload.h ++++ b/include/net/flow_offload.h +@@ -147,6 +147,7 @@ enum flow_action_id { + FLOW_ACTION_MPLS_POP, + FLOW_ACTION_MPLS_MANGLE, + FLOW_ACTION_GATE, ++ FLOW_ACTION_PPPOE_PUSH, + NUM_FLOW_ACTIONS, + }; + +@@ -271,6 +272,9 @@ struct flow_action_entry { + u32 num_entries; + struct action_gate_entry *entries; + } gate; ++ struct { /* FLOW_ACTION_PPPOE_PUSH */ ++ u16 sid; ++ } pppoe; + }; + struct flow_action_cookie *cookie; /* user defined action cookie */ + }; diff --git a/target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch b/target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch new file mode 100644 index 0000000000..ed7346a61a --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch @@ -0,0 +1,35 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:50 +0100 +Subject: [PATCH] netfilter: flowtable: support for + FLOW_ACTION_PPPOE_PUSH + +Add a PPPoE push action if layer 2 protocol is ETH_P_PPP_SES to add +PPPoE flowtable hardware offload support. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -600,9 +600,18 @@ nf_flow_rule_route_common(struct net *ne + continue; + + entry = flow_action_entry_next(flow_rule); +- entry->id = FLOW_ACTION_VLAN_PUSH; +- entry->vlan.vid = other_tuple->encap[i].id; +- entry->vlan.proto = other_tuple->encap[i].proto; ++ ++ switch (other_tuple->encap[i].proto) { ++ case htons(ETH_P_PPP_SES): ++ entry->id = FLOW_ACTION_PPPOE_PUSH; ++ entry->pppoe.sid = other_tuple->encap[i].id; ++ break; ++ case htons(ETH_P_8021Q): ++ entry->id = FLOW_ACTION_VLAN_PUSH; ++ entry->vlan.vid = other_tuple->encap[i].id; ++ entry->vlan.proto = other_tuple->encap[i].proto; ++ break; ++ } + } + + return 0; diff --git a/target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch b/target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch new file mode 100644 index 0000000000..72675dc294 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch @@ -0,0 +1,53 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:51 +0100 +Subject: [PATCH] dsa: slave: add support for TC_SETUP_FT + +The dsa infrastructure provides a well-defined hierarchy of devices, +pass up the call to set up the flow block to the master device. From the +software dataplane, the netfilter infrastructure uses the dsa slave +devices to refer to the input and output device for the given skbuff. +Similarly, the flowtable definition in the ruleset refers to the dsa +slave port devices. + +This patch adds the glue code to call ndo_setup_tc with TC_SETUP_FT +with the master device via the dsa slave devices. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -1239,14 +1239,32 @@ static int dsa_slave_setup_tc_block(stru + } + } + ++static int dsa_slave_setup_ft_block(struct dsa_switch *ds, int port, ++ void *type_data) ++{ ++ struct dsa_port *cpu_dp = dsa_to_port(ds, port)->cpu_dp; ++ struct net_device *master = cpu_dp->master; ++ ++ if (!master->netdev_ops->ndo_setup_tc) ++ return -EOPNOTSUPP; ++ ++ return master->netdev_ops->ndo_setup_tc(master, TC_SETUP_FT, type_data); ++} ++ + static int dsa_slave_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data) + { + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + +- if (type == TC_SETUP_BLOCK) ++ switch (type) { ++ case TC_SETUP_BLOCK: + return dsa_slave_setup_tc_block(dev, type_data); ++ case TC_SETUP_FT: ++ return dsa_slave_setup_ft_block(ds, dp->index, type_data); ++ default: ++ break; ++ } + + if (!ds->ops->port_setup_tc) + return -EOPNOTSUPP; diff --git a/target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch b/target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch new file mode 100644 index 0000000000..b763984732 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch @@ -0,0 +1,68 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:52 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix parsing packets in GDM + +When using DSA, set the special tag in GDM ingress control to allow the MAC +to parse packets properly earlier. This affects rx DMA source port reporting. + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include "mtk_eth_soc.h" + +@@ -1285,13 +1286,12 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) || ++ (trxd.rxd4 & RX_DMA_SPECIAL_TAG)) + mac = 0; +- } else { +- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & +- RX_DMA_FPORT_MASK; +- mac--; +- } ++ else ++ mac = ((trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & ++ RX_DMA_FPORT_MASK) - 1; + + if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || + !eth->netdev[mac])) +@@ -2254,6 +2254,9 @@ static void mtk_gdm_config(struct mtk_et + + val |= config; + ++ if (!i && eth->netdev[0] && netdev_uses_dsa(eth->netdev[0])) ++ val |= MTK_GDMA_SPECIAL_TAG; ++ + mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); + } + /* Reset and enable PSE */ +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -81,6 +81,7 @@ + + /* GDM Exgress Control Register */ + #define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) ++#define MTK_GDMA_SPECIAL_TAG BIT(24) + #define MTK_GDMA_ICS_EN BIT(22) + #define MTK_GDMA_TCS_EN BIT(21) + #define MTK_GDMA_UCS_EN BIT(20) +@@ -318,6 +319,7 @@ + #define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */ + #define RX_DMA_FPORT_SHIFT 19 + #define RX_DMA_FPORT_MASK 0x7 ++#define RX_DMA_SPECIAL_TAG BIT(22) + + /* PHY Indirect Access Control registers */ + #define MTK_PHY_IAC 0x10004 diff --git a/target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch b/target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch new file mode 100644 index 0000000000..4fd6f8a36b --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch @@ -0,0 +1,1308 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:53 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for + initializing the PPE + +The PPE (packet processing engine) is used to offload NAT/routed or even +bridged flows. This patch brings up the PPE and uses it to get a packet +hash. It also contains some functionality that will be used to bring up +flow offloading. + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.h + create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_regs.h + +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -4,5 +4,5 @@ + # + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o +-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o ++mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o + obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2279,12 +2279,17 @@ static int mtk_open(struct net_device *d + + /* we run 2 netdevs on the same dma ring so we only bring it up once */ + if (!refcount_read(ð->dma_refcnt)) { +- int err = mtk_start_dma(eth); ++ u32 gdm_config = MTK_GDMA_TO_PDMA; ++ int err; + ++ err = mtk_start_dma(eth); + if (err) + return err; + +- mtk_gdm_config(eth, MTK_GDMA_TO_PDMA); ++ if (eth->soc->offload_version && mtk_ppe_start(ð->ppe) == 0) ++ gdm_config = MTK_GDMA_TO_PPE; ++ ++ mtk_gdm_config(eth, gdm_config); + + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); +@@ -2351,6 +2356,9 @@ static int mtk_stop(struct net_device *d + + mtk_dma_free(eth); + ++ if (eth->soc->offload_version) ++ mtk_ppe_stop(ð->ppe); ++ + return 0; + } + +@@ -3079,6 +3087,13 @@ static int mtk_probe(struct platform_dev + goto err_free_dev; + } + ++ if (eth->soc->offload_version) { ++ err = mtk_ppe_init(ð->ppe, eth->dev, ++ eth->base + MTK_ETH_PPE_BASE, 2); ++ if (err) ++ goto err_free_dev; ++ } ++ + for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) + continue; +@@ -3153,6 +3168,7 @@ static const struct mtk_soc_data mt7621_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7621_CLKS_BITMAP, + .required_pctl = false, ++ .offload_version = 2, + }; + + static const struct mtk_soc_data mt7622_data = { +@@ -3161,6 +3177,7 @@ static const struct mtk_soc_data mt7622_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7622_CLKS_BITMAP, + .required_pctl = false, ++ .offload_version = 2, + }; + + static const struct mtk_soc_data mt7623_data = { +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include "mtk_ppe.h" + + #define MTK_QDMA_PAGE_SIZE 2048 + #define MTK_MAX_RX_LENGTH 1536 +@@ -86,6 +87,7 @@ + #define MTK_GDMA_TCS_EN BIT(21) + #define MTK_GDMA_UCS_EN BIT(20) + #define MTK_GDMA_TO_PDMA 0x0 ++#define MTK_GDMA_TO_PPE 0x4444 + #define MTK_GDMA_DROP_ALL 0x7777 + + /* Unicast Filter MAC Address Register - Low */ +@@ -315,6 +317,12 @@ + #define RX_DMA_VID(_x) ((_x) & 0xfff) + + /* QDMA descriptor rxd4 */ ++#define MTK_RXD4_FOE_ENTRY GENMASK(13, 0) ++#define MTK_RXD4_PPE_CPU_REASON GENMASK(18, 14) ++#define MTK_RXD4_SRC_PORT GENMASK(21, 19) ++#define MTK_RXD4_ALG GENMASK(31, 22) ++ ++/* QDMA descriptor rxd4 */ + #define RX_DMA_L4_VALID BIT(24) + #define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */ + #define RX_DMA_FPORT_SHIFT 19 +@@ -819,6 +827,7 @@ struct mtk_soc_data { + u32 caps; + u32 required_clks; + bool required_pctl; ++ u8 offload_version; + netdev_features_t hw_features; + }; + +@@ -918,6 +927,8 @@ struct mtk_eth { + u32 tx_int_status_reg; + u32 rx_dma_l4_valid; + int ip_align; ++ ++ struct mtk_ppe ppe; + }; + + /* struct mtk_mac - the structure that holds the info about the MACs of the +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -0,0 +1,511 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mtk_ppe.h" ++#include "mtk_ppe_regs.h" ++ ++static void ppe_w32(struct mtk_ppe *ppe, u32 reg, u32 val) ++{ ++ writel(val, ppe->base + reg); ++} ++ ++static u32 ppe_r32(struct mtk_ppe *ppe, u32 reg) ++{ ++ return readl(ppe->base + reg); ++} ++ ++static u32 ppe_m32(struct mtk_ppe *ppe, u32 reg, u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = ppe_r32(ppe, reg); ++ val &= ~mask; ++ val |= set; ++ ppe_w32(ppe, reg, val); ++ ++ return val; ++} ++ ++static u32 ppe_set(struct mtk_ppe *ppe, u32 reg, u32 val) ++{ ++ return ppe_m32(ppe, reg, 0, val); ++} ++ ++static u32 ppe_clear(struct mtk_ppe *ppe, u32 reg, u32 val) ++{ ++ return ppe_m32(ppe, reg, val, 0); ++} ++ ++static int mtk_ppe_wait_busy(struct mtk_ppe *ppe) ++{ ++ unsigned long timeout = jiffies + HZ; ++ ++ while (time_is_before_jiffies(timeout)) { ++ if (!(ppe_r32(ppe, MTK_PPE_GLO_CFG) & MTK_PPE_GLO_CFG_BUSY)) ++ return 0; ++ ++ usleep_range(10, 20); ++ } ++ ++ dev_err(ppe->dev, "PPE table busy"); ++ ++ return -ETIMEDOUT; ++} ++ ++static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) ++{ ++ ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); ++ ppe_clear(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); ++} ++ ++static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable) ++{ ++ mtk_ppe_cache_clear(ppe); ++ ++ ppe_m32(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_EN, ++ enable * MTK_PPE_CACHE_CTL_EN); ++} ++ ++static u32 mtk_ppe_hash_entry(struct mtk_foe_entry *e) ++{ ++ u32 hv1, hv2, hv3; ++ u32 hash; ++ ++ switch (FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, e->ib1)) { ++ case MTK_PPE_PKT_TYPE_BRIDGE: ++ hv1 = e->bridge.src_mac_lo; ++ hv1 ^= ((e->bridge.src_mac_hi & 0xffff) << 16); ++ hv2 = e->bridge.src_mac_hi >> 16; ++ hv2 ^= e->bridge.dest_mac_lo; ++ hv3 = e->bridge.dest_mac_hi; ++ break; ++ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: ++ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: ++ hv1 = e->ipv4.orig.ports; ++ hv2 = e->ipv4.orig.dest_ip; ++ hv3 = e->ipv4.orig.src_ip; ++ break; ++ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T: ++ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T: ++ hv1 = e->ipv6.src_ip[3] ^ e->ipv6.dest_ip[3]; ++ hv1 ^= e->ipv6.ports; ++ ++ hv2 = e->ipv6.src_ip[2] ^ e->ipv6.dest_ip[2]; ++ hv2 ^= e->ipv6.dest_ip[0]; ++ ++ hv3 = e->ipv6.src_ip[1] ^ e->ipv6.dest_ip[1]; ++ hv3 ^= e->ipv6.src_ip[0]; ++ break; ++ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: ++ case MTK_PPE_PKT_TYPE_IPV6_6RD: ++ default: ++ WARN_ON_ONCE(1); ++ return MTK_PPE_HASH_MASK; ++ } ++ ++ hash = (hv1 & hv2) | ((~hv1) & hv3); ++ hash = (hash >> 24) | ((hash & 0xffffff) << 8); ++ hash ^= hv1 ^ hv2 ^ hv3; ++ hash ^= hash >> 16; ++ hash <<= 1; ++ hash &= MTK_PPE_ENTRIES - 1; ++ ++ return hash; ++} ++ ++static inline struct mtk_foe_mac_info * ++mtk_foe_entry_l2(struct mtk_foe_entry *entry) ++{ ++ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ ++ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) ++ return &entry->ipv6.l2; ++ ++ return &entry->ipv4.l2; ++} ++ ++static inline u32 * ++mtk_foe_entry_ib2(struct mtk_foe_entry *entry) ++{ ++ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ ++ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) ++ return &entry->ipv6.ib2; ++ ++ return &entry->ipv4.ib2; ++} ++ ++int mtk_foe_entry_prepare(struct mtk_foe_entry *entry, int type, int l4proto, ++ u8 pse_port, u8 *src_mac, u8 *dest_mac) ++{ ++ struct mtk_foe_mac_info *l2; ++ u32 ports_pad, val; ++ ++ memset(entry, 0, sizeof(*entry)); ++ ++ val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | ++ FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) | ++ FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | ++ MTK_FOE_IB1_BIND_TTL | ++ MTK_FOE_IB1_BIND_CACHE; ++ entry->ib1 = val; ++ ++ val = FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) | ++ FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f) | ++ FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port); ++ ++ if (is_multicast_ether_addr(dest_mac)) ++ val |= MTK_FOE_IB2_MULTICAST; ++ ++ ports_pad = 0xa5a5a500 | (l4proto & 0xff); ++ if (type == MTK_PPE_PKT_TYPE_IPV4_ROUTE) ++ entry->ipv4.orig.ports = ports_pad; ++ if (type == MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T) ++ entry->ipv6.ports = ports_pad; ++ ++ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { ++ entry->ipv6.ib2 = val; ++ l2 = &entry->ipv6.l2; ++ } else { ++ entry->ipv4.ib2 = val; ++ l2 = &entry->ipv4.l2; ++ } ++ ++ l2->dest_mac_hi = get_unaligned_be32(dest_mac); ++ l2->dest_mac_lo = get_unaligned_be16(dest_mac + 4); ++ l2->src_mac_hi = get_unaligned_be32(src_mac); ++ l2->src_mac_lo = get_unaligned_be16(src_mac + 4); ++ ++ if (type >= MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T) ++ l2->etype = ETH_P_IPV6; ++ else ++ l2->etype = ETH_P_IP; ++ ++ return 0; ++} ++ ++int mtk_foe_entry_set_pse_port(struct mtk_foe_entry *entry, u8 port) ++{ ++ u32 *ib2 = mtk_foe_entry_ib2(entry); ++ u32 val; ++ ++ val = *ib2; ++ val &= ~MTK_FOE_IB2_DEST_PORT; ++ val |= FIELD_PREP(MTK_FOE_IB2_DEST_PORT, port); ++ *ib2 = val; ++ ++ return 0; ++} ++ ++int mtk_foe_entry_set_ipv4_tuple(struct mtk_foe_entry *entry, bool egress, ++ __be32 src_addr, __be16 src_port, ++ __be32 dest_addr, __be16 dest_port) ++{ ++ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ struct mtk_ipv4_tuple *t; ++ ++ switch (type) { ++ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: ++ if (egress) { ++ t = &entry->ipv4.new; ++ break; ++ } ++ fallthrough; ++ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: ++ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: ++ t = &entry->ipv4.orig; ++ break; ++ case MTK_PPE_PKT_TYPE_IPV6_6RD: ++ entry->ipv6_6rd.tunnel_src_ip = be32_to_cpu(src_addr); ++ entry->ipv6_6rd.tunnel_dest_ip = be32_to_cpu(dest_addr); ++ return 0; ++ default: ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } ++ ++ t->src_ip = be32_to_cpu(src_addr); ++ t->dest_ip = be32_to_cpu(dest_addr); ++ ++ if (type == MTK_PPE_PKT_TYPE_IPV4_ROUTE) ++ return 0; ++ ++ t->src_port = be16_to_cpu(src_port); ++ t->dest_port = be16_to_cpu(dest_port); ++ ++ return 0; ++} ++ ++int mtk_foe_entry_set_ipv6_tuple(struct mtk_foe_entry *entry, ++ __be32 *src_addr, __be16 src_port, ++ __be32 *dest_addr, __be16 dest_port) ++{ ++ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ u32 *src, *dest; ++ int i; ++ ++ switch (type) { ++ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: ++ src = entry->dslite.tunnel_src_ip; ++ dest = entry->dslite.tunnel_dest_ip; ++ break; ++ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T: ++ case MTK_PPE_PKT_TYPE_IPV6_6RD: ++ entry->ipv6.src_port = be16_to_cpu(src_port); ++ entry->ipv6.dest_port = be16_to_cpu(dest_port); ++ fallthrough; ++ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T: ++ src = entry->ipv6.src_ip; ++ dest = entry->ipv6.dest_ip; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ }; ++ ++ for (i = 0; i < 4; i++) ++ src[i] = be32_to_cpu(src_addr[i]); ++ for (i = 0; i < 4; i++) ++ dest[i] = be32_to_cpu(dest_addr[i]); ++ ++ return 0; ++} ++ ++int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port) ++{ ++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); ++ ++ l2->etype = BIT(port); ++ ++ if (!(entry->ib1 & MTK_FOE_IB1_BIND_VLAN_LAYER)) ++ entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, 1); ++ else ++ l2->etype |= BIT(8); ++ ++ entry->ib1 &= ~MTK_FOE_IB1_BIND_VLAN_TAG; ++ ++ return 0; ++} ++ ++int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid) ++{ ++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); ++ ++ switch (FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, entry->ib1)) { ++ case 0: ++ entry->ib1 |= MTK_FOE_IB1_BIND_VLAN_TAG | ++ FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, 1); ++ l2->vlan1 = vid; ++ return 0; ++ case 1: ++ if (!(entry->ib1 & MTK_FOE_IB1_BIND_VLAN_TAG)) { ++ l2->vlan1 = vid; ++ l2->etype |= BIT(8); ++ } else { ++ l2->vlan2 = vid; ++ entry->ib1 += FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, 1); ++ } ++ return 0; ++ default: ++ return -ENOSPC; ++ } ++} ++ ++int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid) ++{ ++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); ++ ++ if (!(entry->ib1 & MTK_FOE_IB1_BIND_VLAN_LAYER) || ++ (entry->ib1 & MTK_FOE_IB1_BIND_VLAN_TAG)) ++ l2->etype = ETH_P_PPP_SES; ++ ++ entry->ib1 |= MTK_FOE_IB1_BIND_PPPOE; ++ l2->pppoe_id = sid; ++ ++ return 0; ++} ++ ++static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry) ++{ ++ return !(entry->ib1 & MTK_FOE_IB1_STATIC) && ++ FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1) != MTK_FOE_STATE_BIND; ++} ++ ++int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, ++ u16 timestamp) ++{ ++ struct mtk_foe_entry *hwe; ++ u32 hash; ++ ++ timestamp &= MTK_FOE_IB1_BIND_TIMESTAMP; ++ entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP; ++ entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP, timestamp); ++ ++ hash = mtk_ppe_hash_entry(entry); ++ hwe = &ppe->foe_table[hash]; ++ if (!mtk_foe_entry_usable(hwe)) { ++ hwe++; ++ hash++; ++ ++ if (!mtk_foe_entry_usable(hwe)) ++ return -ENOSPC; ++ } ++ ++ memcpy(&hwe->data, &entry->data, sizeof(hwe->data)); ++ wmb(); ++ hwe->ib1 = entry->ib1; ++ ++ dma_wmb(); ++ ++ mtk_ppe_cache_clear(ppe); ++ ++ return hash; ++} ++ ++int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, ++ int version) ++{ ++ struct mtk_foe_entry *foe; ++ ++ /* need to allocate a separate device, since it PPE DMA access is ++ * not coherent. ++ */ ++ ppe->base = base; ++ ppe->dev = dev; ++ ppe->version = version; ++ ++ foe = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*foe), ++ &ppe->foe_phys, GFP_KERNEL); ++ if (!foe) ++ return -ENOMEM; ++ ++ ppe->foe_table = foe; ++ ++ mtk_ppe_debugfs_init(ppe); ++ ++ return 0; ++} ++ ++static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) ++{ ++ static const u8 skip[] = { 12, 25, 38, 51, 76, 89, 102 }; ++ int i, k; ++ ++ memset(ppe->foe_table, 0, MTK_PPE_ENTRIES * sizeof(ppe->foe_table)); ++ ++ if (!IS_ENABLED(CONFIG_SOC_MT7621)) ++ return; ++ ++ /* skip all entries that cross the 1024 byte boundary */ ++ for (i = 0; i < MTK_PPE_ENTRIES; i += 128) ++ for (k = 0; k < ARRAY_SIZE(skip); k++) ++ ppe->foe_table[i + skip[k]].ib1 |= MTK_FOE_IB1_STATIC; ++} ++ ++int mtk_ppe_start(struct mtk_ppe *ppe) ++{ ++ u32 val; ++ ++ mtk_ppe_init_foe_table(ppe); ++ ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); ++ ++ val = MTK_PPE_TB_CFG_ENTRY_80B | ++ MTK_PPE_TB_CFG_AGE_NON_L4 | ++ MTK_PPE_TB_CFG_AGE_UNBIND | ++ MTK_PPE_TB_CFG_AGE_TCP | ++ MTK_PPE_TB_CFG_AGE_UDP | ++ MTK_PPE_TB_CFG_AGE_TCP_FIN | ++ FIELD_PREP(MTK_PPE_TB_CFG_SEARCH_MISS, ++ MTK_PPE_SEARCH_MISS_ACTION_FORWARD_BUILD) | ++ FIELD_PREP(MTK_PPE_TB_CFG_KEEPALIVE, ++ MTK_PPE_KEEPALIVE_DISABLE) | ++ FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) | ++ FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE, ++ MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | ++ FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, ++ MTK_PPE_ENTRIES_SHIFT); ++ ppe_w32(ppe, MTK_PPE_TB_CFG, val); ++ ++ ppe_w32(ppe, MTK_PPE_IP_PROTO_CHK, ++ MTK_PPE_IP_PROTO_CHK_IPV4 | MTK_PPE_IP_PROTO_CHK_IPV6); ++ ++ mtk_ppe_cache_enable(ppe, true); ++ ++ val = MTK_PPE_FLOW_CFG_IP4_TCP_FRAG | ++ MTK_PPE_FLOW_CFG_IP4_UDP_FRAG | ++ MTK_PPE_FLOW_CFG_IP6_3T_ROUTE | ++ MTK_PPE_FLOW_CFG_IP6_5T_ROUTE | ++ MTK_PPE_FLOW_CFG_IP6_6RD | ++ MTK_PPE_FLOW_CFG_IP4_NAT | ++ MTK_PPE_FLOW_CFG_IP4_NAPT | ++ MTK_PPE_FLOW_CFG_IP4_DSLITE | ++ MTK_PPE_FLOW_CFG_L2_BRIDGE | ++ MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; ++ ppe_w32(ppe, MTK_PPE_FLOW_CFG, val); ++ ++ val = FIELD_PREP(MTK_PPE_UNBIND_AGE_MIN_PACKETS, 1000) | ++ FIELD_PREP(MTK_PPE_UNBIND_AGE_DELTA, 3); ++ ppe_w32(ppe, MTK_PPE_UNBIND_AGE, val); ++ ++ val = FIELD_PREP(MTK_PPE_BIND_AGE0_DELTA_UDP, 12) | ++ FIELD_PREP(MTK_PPE_BIND_AGE0_DELTA_NON_L4, 1); ++ ppe_w32(ppe, MTK_PPE_BIND_AGE0, val); ++ ++ val = FIELD_PREP(MTK_PPE_BIND_AGE1_DELTA_TCP_FIN, 1) | ++ FIELD_PREP(MTK_PPE_BIND_AGE1_DELTA_TCP, 7); ++ ppe_w32(ppe, MTK_PPE_BIND_AGE1, val); ++ ++ val = MTK_PPE_BIND_LIMIT0_QUARTER | MTK_PPE_BIND_LIMIT0_HALF; ++ ppe_w32(ppe, MTK_PPE_BIND_LIMIT0, val); ++ ++ val = MTK_PPE_BIND_LIMIT1_FULL | ++ FIELD_PREP(MTK_PPE_BIND_LIMIT1_NON_L4, 1); ++ ppe_w32(ppe, MTK_PPE_BIND_LIMIT1, val); ++ ++ val = FIELD_PREP(MTK_PPE_BIND_RATE_BIND, 30) | ++ FIELD_PREP(MTK_PPE_BIND_RATE_PREBIND, 1); ++ ppe_w32(ppe, MTK_PPE_BIND_RATE, val); ++ ++ /* enable PPE */ ++ val = MTK_PPE_GLO_CFG_EN | ++ MTK_PPE_GLO_CFG_IP4_L4_CS_DROP | ++ MTK_PPE_GLO_CFG_IP4_CS_DROP | ++ MTK_PPE_GLO_CFG_FLOW_DROP_UPDATE; ++ ppe_w32(ppe, MTK_PPE_GLO_CFG, val); ++ ++ ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); ++ ++ return 0; ++} ++ ++int mtk_ppe_stop(struct mtk_ppe *ppe) ++{ ++ u32 val; ++ int i; ++ ++ for (i = 0; i < MTK_PPE_ENTRIES; i++) ++ ppe->foe_table[i].ib1 = FIELD_PREP(MTK_FOE_IB1_STATE, ++ MTK_FOE_STATE_INVALID); ++ ++ mtk_ppe_cache_enable(ppe, false); ++ ++ /* disable offload engine */ ++ ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); ++ ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); ++ ++ /* disable aging */ ++ val = MTK_PPE_TB_CFG_AGE_NON_L4 | ++ MTK_PPE_TB_CFG_AGE_UNBIND | ++ MTK_PPE_TB_CFG_AGE_TCP | ++ MTK_PPE_TB_CFG_AGE_UDP | ++ MTK_PPE_TB_CFG_AGE_TCP_FIN; ++ ppe_clear(ppe, MTK_PPE_TB_CFG, val); ++ ++ return mtk_ppe_wait_busy(ppe); ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -0,0 +1,287 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#ifndef __MTK_PPE_H ++#define __MTK_PPE_H ++ ++#include ++#include ++ ++#define MTK_ETH_PPE_BASE 0xc00 ++ ++#define MTK_PPE_ENTRIES_SHIFT 3 ++#define MTK_PPE_ENTRIES (1024 << MTK_PPE_ENTRIES_SHIFT) ++#define MTK_PPE_HASH_MASK (MTK_PPE_ENTRIES - 1) ++ ++#define MTK_FOE_IB1_UNBIND_TIMESTAMP GENMASK(7, 0) ++#define MTK_FOE_IB1_UNBIND_PACKETS GENMASK(23, 8) ++#define MTK_FOE_IB1_UNBIND_PREBIND BIT(24) ++ ++#define MTK_FOE_IB1_BIND_TIMESTAMP GENMASK(14, 0) ++#define MTK_FOE_IB1_BIND_KEEPALIVE BIT(15) ++#define MTK_FOE_IB1_BIND_VLAN_LAYER GENMASK(18, 16) ++#define MTK_FOE_IB1_BIND_PPPOE BIT(19) ++#define MTK_FOE_IB1_BIND_VLAN_TAG BIT(20) ++#define MTK_FOE_IB1_BIND_PKT_SAMPLE BIT(21) ++#define MTK_FOE_IB1_BIND_CACHE BIT(22) ++#define MTK_FOE_IB1_BIND_TUNNEL_DECAP BIT(23) ++#define MTK_FOE_IB1_BIND_TTL BIT(24) ++ ++#define MTK_FOE_IB1_PACKET_TYPE GENMASK(27, 25) ++#define MTK_FOE_IB1_STATE GENMASK(29, 28) ++#define MTK_FOE_IB1_UDP BIT(30) ++#define MTK_FOE_IB1_STATIC BIT(31) ++ ++enum { ++ MTK_PPE_PKT_TYPE_IPV4_HNAPT = 0, ++ MTK_PPE_PKT_TYPE_IPV4_ROUTE = 1, ++ MTK_PPE_PKT_TYPE_BRIDGE = 2, ++ MTK_PPE_PKT_TYPE_IPV4_DSLITE = 3, ++ MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T = 4, ++ MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T = 5, ++ MTK_PPE_PKT_TYPE_IPV6_6RD = 7, ++}; ++ ++#define MTK_FOE_IB2_QID GENMASK(3, 0) ++#define MTK_FOE_IB2_PSE_QOS BIT(4) ++#define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) ++#define MTK_FOE_IB2_MULTICAST BIT(8) ++ ++#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12) ++#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16) ++#define MTK_FOE_IB2_WHNAT_NAT BIT(17) ++ ++#define MTK_FOE_IB2_PORT_MG GENMASK(17, 12) ++ ++#define MTK_FOE_IB2_PORT_AG GENMASK(23, 18) ++ ++#define MTK_FOE_IB2_DSCP GENMASK(31, 24) ++ ++#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0) ++#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6) ++#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14) ++ ++enum { ++ MTK_FOE_STATE_INVALID, ++ MTK_FOE_STATE_UNBIND, ++ MTK_FOE_STATE_BIND, ++ MTK_FOE_STATE_FIN ++}; ++ ++struct mtk_foe_mac_info { ++ u16 vlan1; ++ u16 etype; ++ ++ u32 dest_mac_hi; ++ ++ u16 vlan2; ++ u16 dest_mac_lo; ++ ++ u32 src_mac_hi; ++ ++ u16 pppoe_id; ++ u16 src_mac_lo; ++}; ++ ++struct mtk_foe_bridge { ++ u32 dest_mac_hi; ++ ++ u16 src_mac_lo; ++ u16 dest_mac_lo; ++ ++ u32 src_mac_hi; ++ ++ u32 ib2; ++ ++ u32 _rsv[5]; ++ ++ u32 udf_tsid; ++ struct mtk_foe_mac_info l2; ++}; ++ ++struct mtk_ipv4_tuple { ++ u32 src_ip; ++ u32 dest_ip; ++ union { ++ struct { ++ u16 dest_port; ++ u16 src_port; ++ }; ++ struct { ++ u8 protocol; ++ u8 _pad[3]; /* fill with 0xa5a5a5 */ ++ }; ++ u32 ports; ++ }; ++}; ++ ++struct mtk_foe_ipv4 { ++ struct mtk_ipv4_tuple orig; ++ ++ u32 ib2; ++ ++ struct mtk_ipv4_tuple new; ++ ++ u16 timestamp; ++ u16 _rsv0[3]; ++ ++ u32 udf_tsid; ++ ++ struct mtk_foe_mac_info l2; ++}; ++ ++struct mtk_foe_ipv4_dslite { ++ struct mtk_ipv4_tuple ip4; ++ ++ u32 tunnel_src_ip[4]; ++ u32 tunnel_dest_ip[4]; ++ ++ u8 flow_label[3]; ++ u8 priority; ++ ++ u32 udf_tsid; ++ ++ u32 ib2; ++ ++ struct mtk_foe_mac_info l2; ++}; ++ ++struct mtk_foe_ipv6 { ++ u32 src_ip[4]; ++ u32 dest_ip[4]; ++ ++ union { ++ struct { ++ u8 protocol; ++ u8 _pad[3]; /* fill with 0xa5a5a5 */ ++ }; /* 3-tuple */ ++ struct { ++ u16 dest_port; ++ u16 src_port; ++ }; /* 5-tuple */ ++ u32 ports; ++ }; ++ ++ u32 _rsv[3]; ++ ++ u32 udf; ++ ++ u32 ib2; ++ struct mtk_foe_mac_info l2; ++}; ++ ++struct mtk_foe_ipv6_6rd { ++ u32 src_ip[4]; ++ u32 dest_ip[4]; ++ u16 dest_port; ++ u16 src_port; ++ ++ u32 tunnel_src_ip; ++ u32 tunnel_dest_ip; ++ ++ u16 hdr_csum; ++ u8 dscp; ++ u8 ttl; ++ ++ u8 flag; ++ u8 pad; ++ u8 per_flow_6rd_id; ++ u8 pad2; ++ ++ u32 ib2; ++ struct mtk_foe_mac_info l2; ++}; ++ ++struct mtk_foe_entry { ++ u32 ib1; ++ ++ union { ++ struct mtk_foe_bridge bridge; ++ struct mtk_foe_ipv4 ipv4; ++ struct mtk_foe_ipv4_dslite dslite; ++ struct mtk_foe_ipv6 ipv6; ++ struct mtk_foe_ipv6_6rd ipv6_6rd; ++ u32 data[19]; ++ }; ++}; ++ ++enum { ++ MTK_PPE_CPU_REASON_TTL_EXCEEDED = 0x02, ++ MTK_PPE_CPU_REASON_OPTION_HEADER = 0x03, ++ MTK_PPE_CPU_REASON_NO_FLOW = 0x07, ++ MTK_PPE_CPU_REASON_IPV4_FRAG = 0x08, ++ MTK_PPE_CPU_REASON_IPV4_DSLITE_FRAG = 0x09, ++ MTK_PPE_CPU_REASON_IPV4_DSLITE_NO_TCP_UDP = 0x0a, ++ MTK_PPE_CPU_REASON_IPV6_6RD_NO_TCP_UDP = 0x0b, ++ MTK_PPE_CPU_REASON_TCP_FIN_SYN_RST = 0x0c, ++ MTK_PPE_CPU_REASON_UN_HIT = 0x0d, ++ MTK_PPE_CPU_REASON_HIT_UNBIND = 0x0e, ++ MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, ++ MTK_PPE_CPU_REASON_HIT_BIND_TCP_FIN = 0x10, ++ MTK_PPE_CPU_REASON_HIT_TTL_1 = 0x11, ++ MTK_PPE_CPU_REASON_HIT_BIND_VLAN_VIOLATION = 0x12, ++ MTK_PPE_CPU_REASON_KEEPALIVE_UC_OLD_HDR = 0x13, ++ MTK_PPE_CPU_REASON_KEEPALIVE_MC_NEW_HDR = 0x14, ++ MTK_PPE_CPU_REASON_KEEPALIVE_DUP_OLD_HDR = 0x15, ++ MTK_PPE_CPU_REASON_HIT_BIND_FORCE_CPU = 0x16, ++ MTK_PPE_CPU_REASON_TUNNEL_OPTION_HEADER = 0x17, ++ MTK_PPE_CPU_REASON_MULTICAST_TO_CPU = 0x18, ++ MTK_PPE_CPU_REASON_MULTICAST_TO_GMAC1_CPU = 0x19, ++ MTK_PPE_CPU_REASON_HIT_PRE_BIND = 0x1a, ++ MTK_PPE_CPU_REASON_PACKET_SAMPLING = 0x1b, ++ MTK_PPE_CPU_REASON_EXCEED_MTU = 0x1c, ++ MTK_PPE_CPU_REASON_PPE_BYPASS = 0x1e, ++ MTK_PPE_CPU_REASON_INVALID = 0x1f, ++}; ++ ++struct mtk_ppe { ++ struct device *dev; ++ void __iomem *base; ++ int version; ++ ++ struct mtk_foe_entry *foe_table; ++ dma_addr_t foe_phys; ++ ++ void *acct_table; ++}; ++ ++int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, ++ int version); ++int mtk_ppe_start(struct mtk_ppe *ppe); ++int mtk_ppe_stop(struct mtk_ppe *ppe); ++ ++static inline void ++mtk_foe_entry_clear(struct mtk_ppe *ppe, u16 hash) ++{ ++ ppe->foe_table[hash].ib1 = 0; ++ dma_wmb(); ++} ++ ++static inline int ++mtk_foe_entry_timestamp(struct mtk_ppe *ppe, u16 hash) ++{ ++ u32 ib1 = READ_ONCE(ppe->foe_table[hash].ib1); ++ ++ if (FIELD_GET(MTK_FOE_IB1_STATE, ib1) != MTK_FOE_STATE_BIND) ++ return -1; ++ ++ return FIELD_GET(MTK_FOE_IB1_BIND_TIMESTAMP, ib1); ++} ++ ++int mtk_foe_entry_prepare(struct mtk_foe_entry *entry, int type, int l4proto, ++ u8 pse_port, u8 *src_mac, u8 *dest_mac); ++int mtk_foe_entry_set_pse_port(struct mtk_foe_entry *entry, u8 port); ++int mtk_foe_entry_set_ipv4_tuple(struct mtk_foe_entry *entry, bool orig, ++ __be32 src_addr, __be16 src_port, ++ __be32 dest_addr, __be16 dest_port); ++int mtk_foe_entry_set_ipv6_tuple(struct mtk_foe_entry *entry, ++ __be32 *src_addr, __be16 src_port, ++ __be32 *dest_addr, __be16 dest_port); ++int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port); ++int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); ++int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); ++int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, ++ u16 timestamp); ++int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); ++ ++#endif +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +@@ -0,0 +1,217 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#include ++#include ++#include "mtk_eth_soc.h" ++ ++struct mtk_flow_addr_info ++{ ++ void *src, *dest; ++ u16 *src_port, *dest_port; ++ bool ipv6; ++}; ++ ++static const char *mtk_foe_entry_state_str(int state) ++{ ++ static const char * const state_str[] = { ++ [MTK_FOE_STATE_INVALID] = "INV", ++ [MTK_FOE_STATE_UNBIND] = "UNB", ++ [MTK_FOE_STATE_BIND] = "BND", ++ [MTK_FOE_STATE_FIN] = "FIN", ++ }; ++ ++ if (state >= ARRAY_SIZE(state_str) || !state_str[state]) ++ return "UNK"; ++ ++ return state_str[state]; ++} ++ ++static const char *mtk_foe_pkt_type_str(int type) ++{ ++ static const char * const type_str[] = { ++ [MTK_PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T", ++ [MTK_PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T", ++ [MTK_PPE_PKT_TYPE_BRIDGE] = "L2", ++ [MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE", ++ [MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T", ++ [MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T", ++ [MTK_PPE_PKT_TYPE_IPV6_6RD] = "6RD", ++ }; ++ ++ if (type >= ARRAY_SIZE(type_str) || !type_str[type]) ++ return "UNKNOWN"; ++ ++ return type_str[type]; ++} ++ ++static void ++mtk_print_addr(struct seq_file *m, u32 *addr, bool ipv6) ++{ ++ u32 n_addr[4]; ++ int i; ++ ++ if (!ipv6) { ++ seq_printf(m, "%pI4h", addr); ++ return; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(n_addr); i++) ++ n_addr[i] = htonl(addr[i]); ++ seq_printf(m, "%pI6", n_addr); ++} ++ ++static void ++mtk_print_addr_info(struct seq_file *m, struct mtk_flow_addr_info *ai) ++{ ++ mtk_print_addr(m, ai->src, ai->ipv6); ++ if (ai->src_port) ++ seq_printf(m, ":%d", *ai->src_port); ++ seq_printf(m, "->"); ++ mtk_print_addr(m, ai->dest, ai->ipv6); ++ if (ai->dest_port) ++ seq_printf(m, ":%d", *ai->dest_port); ++} ++ ++static int ++mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind) ++{ ++ struct mtk_ppe *ppe = m->private; ++ int i, count; ++ ++ for (i = 0, count = 0; i < MTK_PPE_ENTRIES; i++) { ++ struct mtk_foe_entry *entry = &ppe->foe_table[i]; ++ struct mtk_foe_mac_info *l2; ++ struct mtk_flow_addr_info ai = {}; ++ unsigned char h_source[ETH_ALEN]; ++ unsigned char h_dest[ETH_ALEN]; ++ int type, state; ++ u32 ib2; ++ ++ ++ state = FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1); ++ if (!state) ++ continue; ++ ++ if (bind && state != MTK_FOE_STATE_BIND) ++ continue; ++ ++ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); ++ seq_printf(m, "%05x %s %7s", i, ++ mtk_foe_entry_state_str(state), ++ mtk_foe_pkt_type_str(type)); ++ ++ switch (type) { ++ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: ++ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: ++ ai.src_port = &entry->ipv4.orig.src_port; ++ ai.dest_port = &entry->ipv4.orig.dest_port; ++ fallthrough; ++ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: ++ ai.src = &entry->ipv4.orig.src_ip; ++ ai.dest = &entry->ipv4.orig.dest_ip; ++ break; ++ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T: ++ ai.src_port = &entry->ipv6.src_port; ++ ai.dest_port = &entry->ipv6.dest_port; ++ fallthrough; ++ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T: ++ case MTK_PPE_PKT_TYPE_IPV6_6RD: ++ ai.src = &entry->ipv6.src_ip; ++ ai.dest = &entry->ipv6.dest_ip; ++ ai.ipv6 = true; ++ break; ++ } ++ ++ seq_printf(m, " orig="); ++ mtk_print_addr_info(m, &ai); ++ ++ switch (type) { ++ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: ++ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: ++ ai.src_port = &entry->ipv4.new.src_port; ++ ai.dest_port = &entry->ipv4.new.dest_port; ++ fallthrough; ++ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: ++ ai.src = &entry->ipv4.new.src_ip; ++ ai.dest = &entry->ipv4.new.dest_ip; ++ seq_printf(m, " new="); ++ mtk_print_addr_info(m, &ai); ++ break; ++ } ++ ++ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { ++ l2 = &entry->ipv6.l2; ++ ib2 = entry->ipv6.ib2; ++ } else { ++ l2 = &entry->ipv4.l2; ++ ib2 = entry->ipv4.ib2; ++ } ++ ++ *((__be32 *)h_source) = htonl(l2->src_mac_hi); ++ *((__be16 *)&h_source[4]) = htons(l2->src_mac_lo); ++ *((__be32 *)h_dest) = htonl(l2->dest_mac_hi); ++ *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); ++ ++ seq_printf(m, " eth=%pM->%pM etype=%04x" ++ " vlan=%d,%d ib1=%08x ib2=%08x\n", ++ h_source, h_dest, ntohs(l2->etype), ++ l2->vlan1, l2->vlan2, entry->ib1, ib2); ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_ppe_debugfs_foe_show_all(struct seq_file *m, void *private) ++{ ++ return mtk_ppe_debugfs_foe_show(m, private, false); ++} ++ ++static int ++mtk_ppe_debugfs_foe_show_bind(struct seq_file *m, void *private) ++{ ++ return mtk_ppe_debugfs_foe_show(m, private, true); ++} ++ ++static int ++mtk_ppe_debugfs_foe_open_all(struct inode *inode, struct file *file) ++{ ++ return single_open(file, mtk_ppe_debugfs_foe_show_all, ++ inode->i_private); ++} ++ ++static int ++mtk_ppe_debugfs_foe_open_bind(struct inode *inode, struct file *file) ++{ ++ return single_open(file, mtk_ppe_debugfs_foe_show_bind, ++ inode->i_private); ++} ++ ++int mtk_ppe_debugfs_init(struct mtk_ppe *ppe) ++{ ++ static const struct file_operations fops_all = { ++ .open = mtk_ppe_debugfs_foe_open_all, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ }; ++ ++ static const struct file_operations fops_bind = { ++ .open = mtk_ppe_debugfs_foe_open_bind, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ }; ++ ++ struct dentry *root; ++ ++ root = debugfs_create_dir("mtk_ppe", NULL); ++ if (!root) ++ return -ENOMEM; ++ ++ debugfs_create_file("entries", S_IRUGO, root, ppe, &fops_all); ++ debugfs_create_file("bind", S_IRUGO, root, ppe, &fops_bind); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h +@@ -0,0 +1,144 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#ifndef __MTK_PPE_REGS_H ++#define __MTK_PPE_REGS_H ++ ++#define MTK_PPE_GLO_CFG 0x200 ++#define MTK_PPE_GLO_CFG_EN BIT(0) ++#define MTK_PPE_GLO_CFG_TSID_EN BIT(1) ++#define MTK_PPE_GLO_CFG_IP4_L4_CS_DROP BIT(2) ++#define MTK_PPE_GLO_CFG_IP4_CS_DROP BIT(3) ++#define MTK_PPE_GLO_CFG_TTL0_DROP BIT(4) ++#define MTK_PPE_GLO_CFG_PPE_BSWAP BIT(5) ++#define MTK_PPE_GLO_CFG_PSE_HASH_OFS BIT(6) ++#define MTK_PPE_GLO_CFG_MCAST_TB_EN BIT(7) ++#define MTK_PPE_GLO_CFG_FLOW_DROP_KA BIT(8) ++#define MTK_PPE_GLO_CFG_FLOW_DROP_UPDATE BIT(9) ++#define MTK_PPE_GLO_CFG_UDP_LITE_EN BIT(10) ++#define MTK_PPE_GLO_CFG_UDP_LEN_DROP BIT(11) ++#define MTK_PPE_GLO_CFG_MCAST_ENTRIES GNEMASK(13, 12) ++#define MTK_PPE_GLO_CFG_BUSY BIT(31) ++ ++#define MTK_PPE_FLOW_CFG 0x204 ++#define MTK_PPE_FLOW_CFG_IP4_TCP_FRAG BIT(6) ++#define MTK_PPE_FLOW_CFG_IP4_UDP_FRAG BIT(7) ++#define MTK_PPE_FLOW_CFG_IP6_3T_ROUTE BIT(8) ++#define MTK_PPE_FLOW_CFG_IP6_5T_ROUTE BIT(9) ++#define MTK_PPE_FLOW_CFG_IP6_6RD BIT(10) ++#define MTK_PPE_FLOW_CFG_IP4_NAT BIT(12) ++#define MTK_PPE_FLOW_CFG_IP4_NAPT BIT(13) ++#define MTK_PPE_FLOW_CFG_IP4_DSLITE BIT(14) ++#define MTK_PPE_FLOW_CFG_L2_BRIDGE BIT(15) ++#define MTK_PPE_FLOW_CFG_IP_PROTO_BLACKLIST BIT(16) ++#define MTK_PPE_FLOW_CFG_IP4_NAT_FRAG BIT(17) ++#define MTK_PPE_FLOW_CFG_IP4_HASH_FLOW_LABEL BIT(18) ++#define MTK_PPE_FLOW_CFG_IP4_HASH_GRE_KEY BIT(19) ++#define MTK_PPE_FLOW_CFG_IP6_HASH_GRE_KEY BIT(20) ++ ++#define MTK_PPE_IP_PROTO_CHK 0x208 ++#define MTK_PPE_IP_PROTO_CHK_IPV4 GENMASK(15, 0) ++#define MTK_PPE_IP_PROTO_CHK_IPV6 GENMASK(31, 16) ++ ++#define MTK_PPE_TB_CFG 0x21c ++#define MTK_PPE_TB_CFG_ENTRY_NUM GENMASK(2, 0) ++#define MTK_PPE_TB_CFG_ENTRY_80B BIT(3) ++#define MTK_PPE_TB_CFG_SEARCH_MISS GENMASK(5, 4) ++#define MTK_PPE_TB_CFG_AGE_PREBIND BIT(6) ++#define MTK_PPE_TB_CFG_AGE_NON_L4 BIT(7) ++#define MTK_PPE_TB_CFG_AGE_UNBIND BIT(8) ++#define MTK_PPE_TB_CFG_AGE_TCP BIT(9) ++#define MTK_PPE_TB_CFG_AGE_UDP BIT(10) ++#define MTK_PPE_TB_CFG_AGE_TCP_FIN BIT(11) ++#define MTK_PPE_TB_CFG_KEEPALIVE GENMASK(13, 12) ++#define MTK_PPE_TB_CFG_HASH_MODE GENMASK(15, 14) ++#define MTK_PPE_TB_CFG_SCAN_MODE GENMASK(17, 16) ++#define MTK_PPE_TB_CFG_HASH_DEBUG GENMASK(19, 18) ++ ++enum { ++ MTK_PPE_SCAN_MODE_DISABLED, ++ MTK_PPE_SCAN_MODE_CHECK_AGE, ++ MTK_PPE_SCAN_MODE_KEEPALIVE_AGE, ++}; ++ ++enum { ++ MTK_PPE_KEEPALIVE_DISABLE, ++ MTK_PPE_KEEPALIVE_UNICAST_CPU, ++ MTK_PPE_KEEPALIVE_DUP_CPU = 3, ++}; ++ ++enum { ++ MTK_PPE_SEARCH_MISS_ACTION_DROP, ++ MTK_PPE_SEARCH_MISS_ACTION_FORWARD = 2, ++ MTK_PPE_SEARCH_MISS_ACTION_FORWARD_BUILD = 3, ++}; ++ ++#define MTK_PPE_TB_BASE 0x220 ++ ++#define MTK_PPE_TB_USED 0x224 ++#define MTK_PPE_TB_USED_NUM GENMASK(13, 0) ++ ++#define MTK_PPE_BIND_RATE 0x228 ++#define MTK_PPE_BIND_RATE_BIND GENMASK(15, 0) ++#define MTK_PPE_BIND_RATE_PREBIND GENMASK(31, 16) ++ ++#define MTK_PPE_BIND_LIMIT0 0x22c ++#define MTK_PPE_BIND_LIMIT0_QUARTER GENMASK(13, 0) ++#define MTK_PPE_BIND_LIMIT0_HALF GENMASK(29, 16) ++ ++#define MTK_PPE_BIND_LIMIT1 0x230 ++#define MTK_PPE_BIND_LIMIT1_FULL GENMASK(13, 0) ++#define MTK_PPE_BIND_LIMIT1_NON_L4 GENMASK(23, 16) ++ ++#define MTK_PPE_KEEPALIVE 0x234 ++#define MTK_PPE_KEEPALIVE_TIME GENMASK(15, 0) ++#define MTK_PPE_KEEPALIVE_TIME_TCP GENMASK(23, 16) ++#define MTK_PPE_KEEPALIVE_TIME_UDP GENMASK(31, 24) ++ ++#define MTK_PPE_UNBIND_AGE 0x238 ++#define MTK_PPE_UNBIND_AGE_MIN_PACKETS GENMASK(31, 16) ++#define MTK_PPE_UNBIND_AGE_DELTA GENMASK(7, 0) ++ ++#define MTK_PPE_BIND_AGE0 0x23c ++#define MTK_PPE_BIND_AGE0_DELTA_NON_L4 GENMASK(30, 16) ++#define MTK_PPE_BIND_AGE0_DELTA_UDP GENMASK(14, 0) ++ ++#define MTK_PPE_BIND_AGE1 0x240 ++#define MTK_PPE_BIND_AGE1_DELTA_TCP_FIN GENMASK(30, 16) ++#define MTK_PPE_BIND_AGE1_DELTA_TCP GENMASK(14, 0) ++ ++#define MTK_PPE_HASH_SEED 0x244 ++ ++#define MTK_PPE_DEFAULT_CPU_PORT 0x248 ++#define MTK_PPE_DEFAULT_CPU_PORT_MASK(_n) (GENMASK(2, 0) << ((_n) * 4)) ++ ++#define MTK_PPE_MTU_DROP 0x308 ++ ++#define MTK_PPE_VLAN_MTU0 0x30c ++#define MTK_PPE_VLAN_MTU0_NONE GENMASK(13, 0) ++#define MTK_PPE_VLAN_MTU0_1TAG GENMASK(29, 16) ++ ++#define MTK_PPE_VLAN_MTU1 0x310 ++#define MTK_PPE_VLAN_MTU1_2TAG GENMASK(13, 0) ++#define MTK_PPE_VLAN_MTU1_3TAG GENMASK(29, 16) ++ ++#define MTK_PPE_VPM_TPID 0x318 ++ ++#define MTK_PPE_CACHE_CTL 0x320 ++#define MTK_PPE_CACHE_CTL_EN BIT(0) ++#define MTK_PPE_CACHE_CTL_LOCK_CLR BIT(4) ++#define MTK_PPE_CACHE_CTL_REQ BIT(8) ++#define MTK_PPE_CACHE_CTL_CLEAR BIT(9) ++#define MTK_PPE_CACHE_CTL_CMD GENMASK(13, 12) ++ ++#define MTK_PPE_MIB_CFG 0x334 ++#define MTK_PPE_MIB_CFG_EN BIT(0) ++#define MTK_PPE_MIB_CFG_RD_CLR BIT(1) ++ ++#define MTK_PPE_MIB_TB_BASE 0x338 ++ ++#define MTK_PPE_MIB_CACHE_CTL 0x350 ++#define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) ++#define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) ++ ++#endif diff --git a/target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch b/target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch new file mode 100644 index 0000000000..599757d413 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch @@ -0,0 +1,568 @@ +From: Felix Fietkau +Date: Wed, 24 Mar 2021 02:30:54 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add flow offloading support + +This adds support for offloading IPv4 routed flows, including SNAT/DNAT, +one VLAN, PPPoE and DSA. + +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_offload.c + +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -4,5 +4,5 @@ + # + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o +-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o ++mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o + obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2834,6 +2834,7 @@ static const struct net_device_ops mtk_n + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = mtk_poll_controller, + #endif ++ .ndo_setup_tc = mtk_eth_setup_tc, + }; + + static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) +@@ -3092,6 +3093,10 @@ static int mtk_probe(struct platform_dev + eth->base + MTK_ETH_PPE_BASE, 2); + if (err) + goto err_free_dev; ++ ++ err = mtk_eth_offload_init(eth); ++ if (err) ++ goto err_free_dev; + } + + for (i = 0; i < MTK_MAX_DEVS; i++) { +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include "mtk_ppe.h" + + #define MTK_QDMA_PAGE_SIZE 2048 +@@ -40,7 +41,8 @@ + NETIF_F_HW_VLAN_CTAG_RX | \ + NETIF_F_SG | NETIF_F_TSO | \ + NETIF_F_TSO6 | \ +- NETIF_F_IPV6_CSUM) ++ NETIF_F_IPV6_CSUM |\ ++ NETIF_F_HW_TC) + #define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM) + #define NEXT_DESP_IDX(X, Y) (((X) + 1) & ((Y) - 1)) + +@@ -929,6 +931,7 @@ struct mtk_eth { + int ip_align; + + struct mtk_ppe ppe; ++ struct rhashtable flow_table; + }; + + /* struct mtk_mac - the structure that holds the info about the MACs of the +@@ -973,4 +976,9 @@ int mtk_gmac_sgmii_path_setup(struct mtk + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id); + ++int mtk_eth_offload_init(struct mtk_eth *eth); ++int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, ++ void *type_data); ++ ++ + #endif /* MTK_ETH_H */ +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -0,0 +1,485 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Felix Fietkau ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mtk_eth_soc.h" ++ ++struct mtk_flow_data { ++ struct ethhdr eth; ++ ++ union { ++ struct { ++ __be32 src_addr; ++ __be32 dst_addr; ++ } v4; ++ }; ++ ++ __be16 src_port; ++ __be16 dst_port; ++ ++ struct { ++ u16 id; ++ __be16 proto; ++ u8 num; ++ } vlan; ++ struct { ++ u16 sid; ++ u8 num; ++ } pppoe; ++}; ++ ++struct mtk_flow_entry { ++ struct rhash_head node; ++ unsigned long cookie; ++ u16 hash; ++}; ++ ++static const struct rhashtable_params mtk_flow_ht_params = { ++ .head_offset = offsetof(struct mtk_flow_entry, node), ++ .head_offset = offsetof(struct mtk_flow_entry, cookie), ++ .key_len = sizeof(unsigned long), ++ .automatic_shrinking = true, ++}; ++ ++static u32 ++mtk_eth_timestamp(struct mtk_eth *eth) ++{ ++ return mtk_r32(eth, 0x0010) & MTK_FOE_IB1_BIND_TIMESTAMP; ++} ++ ++static int ++mtk_flow_set_ipv4_addr(struct mtk_foe_entry *foe, struct mtk_flow_data *data, ++ bool egress) ++{ ++ return mtk_foe_entry_set_ipv4_tuple(foe, egress, ++ data->v4.src_addr, data->src_port, ++ data->v4.dst_addr, data->dst_port); ++} ++ ++static void ++mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth) ++{ ++ void *dest = eth + act->mangle.offset; ++ const void *src = &act->mangle.val; ++ ++ if (act->mangle.offset > 8) ++ return; ++ ++ if (act->mangle.mask == 0xffff) { ++ src += 2; ++ dest += 2; ++ } ++ ++ memcpy(dest, src, act->mangle.mask ? 2 : 4); ++} ++ ++ ++static int ++mtk_flow_mangle_ports(const struct flow_action_entry *act, ++ struct mtk_flow_data *data) ++{ ++ u32 val = ntohl(act->mangle.val); ++ ++ switch (act->mangle.offset) { ++ case 0: ++ if (act->mangle.mask == ~htonl(0xffff)) ++ data->dst_port = cpu_to_be16(val); ++ else ++ data->src_port = cpu_to_be16(val >> 16); ++ break; ++ case 2: ++ data->dst_port = cpu_to_be16(val); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_flow_mangle_ipv4(const struct flow_action_entry *act, ++ struct mtk_flow_data *data) ++{ ++ __be32 *dest; ++ ++ switch (act->mangle.offset) { ++ case offsetof(struct iphdr, saddr): ++ dest = &data->v4.src_addr; ++ break; ++ case offsetof(struct iphdr, daddr): ++ dest = &data->v4.dst_addr; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ memcpy(dest, &act->mangle.val, sizeof(u32)); ++ ++ return 0; ++} ++ ++static int ++mtk_flow_get_dsa_port(struct net_device **dev) ++{ ++#if IS_ENABLED(CONFIG_NET_DSA) ++ struct dsa_port *dp; ++ ++ dp = dsa_port_from_netdev(*dev); ++ if (IS_ERR(dp)) ++ return -ENODEV; ++ ++ if (dp->cpu_dp->tag_ops->proto != DSA_TAG_PROTO_MTK) ++ return -ENODEV; ++ ++ *dev = dp->cpu_dp->master; ++ ++ return dp->index; ++#else ++ return -ENODEV; ++#endif ++} ++ ++static int ++mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, ++ struct net_device *dev) ++{ ++ int pse_port, dsa_port; ++ ++ dsa_port = mtk_flow_get_dsa_port(&dev); ++ if (dsa_port >= 0) ++ mtk_foe_entry_set_dsa(foe, dsa_port); ++ ++ if (dev == eth->netdev[0]) ++ pse_port = 1; ++ else if (dev == eth->netdev[1]) ++ pse_port = 2; ++ else ++ return -EOPNOTSUPP; ++ ++ mtk_foe_entry_set_pse_port(foe, pse_port); ++ ++ return 0; ++} ++ ++static int ++mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) ++{ ++ struct flow_rule *rule = flow_cls_offload_flow_rule(f); ++ struct flow_action_entry *act; ++ struct mtk_flow_data data = {}; ++ struct mtk_foe_entry foe; ++ struct net_device *odev = NULL; ++ struct mtk_flow_entry *entry; ++ int offload_type = 0; ++ u16 addr_type = 0; ++ u32 timestamp; ++ u8 l4proto = 0; ++ int err = 0; ++ int hash; ++ int i; ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { ++ struct flow_match_meta match; ++ ++ flow_rule_match_meta(rule, &match); ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { ++ struct flow_match_control match; ++ ++ flow_rule_match_control(rule, &match); ++ addr_type = match.key->addr_type; ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { ++ struct flow_match_basic match; ++ ++ flow_rule_match_basic(rule, &match); ++ l4proto = match.key->ip_proto; ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ flow_action_for_each(i, act, &rule->action) { ++ switch (act->id) { ++ case FLOW_ACTION_MANGLE: ++ if (act->mangle.htype == FLOW_ACT_MANGLE_HDR_TYPE_ETH) ++ mtk_flow_offload_mangle_eth(act, &data.eth); ++ break; ++ case FLOW_ACTION_REDIRECT: ++ odev = act->dev; ++ break; ++ case FLOW_ACTION_CSUM: ++ break; ++ case FLOW_ACTION_VLAN_PUSH: ++ if (data.vlan.num == 1 || ++ act->vlan.proto != htons(ETH_P_8021Q)) ++ return -EOPNOTSUPP; ++ ++ data.vlan.id = act->vlan.vid; ++ data.vlan.proto = act->vlan.proto; ++ data.vlan.num++; ++ break; ++ case FLOW_ACTION_PPPOE_PUSH: ++ if (data.pppoe.num == 1) ++ return -EOPNOTSUPP; ++ ++ data.pppoe.sid = act->pppoe.sid; ++ data.pppoe.num++; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ switch (addr_type) { ++ case FLOW_DISSECTOR_KEY_IPV4_ADDRS: ++ offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ if (!is_valid_ether_addr(data.eth.h_source) || ++ !is_valid_ether_addr(data.eth.h_dest)) ++ return -EINVAL; ++ ++ err = mtk_foe_entry_prepare(&foe, offload_type, l4proto, 0, ++ data.eth.h_source, ++ data.eth.h_dest); ++ if (err) ++ return err; ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { ++ struct flow_match_ports ports; ++ ++ flow_rule_match_ports(rule, &ports); ++ data.src_port = ports.key->src; ++ data.dst_port = ports.key->dst; ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { ++ struct flow_match_ipv4_addrs addrs; ++ ++ flow_rule_match_ipv4_addrs(rule, &addrs); ++ ++ data.v4.src_addr = addrs.key->src; ++ data.v4.dst_addr = addrs.key->dst; ++ ++ mtk_flow_set_ipv4_addr(&foe, &data, false); ++ } ++ ++ flow_action_for_each(i, act, &rule->action) { ++ if (act->id != FLOW_ACTION_MANGLE) ++ continue; ++ ++ switch (act->mangle.htype) { ++ case FLOW_ACT_MANGLE_HDR_TYPE_TCP: ++ case FLOW_ACT_MANGLE_HDR_TYPE_UDP: ++ err = mtk_flow_mangle_ports(act, &data); ++ break; ++ case FLOW_ACT_MANGLE_HDR_TYPE_IP4: ++ err = mtk_flow_mangle_ipv4(act, &data); ++ break; ++ case FLOW_ACT_MANGLE_HDR_TYPE_ETH: ++ /* handled earlier */ ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ if (err) ++ return err; ++ } ++ ++ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { ++ err = mtk_flow_set_ipv4_addr(&foe, &data, true); ++ if (err) ++ return err; ++ } ++ ++ if (data.vlan.num == 1) { ++ if (data.vlan.proto != htons(ETH_P_8021Q)) ++ return -EOPNOTSUPP; ++ ++ mtk_foe_entry_set_vlan(&foe, data.vlan.id); ++ } ++ if (data.pppoe.num == 1) ++ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); ++ ++ err = mtk_flow_set_output_device(eth, &foe, odev); ++ if (err) ++ return err; ++ ++ entry = kzalloc(sizeof(*entry), GFP_KERNEL); ++ if (!entry) ++ return -ENOMEM; ++ ++ entry->cookie = f->cookie; ++ timestamp = mtk_eth_timestamp(eth); ++ hash = mtk_foe_entry_commit(ð->ppe, &foe, timestamp); ++ if (hash < 0) { ++ err = hash; ++ goto free; ++ } ++ ++ entry->hash = hash; ++ err = rhashtable_insert_fast(ð->flow_table, &entry->node, ++ mtk_flow_ht_params); ++ if (err < 0) ++ goto clear_flow; ++ ++ return 0; ++clear_flow: ++ mtk_foe_entry_clear(ð->ppe, hash); ++free: ++ kfree(entry); ++ return err; ++} ++ ++static int ++mtk_flow_offload_destroy(struct mtk_eth *eth, struct flow_cls_offload *f) ++{ ++ struct mtk_flow_entry *entry; ++ ++ entry = rhashtable_lookup(ð->flow_table, &f->cookie, ++ mtk_flow_ht_params); ++ if (!entry) ++ return -ENOENT; ++ ++ mtk_foe_entry_clear(ð->ppe, entry->hash); ++ rhashtable_remove_fast(ð->flow_table, &entry->node, ++ mtk_flow_ht_params); ++ kfree(entry); ++ ++ return 0; ++} ++ ++static int ++mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) ++{ ++ struct mtk_flow_entry *entry; ++ int timestamp; ++ u32 idle; ++ ++ entry = rhashtable_lookup(ð->flow_table, &f->cookie, ++ mtk_flow_ht_params); ++ if (!entry) ++ return -ENOENT; ++ ++ timestamp = mtk_foe_entry_timestamp(ð->ppe, entry->hash); ++ if (timestamp < 0) ++ return -ETIMEDOUT; ++ ++ idle = mtk_eth_timestamp(eth) - timestamp; ++ f->stats.lastused = jiffies - idle * HZ; ++ ++ return 0; ++} ++ ++static int ++mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) ++{ ++ struct flow_cls_offload *cls = type_data; ++ struct net_device *dev = cb_priv; ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ ++ if (!tc_can_offload(dev)) ++ return -EOPNOTSUPP; ++ ++ if (type != TC_SETUP_CLSFLOWER) ++ return -EOPNOTSUPP; ++ ++ switch (cls->command) { ++ case FLOW_CLS_REPLACE: ++ return mtk_flow_offload_replace(eth, cls); ++ case FLOW_CLS_DESTROY: ++ return mtk_flow_offload_destroy(eth, cls); ++ case FLOW_CLS_STATS: ++ return mtk_flow_offload_stats(eth, cls); ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ static LIST_HEAD(block_cb_list); ++ struct flow_block_cb *block_cb; ++ flow_setup_cb_t *cb; ++ ++ if (!eth->ppe.foe_table) ++ return -EOPNOTSUPP; ++ ++ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) ++ return -EOPNOTSUPP; ++ ++ cb = mtk_eth_setup_tc_block_cb; ++ f->driver_block_list = &block_cb_list; ++ ++ switch (f->command) { ++ case FLOW_BLOCK_BIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, dev); ++ if (block_cb) { ++ flow_block_cb_incref(block_cb); ++ return 0; ++ } ++ block_cb = flow_block_cb_alloc(cb, dev, dev, NULL); ++ if (IS_ERR(block_cb)) ++ return PTR_ERR(block_cb); ++ ++ flow_block_cb_add(block_cb, f); ++ list_add_tail(&block_cb->driver_list, &block_cb_list); ++ return 0; ++ case FLOW_BLOCK_UNBIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, dev); ++ if (!block_cb) ++ return -ENOENT; ++ ++ if (flow_block_cb_decref(block_cb)) { ++ flow_block_cb_remove(block_cb, f); ++ list_del(&block_cb->driver_list); ++ } ++ return 0; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, ++ void *type_data) ++{ ++ if (type == TC_SETUP_FT) ++ return mtk_eth_setup_tc_block(dev, type_data); ++ ++ return -EOPNOTSUPP; ++} ++ ++int mtk_eth_offload_init(struct mtk_eth *eth) ++{ ++ if (!eth->ppe.foe_table) ++ return 0; ++ ++ return rhashtable_init(ð->flow_table, &mtk_flow_ht_params); ++} diff --git a/target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch b/target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch new file mode 100644 index 0000000000..2cea1ebe24 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch @@ -0,0 +1,236 @@ +From: Pablo Neira Ayuso +Date: Wed, 24 Mar 2021 02:30:55 +0100 +Subject: [PATCH] docs: nf_flowtable: update documentation with + enhancements + +This patch updates the flowtable documentation to describe recent +enhancements: + +- Offload action is available after the first packets go through the + classic forwarding path. +- IPv4 and IPv6 are supported. Only TCP and UDP layer 4 are supported at + this stage. +- Tuple has been augmented to track VLAN id and PPPoE session id. +- Bridge and IP forwarding integration, including bridge VLAN filtering + support. +- Hardware offload support. +- Describe the [OFFLOAD] and [HW_OFFLOAD] tags in the conntrack table + listing. +- Replace 'flow offload' by 'flow add' in example rulesets (preferred + syntax). +- Describe existing cache limitations. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/Documentation/networking/nf_flowtable.rst ++++ b/Documentation/networking/nf_flowtable.rst +@@ -4,35 +4,38 @@ + Netfilter's flowtable infrastructure + ==================================== + +-This documentation describes the software flowtable infrastructure available in +-Netfilter since Linux kernel 4.16. ++This documentation describes the Netfilter flowtable infrastructure which allows ++you to define a fastpath through the flowtable datapath. This infrastructure ++also provides hardware offload support. The flowtable supports for the layer 3 ++IPv4 and IPv6 and the layer 4 TCP and UDP protocols. + + Overview + -------- + +-Initial packets follow the classic forwarding path, once the flow enters the +-established state according to the conntrack semantics (ie. we have seen traffic +-in both directions), then you can decide to offload the flow to the flowtable +-from the forward chain via the 'flow offload' action available in nftables. +- +-Packets that find an entry in the flowtable (ie. flowtable hit) are sent to the +-output netdevice via neigh_xmit(), hence, they bypass the classic forwarding +-path (the visible effect is that you do not see these packets from any of the +-netfilter hooks coming after the ingress). In case of flowtable miss, the packet +-follows the classic forward path. +- +-The flowtable uses a resizable hashtable, lookups are based on the following +-7-tuple selectors: source, destination, layer 3 and layer 4 protocols, source +-and destination ports and the input interface (useful in case there are several +-conntrack zones in place). +- +-Flowtables are populated via the 'flow offload' nftables action, so the user can +-selectively specify what flows are placed into the flow table. Hence, packets +-follow the classic forwarding path unless the user explicitly instruct packets +-to use this new alternative forwarding path via nftables policy. ++Once the first packet of the flow successfully goes through the IP forwarding ++path, from the second packet on, you might decide to offload the flow to the ++flowtable through your ruleset. The flowtable infrastructure provides a rule ++action that allows you to specify when to add a flow to the flowtable. ++ ++A packet that finds a matching entry in the flowtable (ie. flowtable hit) is ++transmitted to the output netdevice via neigh_xmit(), hence, packets bypass the ++classic IP forwarding path (the visible effect is that you do not see these ++packets from any of the Netfilter hooks coming after ingress). In case that ++there is no matching entry in the flowtable (ie. flowtable miss), the packet ++follows the classic IP forwarding path. ++ ++The flowtable uses a resizable hashtable. Lookups are based on the following ++n-tuple selectors: layer 2 protocol encapsulation (VLAN and PPPoE), layer 3 ++source and destination, layer 4 source and destination ports and the input ++interface (useful in case there are several conntrack zones in place). ++ ++The 'flow add' action allows you to populate the flowtable, the user selectively ++specifies what flows are placed into the flowtable. Hence, packets follow the ++classic IP forwarding path unless the user explicitly instruct flows to use this ++new alternative forwarding path via policy. + +-This is represented in Fig.1, which describes the classic forwarding path +-including the Netfilter hooks and the flowtable fastpath bypass. ++The flowtable datapath is represented in Fig.1, which describes the classic IP ++forwarding path including the Netfilter hooks and the flowtable fastpath bypass. + + :: + +@@ -67,11 +70,13 @@ including the Netfilter hooks and the fl + Fig.1 Netfilter hooks and flowtable interactions + + The flowtable entry also stores the NAT configuration, so all packets are +-mangled according to the NAT policy that matches the initial packets that went +-through the classic forwarding path. The TTL is decremented before calling +-neigh_xmit(). Fragmented traffic is passed up to follow the classic forwarding +-path given that the transport selectors are missing, therefore flowtable lookup +-is not possible. ++mangled according to the NAT policy that is specified from the classic IP ++forwarding path. The TTL is decremented before calling neigh_xmit(). Fragmented ++traffic is passed up to follow the classic IP forwarding path given that the ++transport header is missing, in this case, flowtable lookups are not possible. ++TCP RST and FIN packets are also passed up to the classic IP forwarding path to ++release the flow gracefully. Packets that exceed the MTU are also passed up to ++the classic forwarding path to report packet-too-big ICMP errors to the sender. + + Example configuration + --------------------- +@@ -85,7 +90,7 @@ flowtable and add one rule to your forwa + } + chain y { + type filter hook forward priority 0; policy accept; +- ip protocol tcp flow offload @f ++ ip protocol tcp flow add @f + counter packets 0 bytes 0 + } + } +@@ -103,6 +108,117 @@ flow is offloaded, you will observe that + does not get updated for the packets that are being forwarded through the + forwarding bypass. + ++You can identify offloaded flows through the [OFFLOAD] tag when listing your ++connection tracking table. ++ ++:: ++ # conntrack -L ++ tcp 6 src=10.141.10.2 dst=192.168.10.2 sport=52728 dport=5201 src=192.168.10.2 dst=192.168.10.1 sport=5201 dport=52728 [OFFLOAD] mark=0 use=2 ++ ++ ++Layer 2 encapsulation ++--------------------- ++ ++Since Linux kernel 5.13, the flowtable infrastructure discovers the real ++netdevice behind VLAN and PPPoE netdevices. The flowtable software datapath ++parses the VLAN and PPPoE layer 2 headers to extract the ethertype and the ++VLAN ID / PPPoE session ID which are used for the flowtable lookups. The ++flowtable datapath also deals with layer 2 decapsulation. ++ ++You do not need to add the PPPoE and the VLAN devices to your flowtable, ++instead the real device is sufficient for the flowtable to track your flows. ++ ++Bridge and IP forwarding ++------------------------ ++ ++Since Linux kernel 5.13, you can add bridge ports to the flowtable. The ++flowtable infrastructure discovers the topology behind the bridge device. This ++allows the flowtable to define a fastpath bypass between the bridge ports ++(represented as eth1 and eth2 in the example figure below) and the gateway ++device (represented as eth0) in your switch/router. ++ ++:: ++ fastpath bypass ++ .-------------------------. ++ / \ ++ | IP forwarding | ++ | / \ \/ ++ | br0 eth0 ..... eth0 ++ . / \ *host B* ++ -> eth1 eth2 ++ . *switch/router* ++ . ++ . ++ eth0 ++ *host A* ++ ++The flowtable infrastructure also supports for bridge VLAN filtering actions ++such as PVID and untagged. You can also stack a classic VLAN device on top of ++your bridge port. ++ ++If you would like that your flowtable defines a fastpath between your bridge ++ports and your IP forwarding path, you have to add your bridge ports (as ++represented by the real netdevice) to your flowtable definition. ++ ++Counters ++-------- ++ ++The flowtable can synchronize packet and byte counters with the existing ++connection tracking entry by specifying the counter statement in your flowtable ++definition, e.g. ++ ++:: ++ table inet x { ++ flowtable f { ++ hook ingress priority 0; devices = { eth0, eth1 }; ++ counter ++ } ++ ... ++ } ++ ++Counter support is available since Linux kernel 5.7. ++ ++Hardware offload ++---------------- ++ ++If your network device provides hardware offload support, you can turn it on by ++means of the 'offload' flag in your flowtable definition, e.g. ++ ++:: ++ table inet x { ++ flowtable f { ++ hook ingress priority 0; devices = { eth0, eth1 }; ++ flags offload; ++ } ++ ... ++ } ++ ++There is a workqueue that adds the flows to the hardware. Note that a few ++packets might still run over the flowtable software path until the workqueue has ++a chance to offload the flow to the network device. ++ ++You can identify hardware offloaded flows through the [HW_OFFLOAD] tag when ++listing your connection tracking table. Please, note that the [OFFLOAD] tag ++refers to the software offload mode, so there is a distinction between [OFFLOAD] ++which refers to the software flowtable fastpath and [HW_OFFLOAD] which refers ++to the hardware offload datapath being used by the flow. ++ ++The flowtable hardware offload infrastructure also supports for the DSA ++(Distributed Switch Architecture). ++ ++Limitations ++----------- ++ ++The flowtable behaves like a cache. The flowtable entries might get stale if ++either the destination MAC address or the egress netdevice that is used for ++transmission changes. ++ ++This might be a problem if: ++ ++- You run the flowtable in software mode and you combine bridge and IP ++ forwarding in your setup. ++- Hardware offload is enabled. ++ + More reading + ------------ + diff --git a/target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch b/target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch new file mode 100644 index 0000000000..66cd053cd1 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch @@ -0,0 +1,72 @@ +From c5d66587b8900201e1530b7c18d41e87bd5812f4 Mon Sep 17 00:00:00 2001 +From: Ilya Lipnitskiy +Date: Thu, 15 Apr 2021 17:37:48 -0700 +Subject: [PATCH] net: ethernet: mediatek: ppe: fix busy wait loop + +The intention is for the loop to timeout if the body does not succeed. +The current logic calls time_is_before_jiffies(timeout) which is false +until after the timeout, so the loop body never executes. + +Fix by using readl_poll_timeout as a more standard and less error-prone +solution. + +Fixes: ba37b7caf1ed ("net: ethernet: mtk_eth_soc: add support for initializing the PPE") +Signed-off-by: Ilya Lipnitskiy +Cc: Felix Fietkau +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_ppe.c | 20 +++++++++----------- + drivers/net/ethernet/mediatek/mtk_ppe.h | 1 + + 2 files changed, 10 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -2,9 +2,8 @@ + /* Copyright (C) 2020 Felix Fietkau */ + + #include +-#include +-#include + #include ++#include + #include + #include + #include "mtk_ppe.h" +@@ -44,18 +43,17 @@ static u32 ppe_clear(struct mtk_ppe *ppe + + static int mtk_ppe_wait_busy(struct mtk_ppe *ppe) + { +- unsigned long timeout = jiffies + HZ; +- +- while (time_is_before_jiffies(timeout)) { +- if (!(ppe_r32(ppe, MTK_PPE_GLO_CFG) & MTK_PPE_GLO_CFG_BUSY)) +- return 0; ++ int ret; ++ u32 val; + +- usleep_range(10, 20); +- } ++ ret = readl_poll_timeout(ppe->base + MTK_PPE_GLO_CFG, val, ++ !(val & MTK_PPE_GLO_CFG_BUSY), ++ 20, MTK_PPE_WAIT_TIMEOUT_US); + +- dev_err(ppe->dev, "PPE table busy"); ++ if (ret) ++ dev_err(ppe->dev, "PPE table busy"); + +- return -ETIMEDOUT; ++ return ret; + } + + static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -12,6 +12,7 @@ + #define MTK_PPE_ENTRIES_SHIFT 3 + #define MTK_PPE_ENTRIES (1024 << MTK_PPE_ENTRIES_SHIFT) + #define MTK_PPE_HASH_MASK (MTK_PPE_ENTRIES - 1) ++#define MTK_PPE_WAIT_TIMEOUT_US 1000000 + + #define MTK_FOE_IB1_UNBIND_TIMESTAMP GENMASK(7, 0) + #define MTK_FOE_IB1_UNBIND_PACKETS GENMASK(23, 8) diff --git a/target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch b/target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch new file mode 100644 index 0000000000..de376bf78d --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch @@ -0,0 +1,29 @@ +From 6ecaf81d4ac6365f9284f9d68d74f7c209e74f98 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Sat, 17 Apr 2021 15:29:04 +0800 +Subject: [PATCH] net: ethernet: mediatek: fix a typo bug in flow offloading + +Issue was traffic problems after a while with increased ping times if +flow offload is active. It turns out that key_offset with cookie is +needed in rhashtable_params but was re-assigned to head_offset. +Fix the assignment. + +Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support") +Signed-off-by: DENG Qingfang +Tested-by: Frank Wunderlich +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -44,7 +44,7 @@ struct mtk_flow_entry { + + static const struct rhashtable_params mtk_flow_ht_params = { + .head_offset = offsetof(struct mtk_flow_entry, node), +- .head_offset = offsetof(struct mtk_flow_entry, cookie), ++ .key_offset = offsetof(struct mtk_flow_entry, cookie), + .key_len = sizeof(unsigned long), + .automatic_shrinking = true, + }; diff --git a/target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch b/target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch new file mode 100644 index 0000000000..e99302ecda --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch @@ -0,0 +1,38 @@ +From 5196c417854942e218a59ec87bf7d414b3bd581e Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:20:55 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: unmap RX data before calling + build_skb + +Since build_skb accesses the data area (for initializing shinfo), dma unmap +needs to happen before that call + +Signed-off-by: Felix Fietkau +[Ilya: split build_skb cleanup fix into a separate commit] +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1319,6 +1319,9 @@ static int mtk_poll_rx(struct napi_struc + goto release_desc; + } + ++ dma_unmap_single(eth->dev, trxd.rxd1, ++ ring->buf_size, DMA_FROM_DEVICE); ++ + /* receive data */ + skb = build_skb(data, ring->frag_size); + if (unlikely(!skb)) { +@@ -1328,8 +1331,6 @@ static int mtk_poll_rx(struct napi_struc + } + skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); + +- dma_unmap_single(eth->dev, trxd.rxd1, +- ring->buf_size, DMA_FROM_DEVICE); + pktlen = RX_DMA_GET_PLEN0(trxd.rxd2); + skb->dev = netdev; + skb_put(skb, pktlen); diff --git a/target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch b/target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch new file mode 100644 index 0000000000..a82518882a --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch @@ -0,0 +1,38 @@ +From 787082ab9f7be4711e52f67c388535eda74a1269 Mon Sep 17 00:00:00 2001 +From: Ilya Lipnitskiy +Date: Thu, 22 Apr 2021 22:20:56 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix build_skb cleanup + +In case build_skb fails, call skb_free_frag on the correct pointer. Also +update the DMA structures with the new mapping before exiting, because +the mapping was successful + +Suggested-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1325,9 +1325,9 @@ static int mtk_poll_rx(struct napi_struc + /* receive data */ + skb = build_skb(data, ring->frag_size); + if (unlikely(!skb)) { +- skb_free_frag(new_data); ++ skb_free_frag(data); + netdev->stats.rx_dropped++; +- goto release_desc; ++ goto skip_rx; + } + skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); + +@@ -1347,6 +1347,7 @@ static int mtk_poll_rx(struct napi_struc + skb_record_rx_queue(skb, 0); + napi_gro_receive(napi, skb); + ++skip_rx: + ring->data[idx] = new_data; + rxd->rxd1 = (unsigned int)dma_addr; + diff --git a/target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch b/target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch new file mode 100644 index 0000000000..5972b9afa7 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch @@ -0,0 +1,77 @@ +From c30c4a82739090a2de4a4e3f245355ea4fb3ec14 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:20:57 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: use napi_consume_skb + +Should improve performance, since it can use bulk free + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -879,7 +879,8 @@ static int txd_to_idx(struct mtk_tx_ring + return ((void *)dma - (void *)ring->dma) / sizeof(*dma); + } + +-static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf) ++static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf, ++ bool napi) + { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { + if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) { +@@ -911,8 +912,12 @@ static void mtk_tx_unmap(struct mtk_eth + + tx_buf->flags = 0; + if (tx_buf->skb && +- (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC)) +- dev_kfree_skb_any(tx_buf->skb); ++ (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC)) { ++ if (napi) ++ napi_consume_skb(tx_buf->skb, napi); ++ else ++ dev_kfree_skb_any(tx_buf->skb); ++ } + tx_buf->skb = NULL; + } + +@@ -1090,7 +1095,7 @@ err_dma: + tx_buf = mtk_desc_to_tx_buf(ring, itxd); + + /* unmap dma */ +- mtk_tx_unmap(eth, tx_buf); ++ mtk_tx_unmap(eth, tx_buf, false); + + itxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +@@ -1409,7 +1414,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + done[mac]++; + budget--; + } +- mtk_tx_unmap(eth, tx_buf); ++ mtk_tx_unmap(eth, tx_buf, true); + + ring->last_free = desc; + atomic_inc(&ring->free_count); +@@ -1446,7 +1451,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + budget--; + } + +- mtk_tx_unmap(eth, tx_buf); ++ mtk_tx_unmap(eth, tx_buf, true); + + desc = &ring->dma[cpu]; + ring->last_free = desc; +@@ -1648,7 +1653,7 @@ static void mtk_tx_clean(struct mtk_eth + + if (ring->buf) { + for (i = 0; i < MTK_DMA_SIZE; i++) +- mtk_tx_unmap(eth, &ring->buf[i]); ++ mtk_tx_unmap(eth, &ring->buf[i], false); + kfree(ring->buf); + ring->buf = NULL; + } diff --git a/target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch b/target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch new file mode 100644 index 0000000000..7ebc3fa903 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch @@ -0,0 +1,30 @@ +From 3630d519d7c3eab92567658690e44ffe0517d109 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:20:58 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: reduce MDIO bus access latency + +usleep_range often ends up sleeping much longer than the 10-20us provided +as a range here. This causes significant latency in mdio bus acceses, +which easily adds multiple seconds to the boot time on MT7621 when polling +DSA slave ports. +Use cond_resched instead of usleep_range, since the MDIO access does not +take much time + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -86,7 +86,7 @@ static int mtk_mdio_busy_wait(struct mtk + return 0; + if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT)) + break; +- usleep_range(10, 20); ++ cond_resched(); + } + + dev_err(eth->dev, "mdio: MDIO timeout\n"); diff --git a/target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch b/target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch new file mode 100644 index 0000000000..56d4a82824 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch @@ -0,0 +1,54 @@ +From 16ef670789b252b221700adc413497ed2f941d8a Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:20:59 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: remove unnecessary TX queue stops + +When running short on descriptors, only stop the queue for the netdev that +tx was attempted for. By the time something tries to send on the other +netdev, the ring might have some more room already. + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 ++------------- + 1 file changed, 2 insertions(+), 13 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1152,17 +1152,6 @@ static void mtk_wake_queue(struct mtk_et + } + } + +-static void mtk_stop_queue(struct mtk_eth *eth) +-{ +- int i; +- +- for (i = 0; i < MTK_MAC_COUNT; i++) { +- if (!eth->netdev[i]) +- continue; +- netif_stop_queue(eth->netdev[i]); +- } +-} +- + static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); +@@ -1183,7 +1172,7 @@ static netdev_tx_t mtk_start_xmit(struct + + tx_num = mtk_cal_txd_req(skb); + if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { +- mtk_stop_queue(eth); ++ netif_stop_queue(dev); + netif_err(eth, tx_queued, dev, + "Tx Ring full when queue awake!\n"); + spin_unlock(ð->page_lock); +@@ -1209,7 +1198,7 @@ static netdev_tx_t mtk_start_xmit(struct + goto drop; + + if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) +- mtk_stop_queue(eth); ++ netif_stop_queue(dev); + + spin_unlock(ð->page_lock); + diff --git a/target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch b/target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch new file mode 100644 index 0000000000..a192250e28 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch @@ -0,0 +1,37 @@ +From 59555a8d0dd39bf60b7ca1ba5e7393d293f7398d Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:00 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: use larger burst size for QDMA TX + +Improves tx performance + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2214,7 +2214,7 @@ static int mtk_start_dma(struct mtk_eth + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { + mtk_w32(eth, + MTK_TX_WB_DDONE | MTK_TX_DMA_EN | +- MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO | ++ MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | + MTK_RX_DMA_EN | MTK_RX_2B_OFFSET | + MTK_RX_BT_32DWORDS, + MTK_QDMA_GLO_CFG); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -202,7 +202,7 @@ + #define MTK_RX_BT_32DWORDS (3 << 11) + #define MTK_NDP_CO_PRO BIT(10) + #define MTK_TX_WB_DDONE BIT(6) +-#define MTK_DMA_SIZE_16DWORDS (2 << 4) ++#define MTK_TX_BT_32DWORDS (3 << 4) + #define MTK_RX_DMA_BUSY BIT(3) + #define MTK_TX_DMA_BUSY BIT(1) + #define MTK_RX_DMA_EN BIT(2) diff --git a/target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch b/target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch new file mode 100644 index 0000000000..d695f0fb8a --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch @@ -0,0 +1,26 @@ +From 6b4423b258b91032c50a5efca15d3d9bb194ea1d Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:01 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: increase DMA ring sizes + +256 descriptors is not enough for multi-gigabit traffic under load on +MT7622. Bump it to 512 to improve performance. + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -21,7 +21,7 @@ + #define MTK_QDMA_PAGE_SIZE 2048 + #define MTK_MAX_RX_LENGTH 1536 + #define MTK_TX_DMA_BUF_LEN 0x3fff +-#define MTK_DMA_SIZE 256 ++#define MTK_DMA_SIZE 512 + #define MTK_NAPI_WEIGHT 64 + #define MTK_MAC_COUNT 2 + #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) diff --git a/target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch b/target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch new file mode 100644 index 0000000000..207d8397d8 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch @@ -0,0 +1,313 @@ +From e9229ffd550b2d8c4997c67a501dbc3919fd4e26 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:02 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: implement dynamic interrupt + moderation + +Reduces the number of interrupts under load + +Signed-off-by: Felix Fietkau +[Ilya: add documentation for new struct fields] +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/Kconfig | 1 + + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 96 +++++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 41 +++++++-- + 3 files changed, 124 insertions(+), 14 deletions(-) + +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -10,6 +10,7 @@ if NET_VENDOR_MEDIATEK + config NET_MEDIATEK_SOC + tristate "MediaTek SoC Gigabit Ethernet support" + select PHYLINK ++ select DIMLIB + help + This driver supports the gigabit ethernet MACs in the + MediaTek SoC family. +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1254,12 +1254,13 @@ static void mtk_update_rx_cpu_idx(struct + static int mtk_poll_rx(struct napi_struct *napi, int budget, + struct mtk_eth *eth) + { ++ struct dim_sample dim_sample = {}; + struct mtk_rx_ring *ring; + int idx; + struct sk_buff *skb; + u8 *data, *new_data; + struct mtk_rx_dma *rxd, trxd; +- int done = 0; ++ int done = 0, bytes = 0; + + while (done < budget) { + struct net_device *netdev; +@@ -1333,6 +1334,7 @@ static int mtk_poll_rx(struct napi_struc + else + skb_checksum_none_assert(skb); + skb->protocol = eth_type_trans(skb, netdev); ++ bytes += pktlen; + + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && + (trxd.rxd2 & RX_DMA_VTAG)) +@@ -1365,6 +1367,12 @@ rx_done: + mtk_update_rx_cpu_idx(eth); + } + ++ eth->rx_packets += done; ++ eth->rx_bytes += bytes; ++ dim_update_sample(eth->rx_events, eth->rx_packets, eth->rx_bytes, ++ &dim_sample); ++ net_dim(ð->rx_dim, dim_sample); ++ + return done; + } + +@@ -1457,6 +1465,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + static int mtk_poll_tx(struct mtk_eth *eth, int budget) + { + struct mtk_tx_ring *ring = ð->tx_ring; ++ struct dim_sample dim_sample = {}; + unsigned int done[MTK_MAX_DEVS]; + unsigned int bytes[MTK_MAX_DEVS]; + int total = 0, i; +@@ -1474,8 +1483,14 @@ static int mtk_poll_tx(struct mtk_eth *e + continue; + netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); + total += done[i]; ++ eth->tx_packets += done[i]; ++ eth->tx_bytes += bytes[i]; + } + ++ dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, ++ &dim_sample); ++ net_dim(ð->tx_dim, dim_sample); ++ + if (mtk_queue_stopped(eth) && + (atomic_read(&ring->free_count) > ring->thresh)) + mtk_wake_queue(eth); +@@ -2150,6 +2165,7 @@ static irqreturn_t mtk_handle_irq_rx(int + { + struct mtk_eth *eth = _eth; + ++ eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { + __napi_schedule(ð->rx_napi); + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); +@@ -2162,6 +2178,7 @@ static irqreturn_t mtk_handle_irq_tx(int + { + struct mtk_eth *eth = _eth; + ++ eth->tx_events++; + if (likely(napi_schedule_prep(ð->tx_napi))) { + __napi_schedule(ð->tx_napi); + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +@@ -2346,6 +2363,9 @@ static int mtk_stop(struct net_device *d + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + ++ cancel_work_sync(ð->rx_dim.work); ++ cancel_work_sync(ð->tx_dim.work); ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) + mtk_stop_dma(eth, MTK_QDMA_GLO_CFG); + mtk_stop_dma(eth, MTK_PDMA_GLO_CFG); +@@ -2398,6 +2418,64 @@ err_disable_clks: + return ret; + } + ++static void mtk_dim_rx(struct work_struct *work) ++{ ++ struct dim *dim = container_of(work, struct dim, work); ++ struct mtk_eth *eth = container_of(dim, struct mtk_eth, rx_dim); ++ struct dim_cq_moder cur_profile; ++ u32 val, cur; ++ ++ cur_profile = net_dim_get_rx_moderation(eth->rx_dim.mode, ++ dim->profile_ix); ++ spin_lock_bh(ð->dim_lock); ++ ++ val = mtk_r32(eth, MTK_PDMA_DELAY_INT); ++ val &= MTK_PDMA_DELAY_TX_MASK; ++ val |= MTK_PDMA_DELAY_RX_EN; ++ ++ cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK); ++ val |= cur << MTK_PDMA_DELAY_RX_PTIME_SHIFT; ++ ++ cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK); ++ val |= cur << MTK_PDMA_DELAY_RX_PINT_SHIFT; ++ ++ mtk_w32(eth, val, MTK_PDMA_DELAY_INT); ++ mtk_w32(eth, val, MTK_QDMA_DELAY_INT); ++ ++ spin_unlock_bh(ð->dim_lock); ++ ++ dim->state = DIM_START_MEASURE; ++} ++ ++static void mtk_dim_tx(struct work_struct *work) ++{ ++ struct dim *dim = container_of(work, struct dim, work); ++ struct mtk_eth *eth = container_of(dim, struct mtk_eth, tx_dim); ++ struct dim_cq_moder cur_profile; ++ u32 val, cur; ++ ++ cur_profile = net_dim_get_tx_moderation(eth->tx_dim.mode, ++ dim->profile_ix); ++ spin_lock_bh(ð->dim_lock); ++ ++ val = mtk_r32(eth, MTK_PDMA_DELAY_INT); ++ val &= MTK_PDMA_DELAY_RX_MASK; ++ val |= MTK_PDMA_DELAY_TX_EN; ++ ++ cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK); ++ val |= cur << MTK_PDMA_DELAY_TX_PTIME_SHIFT; ++ ++ cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK); ++ val |= cur << MTK_PDMA_DELAY_TX_PINT_SHIFT; ++ ++ mtk_w32(eth, val, MTK_PDMA_DELAY_INT); ++ mtk_w32(eth, val, MTK_QDMA_DELAY_INT); ++ ++ spin_unlock_bh(ð->dim_lock); ++ ++ dim->state = DIM_START_MEASURE; ++} ++ + static int mtk_hw_init(struct mtk_eth *eth) + { + int i, val, ret; +@@ -2419,9 +2497,6 @@ static int mtk_hw_init(struct mtk_eth *e + goto err_disable_pm; + } + +- /* enable interrupt delay for RX */ +- mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT); +- + /* disable delay and normal interrupt */ + mtk_tx_irq_disable(eth, ~0); + mtk_rx_irq_disable(eth, ~0); +@@ -2460,11 +2535,11 @@ static int mtk_hw_init(struct mtk_eth *e + /* Enable RX VLan Offloading */ + mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); + +- /* enable interrupt delay for RX */ +- mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT); ++ /* set interrupt delays based on current Net DIM sample */ ++ mtk_dim_rx(ð->rx_dim.work); ++ mtk_dim_tx(ð->tx_dim.work); + + /* disable delay and normal interrupt */ +- mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); + mtk_tx_irq_disable(eth, ~0); + mtk_rx_irq_disable(eth, ~0); + +@@ -2969,6 +3044,13 @@ static int mtk_probe(struct platform_dev + spin_lock_init(ð->page_lock); + spin_lock_init(ð->tx_irq_lock); + spin_lock_init(ð->rx_irq_lock); ++ spin_lock_init(ð->dim_lock); ++ ++ eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; ++ INIT_WORK(ð->rx_dim.work, mtk_dim_rx); ++ ++ eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; ++ INIT_WORK(ð->tx_dim.work, mtk_dim_tx); + + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { + eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include "mtk_ppe.h" + + #define MTK_QDMA_PAGE_SIZE 2048 +@@ -136,13 +137,18 @@ + + /* PDMA Delay Interrupt Register */ + #define MTK_PDMA_DELAY_INT 0xa0c ++#define MTK_PDMA_DELAY_RX_MASK GENMASK(15, 0) + #define MTK_PDMA_DELAY_RX_EN BIT(15) +-#define MTK_PDMA_DELAY_RX_PINT 4 + #define MTK_PDMA_DELAY_RX_PINT_SHIFT 8 +-#define MTK_PDMA_DELAY_RX_PTIME 4 +-#define MTK_PDMA_DELAY_RX_DELAY \ +- (MTK_PDMA_DELAY_RX_EN | MTK_PDMA_DELAY_RX_PTIME | \ +- (MTK_PDMA_DELAY_RX_PINT << MTK_PDMA_DELAY_RX_PINT_SHIFT)) ++#define MTK_PDMA_DELAY_RX_PTIME_SHIFT 0 ++ ++#define MTK_PDMA_DELAY_TX_MASK GENMASK(31, 16) ++#define MTK_PDMA_DELAY_TX_EN BIT(31) ++#define MTK_PDMA_DELAY_TX_PINT_SHIFT 24 ++#define MTK_PDMA_DELAY_TX_PTIME_SHIFT 16 ++ ++#define MTK_PDMA_DELAY_PINT_MASK 0x7f ++#define MTK_PDMA_DELAY_PTIME_MASK 0xff + + /* PDMA Interrupt Status Register */ + #define MTK_PDMA_INT_STATUS 0xa20 +@@ -224,6 +230,7 @@ + /* QDMA Interrupt Status Register */ + #define MTK_QDMA_INT_STATUS 0x1A18 + #define MTK_RX_DONE_DLY BIT(30) ++#define MTK_TX_DONE_DLY BIT(28) + #define MTK_RX_DONE_INT3 BIT(19) + #define MTK_RX_DONE_INT2 BIT(18) + #define MTK_RX_DONE_INT1 BIT(17) +@@ -233,8 +240,7 @@ + #define MTK_TX_DONE_INT1 BIT(1) + #define MTK_TX_DONE_INT0 BIT(0) + #define MTK_RX_DONE_INT MTK_RX_DONE_DLY +-#define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \ +- MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3) ++#define MTK_TX_DONE_INT MTK_TX_DONE_DLY + + /* QDMA Interrupt grouping registers */ + #define MTK_QDMA_INT_GRP1 0x1a20 +@@ -863,6 +869,7 @@ struct mtk_sgmii { + * @page_lock: Make sure that register operations are atomic + * @tx_irq__lock: Make sure that IRQ register operations are atomic + * @rx_irq__lock: Make sure that IRQ register operations are atomic ++ * @dim_lock: Make sure that Net DIM operations are atomic + * @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a + * dummy for NAPI to work + * @netdev: The netdev instances +@@ -881,6 +888,14 @@ struct mtk_sgmii { + * @rx_ring_qdma: Pointer to the memory holding info about the QDMA RX ring + * @tx_napi: The TX NAPI struct + * @rx_napi: The RX NAPI struct ++ * @rx_events: Net DIM RX event counter ++ * @rx_packets: Net DIM RX packet counter ++ * @rx_bytes: Net DIM RX byte counter ++ * @rx_dim: Net DIM RX context ++ * @tx_events: Net DIM TX event counter ++ * @tx_packets: Net DIM TX packet counter ++ * @tx_bytes: Net DIM TX byte counter ++ * @tx_dim: Net DIM TX context + * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring + * @phy_scratch_ring: physical address of scratch_ring + * @scratch_head: The scratch memory that scratch_ring points to. +@@ -925,6 +940,18 @@ struct mtk_eth { + + const struct mtk_soc_data *soc; + ++ spinlock_t dim_lock; ++ ++ u32 rx_events; ++ u32 rx_packets; ++ u32 rx_bytes; ++ struct dim rx_dim; ++ ++ u32 tx_events; ++ u32 tx_packets; ++ u32 tx_bytes; ++ struct dim tx_dim; ++ + u32 tx_int_mask_reg; + u32 tx_int_status_reg; + u32 rx_dma_l4_valid; diff --git a/target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch b/target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch new file mode 100644 index 0000000000..c2252ed728 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch @@ -0,0 +1,73 @@ +From 4e6bf609569c59b6bd6acf4a607c096cbd820d79 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:03 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: cache HW pointer of last freed TX + descriptor + +The value is only updated by the CPU, so it is cheaper to access from the +ring data structure than from a hardware register. + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++ + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1385,7 +1385,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + struct mtk_tx_buf *tx_buf; + u32 cpu, dma; + +- cpu = mtk_r32(eth, MTK_QTX_CRX_PTR); ++ cpu = ring->last_free_ptr; + dma = mtk_r32(eth, MTK_QTX_DRX_PTR); + + desc = mtk_qdma_phys_to_virt(ring, cpu); +@@ -1419,6 +1419,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + cpu = next_cpu; + } + ++ ring->last_free_ptr = cpu; + mtk_w32(eth, cpu, MTK_QTX_CRX_PTR); + + return budget; +@@ -1619,6 +1620,7 @@ static int mtk_tx_alloc(struct mtk_eth * + atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); + ring->next_free = &ring->dma[0]; + ring->last_free = &ring->dma[MTK_DMA_SIZE - 1]; ++ ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); + ring->thresh = MAX_SKB_FRAGS; + + /* make sure that all changes to the dma ring are flushed before we +@@ -1632,9 +1634,7 @@ static int mtk_tx_alloc(struct mtk_eth * + mtk_w32(eth, + ring->phys + ((MTK_DMA_SIZE - 1) * sz), + MTK_QTX_CRX_PTR); +- mtk_w32(eth, +- ring->phys + ((MTK_DMA_SIZE - 1) * sz), +- MTK_QTX_DRX_PTR); ++ mtk_w32(eth, ring->last_free_ptr, MTK_QTX_DRX_PTR); + mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, + MTK_QTX_CFG(0)); + } else { +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -656,6 +656,7 @@ struct mtk_tx_buf { + * @phys: The physical addr of tx_buf + * @next_free: Pointer to the next free descriptor + * @last_free: Pointer to the last free descriptor ++ * @last_free_ptr: Hardware pointer value of the last free descriptor + * @thresh: The threshold of minimum amount of free descriptors + * @free_count: QDMA uses a linked list. Track how many free descriptors + * are present +@@ -666,6 +667,7 @@ struct mtk_tx_ring { + dma_addr_t phys; + struct mtk_tx_dma *next_free; + struct mtk_tx_dma *last_free; ++ u32 last_free_ptr; + u16 thresh; + atomic_t free_count; + int dma_size; diff --git a/target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch b/target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch new file mode 100644 index 0000000000..09b8b3afb9 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch @@ -0,0 +1,49 @@ +From 816ac3e6e67bdd78d86226c6eb53619780750e92 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:04 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: only read the full RX descriptor + if DMA is done + +Uncached memory access is expensive, and there is no need to access all +descriptor words if we can't process them anyway + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -798,13 +798,18 @@ static inline int mtk_max_buf_size(int f + return buf_size; + } + +-static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd, ++static inline bool mtk_rx_get_desc(struct mtk_rx_dma *rxd, + struct mtk_rx_dma *dma_rxd) + { +- rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd2 = READ_ONCE(dma_rxd->rxd2); ++ if (!(rxd->rxd2 & RX_DMA_DONE)) ++ return false; ++ ++ rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); ++ ++ return true; + } + + /* the qdma core needs scratch memory to be setup */ +@@ -1276,8 +1281,7 @@ static int mtk_poll_rx(struct napi_struc + rxd = &ring->dma[idx]; + data = ring->data[idx]; + +- mtk_rx_get_desc(&trxd, rxd); +- if (!(trxd.rxd2 & RX_DMA_DONE)) ++ if (!mtk_rx_get_desc(&trxd, rxd)) + break; + + /* find out which mac the packet come from. values start at 1 */ diff --git a/target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch b/target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch new file mode 100644 index 0000000000..411374c2e7 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch @@ -0,0 +1,39 @@ +From 16769a8923fad5a5377253bcd76b0e0d64976c73 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:05 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: reduce unnecessary interrupts + +Avoid rearming interrupt if napi_complete returns false + +Signed-off-by: Felix Fietkau +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1540,8 +1540,8 @@ static int mtk_napi_tx(struct napi_struc + if (status & MTK_TX_DONE_INT) + return budget; + +- napi_complete(napi); +- mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); ++ if (napi_complete(napi)) ++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); + + return tx_done; + } +@@ -1574,8 +1574,9 @@ poll_again: + remain_budget -= rx_done; + goto poll_again; + } +- napi_complete(napi); +- mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); ++ ++ if (napi_complete(napi)) ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); + + return rx_done + budget - remain_budget; + } diff --git a/target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch b/target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch new file mode 100644 index 0000000000..d0926325d9 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch @@ -0,0 +1,110 @@ +From db2c7b353db3b3f71b55f9ff4627d8a786446fbe Mon Sep 17 00:00:00 2001 +From: Ilya Lipnitskiy +Date: Thu, 22 Apr 2021 22:21:06 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: rework NAPI callbacks + +Use napi_complete_done to communicate total TX and RX work done to NAPI. +Count total RX work up instead of remaining work down for clarity. +Remove unneeded local variables for clarity. Use do {} while instead of +goto for clarity. + +Suggested-by: Jakub Kicinski +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 54 +++++++++------------ + 1 file changed, 24 insertions(+), 30 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1517,7 +1517,6 @@ static void mtk_handle_status_irq(struct + static int mtk_napi_tx(struct napi_struct *napi, int budget) + { + struct mtk_eth *eth = container_of(napi, struct mtk_eth, tx_napi); +- u32 status, mask; + int tx_done = 0; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +@@ -1526,21 +1525,19 @@ static int mtk_napi_tx(struct napi_struc + tx_done = mtk_poll_tx(eth, budget); + + if (unlikely(netif_msg_intr(eth))) { +- status = mtk_r32(eth, eth->tx_int_status_reg); +- mask = mtk_r32(eth, eth->tx_int_mask_reg); + dev_info(eth->dev, +- "done tx %d, intr 0x%08x/0x%x\n", +- tx_done, status, mask); ++ "done tx %d, intr 0x%08x/0x%x\n", tx_done, ++ mtk_r32(eth, eth->tx_int_status_reg), ++ mtk_r32(eth, eth->tx_int_mask_reg)); + } + + if (tx_done == budget) + return budget; + +- status = mtk_r32(eth, eth->tx_int_status_reg); +- if (status & MTK_TX_DONE_INT) ++ if (mtk_r32(eth, eth->tx_int_status_reg) & MTK_TX_DONE_INT) + return budget; + +- if (napi_complete(napi)) ++ if (napi_complete_done(napi, tx_done)) + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); + + return tx_done; +@@ -1549,36 +1546,33 @@ static int mtk_napi_tx(struct napi_struc + static int mtk_napi_rx(struct napi_struct *napi, int budget) + { + struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi); +- u32 status, mask; +- int rx_done = 0; +- int remain_budget = budget; ++ int rx_done_total = 0; + + mtk_handle_status_irq(eth); + +-poll_again: +- mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS); +- rx_done = mtk_poll_rx(napi, remain_budget, eth); ++ do { ++ int rx_done; + +- if (unlikely(netif_msg_intr(eth))) { +- status = mtk_r32(eth, MTK_PDMA_INT_STATUS); +- mask = mtk_r32(eth, MTK_PDMA_INT_MASK); +- dev_info(eth->dev, +- "done rx %d, intr 0x%08x/0x%x\n", +- rx_done, status, mask); +- } +- if (rx_done == remain_budget) +- return budget; ++ mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS); ++ rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); ++ rx_done_total += rx_done; ++ ++ if (unlikely(netif_msg_intr(eth))) { ++ dev_info(eth->dev, ++ "done rx %d, intr 0x%08x/0x%x\n", rx_done, ++ mtk_r32(eth, MTK_PDMA_INT_STATUS), ++ mtk_r32(eth, MTK_PDMA_INT_MASK)); ++ } + +- status = mtk_r32(eth, MTK_PDMA_INT_STATUS); +- if (status & MTK_RX_DONE_INT) { +- remain_budget -= rx_done; +- goto poll_again; +- } ++ if (rx_done_total == budget) ++ return budget; ++ ++ } while (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT); + +- if (napi_complete(napi)) ++ if (napi_complete_done(napi, rx_done_total)) + mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); + +- return rx_done + budget - remain_budget; ++ return rx_done_total; + } + + static int mtk_tx_alloc(struct mtk_eth *eth) diff --git a/target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch b/target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch new file mode 100644 index 0000000000..ab298ec42b --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch @@ -0,0 +1,47 @@ +From fa817272c37ef78e25dc14e4760ac78a7043a18a Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 22 Apr 2021 22:21:07 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: set PPE flow hash as skb hash if + present + +This improves GRO performance + +Signed-off-by: Felix Fietkau +[Ilya: Use MTK_RXD4_FOE_ENTRY instead of GENMASK(13, 0)] +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + + #include "mtk_eth_soc.h" +@@ -1271,6 +1272,7 @@ static int mtk_poll_rx(struct napi_struc + struct net_device *netdev; + unsigned int pktlen; + dma_addr_t dma_addr; ++ u32 hash; + int mac; + + ring = mtk_get_rx_ring(eth); +@@ -1340,6 +1342,12 @@ static int mtk_poll_rx(struct napi_struc + skb->protocol = eth_type_trans(skb, netdev); + bytes += pktlen; + ++ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; ++ if (hash != MTK_RXD4_FOE_ENTRY) { ++ hash = jhash_1word(hash, 0); ++ skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); ++ } ++ + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && + (trxd.rxd2 & RX_DMA_VTAG)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), diff --git a/target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch b/target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch new file mode 100644 index 0000000000..26bb33e42c --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch @@ -0,0 +1,71 @@ +From 3bc8e0aff23be0526af0dbc7973a8866a08d73f1 Mon Sep 17 00:00:00 2001 +From: Ilya Lipnitskiy +Date: Thu, 22 Apr 2021 22:21:08 -0700 +Subject: [PATCH] net: ethernet: mtk_eth_soc: use iopoll.h macro for DMA init + +Replace a tight busy-wait loop without a pause with a standard +readx_poll_timeout_atomic routine with a 5 us poll period. + +Tested by booting a MT7621 device to ensure the driver initializes +properly. + +Signed-off-by: Ilya Lipnitskiy +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 29 +++++++++------------ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + 2 files changed, 14 insertions(+), 17 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2054,25 +2054,22 @@ static int mtk_set_features(struct net_d + /* wait for DMA to finish whatever it is doing before we start using it again */ + static int mtk_dma_busy_wait(struct mtk_eth *eth) + { +- unsigned long t_start = jiffies; ++ unsigned int reg; ++ int ret; ++ u32 val; + +- while (1) { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { +- if (!(mtk_r32(eth, MTK_QDMA_GLO_CFG) & +- (MTK_RX_DMA_BUSY | MTK_TX_DMA_BUSY))) +- return 0; +- } else { +- if (!(mtk_r32(eth, MTK_PDMA_GLO_CFG) & +- (MTK_RX_DMA_BUSY | MTK_TX_DMA_BUSY))) +- return 0; +- } ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) ++ reg = MTK_QDMA_GLO_CFG; ++ else ++ reg = MTK_PDMA_GLO_CFG; + +- if (time_after(jiffies, t_start + MTK_DMA_BUSY_TIMEOUT)) +- break; +- } ++ ret = readx_poll_timeout_atomic(__raw_readl, eth->base + reg, val, ++ !(val & (MTK_RX_DMA_BUSY | MTK_TX_DMA_BUSY)), ++ 5, MTK_DMA_BUSY_TIMEOUT_US); ++ if (ret) ++ dev_err(eth->dev, "DMA init timeout\n"); + +- dev_err(eth->dev, "DMA init timeout\n"); +- return -1; ++ return ret; + } + + static int mtk_dma_init(struct mtk_eth *eth) +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -213,7 +213,7 @@ + #define MTK_TX_DMA_BUSY BIT(1) + #define MTK_RX_DMA_EN BIT(2) + #define MTK_TX_DMA_EN BIT(0) +-#define MTK_DMA_BUSY_TIMEOUT HZ ++#define MTK_DMA_BUSY_TIMEOUT_US 1000000 + + /* QDMA Reset Index Register */ + #define MTK_QDMA_RST_IDX 0x1A08 diff --git a/target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch b/target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch new file mode 100644 index 0000000000..a846ce43e2 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch @@ -0,0 +1,63 @@ +From: Pablo Neira Ayuso +Date: Sun, 18 Apr 2021 23:11:44 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: missing mutex + +Patch 2ed37183abb7 ("netfilter: flowtable: separate replace, destroy and +stats to different workqueues") splits the workqueue per event type. Add +a mutex to serialize updates. + +Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support") +Reported-by: Frank Wunderlich +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -392,6 +392,8 @@ mtk_flow_offload_stats(struct mtk_eth *e + return 0; + } + ++static DEFINE_MUTEX(mtk_flow_offload_mutex); ++ + static int + mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) + { +@@ -399,6 +401,7 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ + struct net_device *dev = cb_priv; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; ++ int err; + + if (!tc_can_offload(dev)) + return -EOPNOTSUPP; +@@ -406,18 +409,24 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ + if (type != TC_SETUP_CLSFLOWER) + return -EOPNOTSUPP; + ++ mutex_lock(&mtk_flow_offload_mutex); + switch (cls->command) { + case FLOW_CLS_REPLACE: +- return mtk_flow_offload_replace(eth, cls); ++ err = mtk_flow_offload_replace(eth, cls); ++ break; + case FLOW_CLS_DESTROY: +- return mtk_flow_offload_destroy(eth, cls); ++ err = mtk_flow_offload_destroy(eth, cls); ++ break; + case FLOW_CLS_STATS: +- return mtk_flow_offload_stats(eth, cls); ++ err = mtk_flow_offload_stats(eth, cls); ++ break; + default: +- return -EOPNOTSUPP; ++ err = -EOPNOTSUPP; ++ break; + } ++ mutex_unlock(&mtk_flow_offload_mutex); + +- return 0; ++ return err; + } + + static int diff --git a/target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch b/target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch new file mode 100644 index 0000000000..806fd0dcdf --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch @@ -0,0 +1,22 @@ +From: Pablo Neira Ayuso +Date: Sun, 18 Apr 2021 23:11:45 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: handle VLAN pop action + +Do not hit EOPNOTSUPP when flowtable offload provides a VLAN pop action. + +Fixes: efce49dfe6a8 ("netfilter: flowtable: add vlan pop action offload support") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -233,6 +233,8 @@ mtk_flow_offload_replace(struct mtk_eth + data.vlan.proto = act->vlan.proto; + data.vlan.num++; + break; ++ case FLOW_ACTION_VLAN_POP: ++ break; + case FLOW_ACTION_PPPOE_PUSH: + if (data.pppoe.num == 1) + return -EOPNOTSUPP; diff --git a/target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch b/target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch new file mode 100644 index 0000000000..42b55f021a --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch @@ -0,0 +1,159 @@ +From: Pablo Neira Ayuso +Date: Sun, 28 Mar 2021 23:08:55 +0200 +Subject: [PATCH] netfilter: flowtable: dst_check() from garbage collector path + +Move dst_check() to the garbage collector path. Stale routes trigger the +flow entry teardown state which makes affected flows go back to the +classic forwarding path to re-evaluate flow offloading. + +IPv6 requires the dst cookie to work, store it in the flow_tuple, +otherwise dst_check() always fails. + +Fixes: e5075c0badaa ("netfilter: flowtable: call dst_check() to fall back to classic forwarding") +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -129,7 +129,10 @@ struct flow_offload_tuple { + in_vlan_ingress:2; + u16 mtu; + union { +- struct dst_entry *dst_cache; ++ struct { ++ struct dst_entry *dst_cache; ++ u32 dst_cookie; ++ }; + struct { + u32 ifidx; + u32 hw_ifidx; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -74,6 +74,18 @@ err_ct_refcnt: + } + EXPORT_SYMBOL_GPL(flow_offload_alloc); + ++static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple) ++{ ++ const struct rt6_info *rt; ++ ++ if (flow_tuple->l3proto == NFPROTO_IPV6) { ++ rt = (const struct rt6_info *)flow_tuple->dst_cache; ++ return rt6_get_cookie(rt); ++ } ++ ++ return 0; ++} ++ + static int flow_offload_fill_route(struct flow_offload *flow, + const struct nf_flow_route *route, + enum flow_offload_tuple_dir dir) +@@ -116,6 +128,7 @@ static int flow_offload_fill_route(struc + return -1; + + flow_tuple->dst_cache = dst; ++ flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple); + break; + } + flow_tuple->xmit_type = route->tuple[dir].xmit_type; +@@ -389,11 +402,33 @@ nf_flow_table_iterate(struct nf_flowtabl + return err; + } + ++static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple) ++{ ++ struct dst_entry *dst; ++ ++ if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || ++ tuple->xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { ++ dst = tuple->dst_cache; ++ if (!dst_check(dst, tuple->dst_cookie)) ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool nf_flow_has_stale_dst(struct flow_offload *flow) ++{ ++ return flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple) || ++ flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple); ++} ++ + static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data) + { + struct nf_flowtable *flow_table = data; + +- if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct)) ++ if (nf_flow_has_expired(flow) || ++ nf_ct_is_dying(flow->ct) || ++ nf_flow_has_stale_dst(flow)) + set_bit(NF_FLOW_TEARDOWN, &flow->flags); + + if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) { +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -364,15 +364,6 @@ nf_flow_offload_ip_hook(void *priv, stru + if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) + return NF_ACCEPT; + +- if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || +- tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { +- rt = (struct rtable *)tuplehash->tuple.dst_cache; +- if (!dst_check(&rt->dst, 0)) { +- flow_offload_teardown(flow); +- return NF_ACCEPT; +- } +- } +- + if (skb_try_make_writable(skb, thoff + hdrsize)) + return NF_DROP; + +@@ -391,6 +382,7 @@ nf_flow_offload_ip_hook(void *priv, stru + nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); + + if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { ++ rt = (struct rtable *)tuplehash->tuple.dst_cache; + memset(skb->cb, 0, sizeof(struct inet_skb_parm)); + IPCB(skb)->iif = skb->dev->ifindex; + IPCB(skb)->flags = IPSKB_FORWARDED; +@@ -399,6 +391,7 @@ nf_flow_offload_ip_hook(void *priv, stru + + switch (tuplehash->tuple.xmit_type) { + case FLOW_OFFLOAD_XMIT_NEIGH: ++ rt = (struct rtable *)tuplehash->tuple.dst_cache; + outdev = rt->dst.dev; + skb->dev = outdev; + nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +@@ -607,15 +600,6 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff)) + return NF_ACCEPT; + +- if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || +- tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { +- rt = (struct rt6_info *)tuplehash->tuple.dst_cache; +- if (!dst_check(&rt->dst, 0)) { +- flow_offload_teardown(flow); +- return NF_ACCEPT; +- } +- } +- + if (skb_try_make_writable(skb, thoff + hdrsize)) + return NF_DROP; + +@@ -633,6 +617,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); + + if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { ++ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + IP6CB(skb)->iif = skb->dev->ifindex; + IP6CB(skb)->flags = IP6SKB_FORWARDED; +@@ -641,6 +626,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + + switch (tuplehash->tuple.xmit_type) { + case FLOW_OFFLOAD_XMIT_NEIGH: ++ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; + outdev = rt->dst.dev; + skb->dev = outdev; + nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); diff --git a/target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch b/target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch new file mode 100644 index 0000000000..e5a346cac4 --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch @@ -0,0 +1,94 @@ +From: Oz Shlomo +Date: Thu, 3 Jun 2021 15:12:33 +0300 +Subject: [PATCH] netfilter: conntrack: Introduce tcp offload timeout + configuration + +TCP connections may be offloaded from nf conntrack to nf flow table. +Offloaded connections are aged after 30 seconds of inactivity. +Once aged, ownership is returned to conntrack with a hard coded pickup +time of 120 seconds, after which the connection may be deleted. +eted. The current aging intervals may be too aggressive for some users. + +Provide users with the ability to control the nf flow table offload +aging and pickup time intervals via sysctl parameter as a pre-step for +configuring the nf flow table GC timeout intervals. + +Signed-off-by: Oz Shlomo +Reviewed-by: Paul Blakey +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netns/conntrack.h ++++ b/include/net/netns/conntrack.h +@@ -27,6 +27,10 @@ struct nf_tcp_net { + int tcp_loose; + int tcp_be_liberal; + int tcp_max_retrans; ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ unsigned int offload_timeout; ++ unsigned int offload_pickup; ++#endif + }; + + enum udp_conntrack { +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1438,6 +1438,11 @@ void nf_conntrack_tcp_init_net(struct ne + tn->tcp_loose = nf_ct_tcp_loose; + tn->tcp_be_liberal = nf_ct_tcp_be_liberal; + tn->tcp_max_retrans = nf_ct_tcp_max_retrans; ++ ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ tn->offload_timeout = 30 * HZ; ++ tn->offload_pickup = 120 * HZ; ++#endif + } + + const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp = +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -567,6 +567,10 @@ enum nf_ct_sysctl_index { + NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE, + NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_RETRANS, + NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK, ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD, ++ NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP, ++#endif + NF_SYSCTL_CT_PROTO_TCP_LOOSE, + NF_SYSCTL_CT_PROTO_TCP_LIBERAL, + NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS, +@@ -758,6 +762,20 @@ static struct ctl_table nf_ct_sysctl_tab + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD] = { ++ .procname = "nf_flowtable_tcp_timeout", ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++ [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP] = { ++ .procname = "nf_flowtable_tcp_pickup", ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++#endif + [NF_SYSCTL_CT_PROTO_TCP_LOOSE] = { + .procname = "nf_conntrack_tcp_loose", + .maxlen = sizeof(int), +@@ -967,6 +985,12 @@ static void nf_conntrack_standalone_init + XASSIGN(LIBERAL, &tn->tcp_be_liberal); + XASSIGN(MAX_RETRANS, &tn->tcp_max_retrans); + #undef XASSIGN ++ ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD].data = &tn->offload_timeout; ++ table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP].data = &tn->offload_pickup; ++#endif ++ + } + + static void nf_conntrack_standalone_init_sctp_sysctl(struct net *net, diff --git a/target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch b/target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch new file mode 100644 index 0000000000..416e20356d --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch @@ -0,0 +1,92 @@ +From: Oz Shlomo +Date: Thu, 3 Jun 2021 15:12:34 +0300 +Subject: [PATCH] netfilter: conntrack: Introduce udp offload timeout + configuration + +UDP connections may be offloaded from nf conntrack to nf flow table. +Offloaded connections are aged after 30 seconds of inactivity. +Once aged, ownership is returned to conntrack with a hard coded pickup +time of 30 seconds, after which the connection may be deleted. +eted. The current aging intervals may be too aggressive for some users. + +Provide users with the ability to control the nf flow table offload +aging and pickup time intervals via sysctl parameter as a pre-step for +configuring the nf flow table GC timeout intervals. + +Signed-off-by: Oz Shlomo +Reviewed-by: Paul Blakey +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netns/conntrack.h ++++ b/include/net/netns/conntrack.h +@@ -41,6 +41,10 @@ enum udp_conntrack { + + struct nf_udp_net { + unsigned int timeouts[UDP_CT_MAX]; ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ unsigned int offload_timeout; ++ unsigned int offload_pickup; ++#endif + }; + + struct nf_icmp_net { +--- a/net/netfilter/nf_conntrack_proto_udp.c ++++ b/net/netfilter/nf_conntrack_proto_udp.c +@@ -273,6 +273,11 @@ void nf_conntrack_udp_init_net(struct ne + + for (i = 0; i < UDP_CT_MAX; i++) + un->timeouts[i] = udp_timeouts[i]; ++ ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ un->offload_timeout = 30 * HZ; ++ un->offload_pickup = 30 * HZ; ++#endif + } + + const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp = +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -576,6 +576,10 @@ enum nf_ct_sysctl_index { + NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS, + NF_SYSCTL_CT_PROTO_TIMEOUT_UDP, + NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM, ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD, ++ NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP, ++#endif + NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP, + NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6, + #ifdef CONFIG_NF_CT_PROTO_SCTP +@@ -810,6 +814,20 @@ static struct ctl_table nf_ct_sysctl_tab + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, ++#if IS_ENABLED(CONFIG_NFT_FLOW_OFFLOAD) ++ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD] = { ++ .procname = "nf_flowtable_udp_timeout", ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP] = { ++ .procname = "nf_flowtable_udp_pickup", ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++#endif + [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP] = { + .procname = "nf_conntrack_icmp_timeout", + .maxlen = sizeof(unsigned int), +@@ -1078,6 +1096,10 @@ static int nf_conntrack_standalone_init_ + table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout; + table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP].data = &un->timeouts[UDP_CT_UNREPLIED]; + table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM].data = &un->timeouts[UDP_CT_REPLIED]; ++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) ++ table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD].data = &un->offload_timeout; ++ table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP].data = &un->offload_pickup; ++#endif + + nf_conntrack_standalone_init_tcp_sysctl(net, table); + nf_conntrack_standalone_init_sctp_sysctl(net, table); diff --git a/target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch b/target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch new file mode 100644 index 0000000000..1e82308eaa --- /dev/null +++ b/target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch @@ -0,0 +1,134 @@ +From: Oz Shlomo +Date: Thu, 3 Jun 2021 15:12:35 +0300 +Subject: [PATCH] netfilter: flowtable: Set offload timeouts according to proto + values + +Currently the aging period for tcp/udp connections is hard coded to +30 seconds. Aged tcp/udp connections configure a hard coded 120/30 +seconds pickup timeout for conntrack. +This configuration may be too aggressive or permissive for some users. + +Dynamically configure the nf flow table GC timeout intervals according +to the user defined values. + +Signed-off-by: Oz Shlomo +Reviewed-by: Paul Blakey +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -174,6 +174,8 @@ struct flow_offload { + #define NF_FLOW_TIMEOUT (30 * HZ) + #define nf_flowtable_time_stamp (u32)jiffies + ++unsigned long flow_offload_get_timeout(struct flow_offload *flow); ++ + static inline __s32 nf_flow_timeout_delta(unsigned int timeout) + { + return (__s32)(timeout - nf_flowtable_time_stamp); +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -175,12 +175,10 @@ static void flow_offload_fixup_tcp(struc + tcp->seen[1].td_maxwin = 0; + } + +-#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ) +-#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ) +- + static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) + { + const struct nf_conntrack_l4proto *l4proto; ++ struct net *net = nf_ct_net(ct); + int l4num = nf_ct_protonum(ct); + unsigned int timeout; + +@@ -188,12 +186,17 @@ static void flow_offload_fixup_ct_timeou + if (!l4proto) + return; + +- if (l4num == IPPROTO_TCP) +- timeout = NF_FLOWTABLE_TCP_PICKUP_TIMEOUT; +- else if (l4num == IPPROTO_UDP) +- timeout = NF_FLOWTABLE_UDP_PICKUP_TIMEOUT; +- else ++ if (l4num == IPPROTO_TCP) { ++ struct nf_tcp_net *tn = nf_tcp_pernet(net); ++ ++ timeout = tn->offload_pickup; ++ } else if (l4num == IPPROTO_UDP) { ++ struct nf_udp_net *tn = nf_udp_pernet(net); ++ ++ timeout = tn->offload_pickup; ++ } else { + return; ++ } + + if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout) + WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout); +@@ -265,11 +268,35 @@ static const struct rhashtable_params nf + .automatic_shrinking = true, + }; + ++unsigned long flow_offload_get_timeout(struct flow_offload *flow) ++{ ++ const struct nf_conntrack_l4proto *l4proto; ++ unsigned long timeout = NF_FLOW_TIMEOUT; ++ struct net *net = nf_ct_net(flow->ct); ++ int l4num = nf_ct_protonum(flow->ct); ++ ++ l4proto = nf_ct_l4proto_find(l4num); ++ if (!l4proto) ++ return timeout; ++ ++ if (l4num == IPPROTO_TCP) { ++ struct nf_tcp_net *tn = nf_tcp_pernet(net); ++ ++ timeout = tn->offload_timeout; ++ } else if (l4num == IPPROTO_UDP) { ++ struct nf_udp_net *tn = nf_udp_pernet(net); ++ ++ timeout = tn->offload_timeout; ++ } ++ ++ return timeout; ++} ++ + int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) + { + int err; + +- flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT; ++ flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); + + err = rhashtable_insert_fast(&flow_table->rhashtable, + &flow->tuplehash[0].node, +@@ -301,7 +328,7 @@ EXPORT_SYMBOL_GPL(flow_offload_add); + void flow_offload_refresh(struct nf_flowtable *flow_table, + struct flow_offload *flow) + { +- flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT; ++ flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); + + if (likely(!nf_flowtable_hw_offload(flow_table))) + return; +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -885,7 +885,7 @@ static void flow_offload_work_stats(stru + + lastused = max_t(u64, stats[0].lastused, stats[1].lastused); + offload->flow->timeout = max_t(u64, offload->flow->timeout, +- lastused + NF_FLOW_TIMEOUT); ++ lastused + flow_offload_get_timeout(offload->flow)); + + if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) { + if (stats[0].pkts) +@@ -989,7 +989,7 @@ void nf_flow_offload_stats(struct nf_flo + __s32 delta; + + delta = nf_flow_timeout_delta(flow->timeout); +- if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10)) ++ if ((delta >= (9 * flow_offload_get_timeout(flow)) / 10)) + return; + + offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS); diff --git a/target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch b/target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch new file mode 100644 index 0000000000..289d140f34 --- /dev/null +++ b/target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch @@ -0,0 +1,138 @@ +From 4fd59792097a6b2fb949d41264386a7ecade469e Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Mon, 25 Jan 2021 12:20:46 +0800 +Subject: [PATCH] net: ethernet: mediatek: support setting MTU + +MT762x HW, except for MT7628, supports frame length up to 2048 +(maximum length on GDM), so allow setting MTU up to 2030. + +Also set the default frame length to the hardware default 1518. + +Signed-off-by: DENG Qingfang +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20210125042046.5599-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 43 ++++++++++++++++++--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++++-- + 2 files changed, 47 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -355,7 +355,7 @@ static void mtk_mac_config(struct phylin + /* Setup gmac */ + mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr_new = mcr_cur; +- mcr_new |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | ++ mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | + MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK; + + /* Only update control register when needed! */ +@@ -782,8 +782,8 @@ static void mtk_get_stats64(struct net_d + static inline int mtk_max_frag_size(int mtu) + { + /* make sure buf_size will be at least MTK_MAX_RX_LENGTH */ +- if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH) +- mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; ++ if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH_2K) ++ mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; + + return SKB_DATA_ALIGN(MTK_RX_HLEN + mtu) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); +@@ -794,7 +794,7 @@ static inline int mtk_max_buf_size(int f + int buf_size = frag_size - NET_SKB_PAD - NET_IP_ALIGN - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + +- WARN_ON(buf_size < MTK_MAX_RX_LENGTH); ++ WARN_ON(buf_size < MTK_MAX_RX_LENGTH_2K); + + return buf_size; + } +@@ -2606,6 +2606,35 @@ static void mtk_uninit(struct net_device + mtk_rx_irq_disable(eth, ~0); + } + ++static int mtk_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ int length = new_mtu + MTK_RX_ETH_HLEN; ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ u32 mcr_cur, mcr_new; ++ ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { ++ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); ++ mcr_new = mcr_cur & ~MAC_MCR_MAX_RX_MASK; ++ ++ if (length <= 1518) ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1518); ++ else if (length <= 1536) ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1536); ++ else if (length <= 1552) ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1552); ++ else ++ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_2048); ++ ++ if (mcr_new != mcr_cur) ++ mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); ++ } ++ ++ dev->mtu = new_mtu; ++ ++ return 0; ++} ++ + static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct mtk_mac *mac = netdev_priv(dev); +@@ -2902,6 +2931,7 @@ static const struct net_device_ops mtk_n + .ndo_set_mac_address = mtk_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = mtk_do_ioctl, ++ .ndo_change_mtu = mtk_change_mtu, + .ndo_tx_timeout = mtk_tx_timeout, + .ndo_get_stats64 = mtk_get_stats64, + .ndo_fix_features = mtk_fix_features, +@@ -3004,7 +3034,10 @@ static int mtk_add_mac(struct mtk_eth *e + eth->netdev[id]->irq = eth->irq[0]; + eth->netdev[id]->dev.of_node = np; + +- eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) ++ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; ++ else ++ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; + + return 0; + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -20,12 +20,13 @@ + #include "mtk_ppe.h" + + #define MTK_QDMA_PAGE_SIZE 2048 +-#define MTK_MAX_RX_LENGTH 1536 ++#define MTK_MAX_RX_LENGTH 1536 ++#define MTK_MAX_RX_LENGTH_2K 2048 + #define MTK_TX_DMA_BUF_LEN 0x3fff + #define MTK_DMA_SIZE 512 + #define MTK_NAPI_WEIGHT 64 + #define MTK_MAC_COUNT 2 +-#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) ++#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) + #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) + #define MTK_DMA_DUMMY_DESC 0xffffffff + #define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \ +@@ -352,7 +353,12 @@ + + /* Mac control registers */ + #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100)) +-#define MAC_MCR_MAX_RX_1536 BIT(24) ++#define MAC_MCR_MAX_RX_MASK GENMASK(25, 24) ++#define MAC_MCR_MAX_RX(_x) (MAC_MCR_MAX_RX_MASK & ((_x) << 24)) ++#define MAC_MCR_MAX_RX_1518 0x0 ++#define MAC_MCR_MAX_RX_1536 0x1 ++#define MAC_MCR_MAX_RX_1552 0x2 ++#define MAC_MCR_MAX_RX_2048 0x3 + #define MAC_MCR_IPG_CFG (BIT(18) | BIT(16)) + #define MAC_MCR_FORCE_MODE BIT(15) + #define MAC_MCR_TX_EN BIT(14) diff --git a/target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch b/target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch new file mode 100644 index 0000000000..00be403299 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch @@ -0,0 +1,108 @@ +From c329e5afb42ff0a88285eb4d8a391a18793e4777 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Thu, 15 Apr 2021 03:26:50 +0200 +Subject: [PATCH] net: phy: at803x: select correct page on config init + +The Atheros AR8031 and AR8033 expose different registers for SGMII/Fiber +as well as the copper side of the PHY depending on the BT_BX_REG_SEL bit +in the chip configure register. + +The driver assumes the copper side is selected on probe, but this might +not be the case depending which page was last selected by the +bootloader. Notably, Ubiquiti UniFi bootloaders show this behavior. + +Select the copper page when probing to circumvent this. + +Signed-off-by: David Bauer +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 49 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -139,6 +139,9 @@ + #define ATH8035_PHY_ID 0x004dd072 + #define AT8030_PHY_ID_MASK 0xffffffef + ++#define AT803X_PAGE_FIBER 0 ++#define AT803X_PAGE_COPPER 1 ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -190,6 +193,35 @@ static int at803x_debug_reg_mask(struct + return phy_write(phydev, AT803X_DEBUG_DATA, val); + } + ++static int at803x_write_page(struct phy_device *phydev, int page) ++{ ++ int mask; ++ int set; ++ ++ if (page == AT803X_PAGE_COPPER) { ++ set = AT803X_BT_BX_REG_SEL; ++ mask = 0; ++ } else { ++ set = 0; ++ mask = AT803X_BT_BX_REG_SEL; ++ } ++ ++ return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set); ++} ++ ++static int at803x_read_page(struct phy_device *phydev) ++{ ++ int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ ++ if (ccr < 0) ++ return ccr; ++ ++ if (ccr & AT803X_BT_BX_REG_SEL) ++ return AT803X_PAGE_COPPER; ++ ++ return AT803X_PAGE_FIBER; ++} ++ + static int at803x_enable_rx_delay(struct phy_device *phydev) + { + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, +@@ -508,6 +540,7 @@ static int at803x_probe(struct phy_devic + { + struct device *dev = &phydev->mdio.dev; + struct at803x_priv *priv; ++ int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -515,7 +548,20 @@ static int at803x_probe(struct phy_devic + + phydev->priv = priv; + +- return at803x_parse_dt(phydev); ++ ret = at803x_parse_dt(phydev); ++ if (ret) ++ return ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the copper page, as otherwise we read ++ * the PHY capabilities from the fiber side. ++ */ ++ if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) { ++ ret = phy_select_page(phydev, AT803X_PAGE_COPPER); ++ ret = phy_restore_page(phydev, AT803X_PAGE_COPPER, ret); ++ } ++ ++ return ret; + } + + static void at803x_remove(struct phy_device *phydev) +@@ -1097,6 +1143,8 @@ static struct phy_driver at803x_driver[] + .get_wol = at803x_get_wol, + .suspend = at803x_suspend, + .resume = at803x_resume, ++ .read_page = at803x_read_page, ++ .write_page = at803x_write_page, + /* PHY_GBIT_FEATURES */ + .read_status = at803x_read_status, + .aneg_done = at803x_aneg_done, diff --git a/target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch b/target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch new file mode 100644 index 0000000000..d6ec7450e8 --- /dev/null +++ b/target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch @@ -0,0 +1,73 @@ +From 8f7e876273e294b732b42af2e5e6bba91d798954 Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Tue, 20 Apr 2021 12:29:29 +0200 +Subject: [PATCH] net: phy: at803x: fix probe error if copper page is selected + +The commit c329e5afb42f ("net: phy: at803x: select correct page on +config init") selects the copper page during probe. This fails if the +copper page was already selected. In this case, the value of the copper +page (which is 1) is propagated through phy_restore_page() and is +finally returned for at803x_probe(). Fix it, by just using the +at803x_page_write() directly. + +Also in case of an error, the regulator is not disabled and leads to a +WARN_ON() when the probe fails. This couldn't happen before, because +at803x_parse_dt() was the last call in at803x_probe(). It is hard to +see, that the parse_dt() actually enables the regulator. Thus move the +regulator_enable() to the probe function and undo it in case of an +error. + +Fixes: c329e5afb42f ("net: phy: at803x: select correct page on config init") +Signed-off-by: Michael Walle +Reviewed-by: David Bauer +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -527,10 +527,6 @@ static int at803x_parse_dt(struct phy_de + phydev_err(phydev, "failed to get VDDIO regulator\n"); + return PTR_ERR(priv->vddio); + } +- +- ret = regulator_enable(priv->vddio); +- if (ret < 0) +- return ret; + } + + return 0; +@@ -552,15 +548,30 @@ static int at803x_probe(struct phy_devic + if (ret) + return ret; + ++ if (priv->vddio) { ++ ret = regulator_enable(priv->vddio); ++ if (ret < 0) ++ return ret; ++ } ++ + /* Some bootloaders leave the fiber page selected. + * Switch to the copper page, as otherwise we read + * the PHY capabilities from the fiber side. + */ + if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) { +- ret = phy_select_page(phydev, AT803X_PAGE_COPPER); +- ret = phy_restore_page(phydev, AT803X_PAGE_COPPER, ret); ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ goto err; + } + ++ return 0; ++ ++err: ++ if (priv->vddio) ++ regulator_disable(priv->vddio); ++ + return ret; + } + diff --git a/target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch b/target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch new file mode 100644 index 0000000000..5c7f97ea90 --- /dev/null +++ b/target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch @@ -0,0 +1,56 @@ +From b1ae3587d16a8c8fc9453e147c8708d6f006ffbb Mon Sep 17 00:00:00 2001 +From: Bjarni Jonasson +Date: Wed, 13 Jan 2021 12:56:25 +0100 +Subject: [PATCH] net: phy: Add 100 base-x mode + +Sparx-5 supports this mode and it is missing in the PHY core. + +Signed-off-by: Bjarni Jonasson +Reviewed-by: Russell King +Signed-off-by: Jakub Kicinski +--- + Documentation/networking/phy.rst | 5 +++++ + include/linux/phy.h | 4 ++++ + 2 files changed, 9 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -286,6 +286,11 @@ Some of the interface modes are describe + Note: due to legacy usage, some 10GBASE-R usage incorrectly makes + use of this definition. + ++``PHY_INTERFACE_MODE_100BASEX`` ++ This defines IEEE 802.3 Clause 24. The link operates at a fixed data ++ rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying ++ data rate of 100Mpbs. ++ + Pause frames / flow control + =========================== + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax + * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII + * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII ++ * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX + * @PHY_INTERFACE_MODE_1000BASEX: 1000 BaseX + * @PHY_INTERFACE_MODE_2500BASEX: 2500 BaseX + * @PHY_INTERFACE_MODE_RXAUI: Reduced XAUI +@@ -135,6 +136,7 @@ typedef enum { + PHY_INTERFACE_MODE_MOCA, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, ++ PHY_INTERFACE_MODE_100BASEX, + PHY_INTERFACE_MODE_1000BASEX, + PHY_INTERFACE_MODE_2500BASEX, + PHY_INTERFACE_MODE_RXAUI, +@@ -217,6 +219,8 @@ static inline const char *phy_modes(phy_ + return "usxgmii"; + case PHY_INTERFACE_MODE_10GKR: + return "10gbase-kr"; ++ case PHY_INTERFACE_MODE_100BASEX: ++ return "100base-x"; + default: + return "unknown"; + } diff --git a/target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch b/target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch new file mode 100644 index 0000000000..7d06c235d9 --- /dev/null +++ b/target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch @@ -0,0 +1,40 @@ +From 6e12f35cef6b8a458d7ecf507ae330e0bffaad8c Mon Sep 17 00:00:00 2001 +From: Bjarni Jonasson +Date: Wed, 13 Jan 2021 12:56:26 +0100 +Subject: [PATCH] sfp: add support for 100 base-x SFPs + +Add support for 100Base-FX, 100Base-LX, 100Base-PX and 100Base-BX10 modules +This is needed for Sparx-5 switch. + +Signed-off-by: Bjarni Jonasson +Reviewed-by: Russell King +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/sfp-bus.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -280,6 +280,12 @@ void sfp_parse_support(struct sfp_bus *b + br_min <= 1300 && br_max >= 1200) + phylink_set(modes, 1000baseX_Full); + ++ /* 100Base-FX, 100Base-LX, 100Base-PX, 100Base-BX10 */ ++ if (id->base.e100_base_fx || id->base.e100_base_lx) ++ phylink_set(modes, 100baseFX_Full); ++ if ((id->base.e_base_px || id->base.e_base_bx10) && br_nom == 100) ++ phylink_set(modes, 100baseFX_Full); ++ + /* For active or passive cables, select the link modes + * based on the bit rates and the cable compliance bytes. + */ +@@ -399,6 +405,9 @@ phy_interface_t sfp_select_interface(str + if (phylink_test(link_modes, 1000baseX_Full)) + return PHY_INTERFACE_MODE_1000BASEX; + ++ if (phylink_test(link_modes, 100baseFX_Full)) ++ return PHY_INTERFACE_MODE_100BASEX; ++ + dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n"); + + return PHY_INTERFACE_MODE_NA; diff --git a/target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch b/target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch new file mode 100644 index 0000000000..278df46313 --- /dev/null +++ b/target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch @@ -0,0 +1,549 @@ +From 41d26bf4aba070dfd2ab48866cc27a48ee6228c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Tue, 20 Apr 2021 09:53:59 +0200 +Subject: [PATCH] net: phy: marvell: refactor HWMON OOP style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use a structure of Marvell PHY specific HWMON methods to reduce code +duplication. Store a pointer to this structure into the PHY driver's +driver_data member. + +Signed-off-by: Marek Behún +Signed-off-by: David S. Miller +--- + drivers/net/phy/marvell.c | 369 +++++++++++++------------------------- + 1 file changed, 125 insertions(+), 244 deletions(-) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -2141,6 +2141,19 @@ static int marvell_vct7_cable_test_get_s + } + + #ifdef CONFIG_HWMON ++struct marvell_hwmon_ops { ++ int (*get_temp)(struct phy_device *phydev, long *temp); ++ int (*get_temp_critical)(struct phy_device *phydev, long *temp); ++ int (*set_temp_critical)(struct phy_device *phydev, long temp); ++ int (*get_temp_alarm)(struct phy_device *phydev, long *alarm); ++}; ++ ++static const struct marvell_hwmon_ops * ++to_marvell_hwmon_ops(const struct phy_device *phydev) ++{ ++ return phydev->drv->driver_data; ++} ++ + static int m88e1121_get_temp(struct phy_device *phydev, long *temp) + { + int oldpage; +@@ -2184,75 +2197,6 @@ error: + return phy_restore_page(phydev, oldpage, ret); + } + +-static int m88e1121_hwmon_read(struct device *dev, +- enum hwmon_sensor_types type, +- u32 attr, int channel, long *temp) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int err; +- +- switch (attr) { +- case hwmon_temp_input: +- err = m88e1121_get_temp(phydev, temp); +- break; +- default: +- return -EOPNOTSUPP; +- } +- +- return err; +-} +- +-static umode_t m88e1121_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) +-{ +- if (type != hwmon_temp) +- return 0; +- +- switch (attr) { +- case hwmon_temp_input: +- return 0444; +- default: +- return 0; +- } +-} +- +-static u32 m88e1121_hwmon_chip_config[] = { +- HWMON_C_REGISTER_TZ, +- 0 +-}; +- +-static const struct hwmon_channel_info m88e1121_hwmon_chip = { +- .type = hwmon_chip, +- .config = m88e1121_hwmon_chip_config, +-}; +- +-static u32 m88e1121_hwmon_temp_config[] = { +- HWMON_T_INPUT, +- 0 +-}; +- +-static const struct hwmon_channel_info m88e1121_hwmon_temp = { +- .type = hwmon_temp, +- .config = m88e1121_hwmon_temp_config, +-}; +- +-static const struct hwmon_channel_info *m88e1121_hwmon_info[] = { +- &m88e1121_hwmon_chip, +- &m88e1121_hwmon_temp, +- NULL +-}; +- +-static const struct hwmon_ops m88e1121_hwmon_hwmon_ops = { +- .is_visible = m88e1121_hwmon_is_visible, +- .read = m88e1121_hwmon_read, +-}; +- +-static const struct hwmon_chip_info m88e1121_hwmon_chip_info = { +- .ops = &m88e1121_hwmon_hwmon_ops, +- .info = m88e1121_hwmon_info, +-}; +- + static int m88e1510_get_temp(struct phy_device *phydev, long *temp) + { + int ret; +@@ -2315,92 +2259,6 @@ static int m88e1510_get_temp_alarm(struc + return 0; + } + +-static int m88e1510_hwmon_read(struct device *dev, +- enum hwmon_sensor_types type, +- u32 attr, int channel, long *temp) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int err; +- +- switch (attr) { +- case hwmon_temp_input: +- err = m88e1510_get_temp(phydev, temp); +- break; +- case hwmon_temp_crit: +- err = m88e1510_get_temp_critical(phydev, temp); +- break; +- case hwmon_temp_max_alarm: +- err = m88e1510_get_temp_alarm(phydev, temp); +- break; +- default: +- return -EOPNOTSUPP; +- } +- +- return err; +-} +- +-static int m88e1510_hwmon_write(struct device *dev, +- enum hwmon_sensor_types type, +- u32 attr, int channel, long temp) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int err; +- +- switch (attr) { +- case hwmon_temp_crit: +- err = m88e1510_set_temp_critical(phydev, temp); +- break; +- default: +- return -EOPNOTSUPP; +- } +- return err; +-} +- +-static umode_t m88e1510_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) +-{ +- if (type != hwmon_temp) +- return 0; +- +- switch (attr) { +- case hwmon_temp_input: +- case hwmon_temp_max_alarm: +- return 0444; +- case hwmon_temp_crit: +- return 0644; +- default: +- return 0; +- } +-} +- +-static u32 m88e1510_hwmon_temp_config[] = { +- HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM, +- 0 +-}; +- +-static const struct hwmon_channel_info m88e1510_hwmon_temp = { +- .type = hwmon_temp, +- .config = m88e1510_hwmon_temp_config, +-}; +- +-static const struct hwmon_channel_info *m88e1510_hwmon_info[] = { +- &m88e1121_hwmon_chip, +- &m88e1510_hwmon_temp, +- NULL +-}; +- +-static const struct hwmon_ops m88e1510_hwmon_hwmon_ops = { +- .is_visible = m88e1510_hwmon_is_visible, +- .read = m88e1510_hwmon_read, +- .write = m88e1510_hwmon_write, +-}; +- +-static const struct hwmon_chip_info m88e1510_hwmon_chip_info = { +- .ops = &m88e1510_hwmon_hwmon_ops, +- .info = m88e1510_hwmon_info, +-}; +- + static int m88e6390_get_temp(struct phy_device *phydev, long *temp) + { + int sum = 0; +@@ -2459,63 +2317,112 @@ error: + return ret; + } + +-static int m88e6390_hwmon_read(struct device *dev, +- enum hwmon_sensor_types type, +- u32 attr, int channel, long *temp) ++static int marvell_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *temp) + { + struct phy_device *phydev = dev_get_drvdata(dev); +- int err; ++ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); ++ int err = -EOPNOTSUPP; + + switch (attr) { + case hwmon_temp_input: +- err = m88e6390_get_temp(phydev, temp); ++ if (ops->get_temp) ++ err = ops->get_temp(phydev, temp); ++ break; ++ case hwmon_temp_crit: ++ if (ops->get_temp_critical) ++ err = ops->get_temp_critical(phydev, temp); ++ break; ++ case hwmon_temp_max_alarm: ++ if (ops->get_temp_alarm) ++ err = ops->get_temp_alarm(phydev, temp); ++ break; ++ } ++ ++ return err; ++} ++ ++static int marvell_hwmon_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long temp) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); ++ int err = -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_crit: ++ if (ops->set_temp_critical) ++ err = ops->set_temp_critical(phydev, temp); + break; + default: +- return -EOPNOTSUPP; ++ fallthrough; + } + + return err; + } + +-static umode_t m88e6390_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) ++static umode_t marvell_hwmon_is_visible(const void *data, ++ enum hwmon_sensor_types type, ++ u32 attr, int channel) + { ++ const struct phy_device *phydev = data; ++ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); ++ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: +- return 0444; ++ return ops->get_temp ? 0444 : 0; ++ case hwmon_temp_max_alarm: ++ return ops->get_temp_alarm ? 0444 : 0; ++ case hwmon_temp_crit: ++ return (ops->get_temp_critical ? 0444 : 0) | ++ (ops->set_temp_critical ? 0200 : 0); + default: + return 0; + } + } + +-static u32 m88e6390_hwmon_temp_config[] = { +- HWMON_T_INPUT, ++static u32 marvell_hwmon_chip_config[] = { ++ HWMON_C_REGISTER_TZ, + 0 + }; + +-static const struct hwmon_channel_info m88e6390_hwmon_temp = { ++static const struct hwmon_channel_info marvell_hwmon_chip = { ++ .type = hwmon_chip, ++ .config = marvell_hwmon_chip_config, ++}; ++ ++/* we can define HWMON_T_CRIT and HWMON_T_MAX_ALARM even though these are not ++ * defined for all PHYs, because the hwmon code checks whether the attributes ++ * exists via the .is_visible method ++ */ ++static u32 marvell_hwmon_temp_config[] = { ++ HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM, ++ 0 ++}; ++ ++static const struct hwmon_channel_info marvell_hwmon_temp = { + .type = hwmon_temp, +- .config = m88e6390_hwmon_temp_config, ++ .config = marvell_hwmon_temp_config, + }; + +-static const struct hwmon_channel_info *m88e6390_hwmon_info[] = { +- &m88e1121_hwmon_chip, +- &m88e6390_hwmon_temp, ++static const struct hwmon_channel_info *marvell_hwmon_info[] = { ++ &marvell_hwmon_chip, ++ &marvell_hwmon_temp, + NULL + }; + +-static const struct hwmon_ops m88e6390_hwmon_hwmon_ops = { +- .is_visible = m88e6390_hwmon_is_visible, +- .read = m88e6390_hwmon_read, ++static const struct hwmon_ops marvell_hwmon_hwmon_ops = { ++ .is_visible = marvell_hwmon_is_visible, ++ .read = marvell_hwmon_read, ++ .write = marvell_hwmon_write, + }; + +-static const struct hwmon_chip_info m88e6390_hwmon_chip_info = { +- .ops = &m88e6390_hwmon_hwmon_ops, +- .info = m88e6390_hwmon_info, ++static const struct hwmon_chip_info marvell_hwmon_chip_info = { ++ .ops = &marvell_hwmon_hwmon_ops, ++ .info = marvell_hwmon_info, + }; + + static int marvell_hwmon_name(struct phy_device *phydev) +@@ -2538,49 +2445,48 @@ static int marvell_hwmon_name(struct phy + return 0; + } + +-static int marvell_hwmon_probe(struct phy_device *phydev, +- const struct hwmon_chip_info *chip) ++static int marvell_hwmon_probe(struct phy_device *phydev) + { ++ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); + struct marvell_priv *priv = phydev->priv; + struct device *dev = &phydev->mdio.dev; + int err; + ++ if (!ops) ++ return 0; ++ + err = marvell_hwmon_name(phydev); + if (err) + return err; + + priv->hwmon_dev = devm_hwmon_device_register_with_info( +- dev, priv->hwmon_name, phydev, chip, NULL); ++ dev, priv->hwmon_name, phydev, &marvell_hwmon_chip_info, NULL); + + return PTR_ERR_OR_ZERO(priv->hwmon_dev); + } + +-static int m88e1121_hwmon_probe(struct phy_device *phydev) +-{ +- return marvell_hwmon_probe(phydev, &m88e1121_hwmon_chip_info); +-} ++static const struct marvell_hwmon_ops m88e1121_hwmon_ops = { ++ .get_temp = m88e1121_get_temp, ++}; + +-static int m88e1510_hwmon_probe(struct phy_device *phydev) +-{ +- return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info); +-} ++static const struct marvell_hwmon_ops m88e1510_hwmon_ops = { ++ .get_temp = m88e1510_get_temp, ++ .get_temp_critical = m88e1510_get_temp_critical, ++ .set_temp_critical = m88e1510_set_temp_critical, ++ .get_temp_alarm = m88e1510_get_temp_alarm, ++}; ++ ++static const struct marvell_hwmon_ops m88e6390_hwmon_ops = { ++ .get_temp = m88e6390_get_temp, ++}; ++ ++#define DEF_MARVELL_HWMON_OPS(s) (&(s)) + +-static int m88e6390_hwmon_probe(struct phy_device *phydev) +-{ +- return marvell_hwmon_probe(phydev, &m88e6390_hwmon_chip_info); +-} + #else +-static int m88e1121_hwmon_probe(struct phy_device *phydev) +-{ +- return 0; +-} + +-static int m88e1510_hwmon_probe(struct phy_device *phydev) +-{ +- return 0; +-} ++#define DEF_MARVELL_HWMON_OPS(s) NULL + +-static int m88e6390_hwmon_probe(struct phy_device *phydev) ++static int marvell_hwmon_probe(struct phy_device *phydev) + { + return 0; + } +@@ -2596,40 +2502,7 @@ static int marvell_probe(struct phy_devi + + phydev->priv = priv; + +- return 0; +-} +- +-static int m88e1121_probe(struct phy_device *phydev) +-{ +- int err; +- +- err = marvell_probe(phydev); +- if (err) +- return err; +- +- return m88e1121_hwmon_probe(phydev); +-} +- +-static int m88e1510_probe(struct phy_device *phydev) +-{ +- int err; +- +- err = marvell_probe(phydev); +- if (err) +- return err; +- +- return m88e1510_hwmon_probe(phydev); +-} +- +-static int m88e6390_probe(struct phy_device *phydev) +-{ +- int err; +- +- err = marvell_probe(phydev); +- if (err) +- return err; +- +- return m88e6390_hwmon_probe(phydev); ++ return marvell_hwmon_probe(phydev); + } + + static struct phy_driver marvell_drivers[] = { +@@ -2714,8 +2587,9 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E1121R, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1121R", ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1121_hwmon_ops), + /* PHY_GBIT_FEATURES */ +- .probe = m88e1121_probe, ++ .probe = marvell_probe, + .config_init = marvell_config_init, + .config_aneg = m88e1121_config_aneg, + .read_status = marvell_read_status, +@@ -2834,9 +2708,10 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E1510, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1510", ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), + .features = PHY_GBIT_FIBRE_FEATURES, + .flags = PHY_POLL_CABLE_TEST, +- .probe = m88e1510_probe, ++ .probe = marvell_probe, + .config_init = m88e1510_config_init, + .config_aneg = m88e1510_config_aneg, + .read_status = marvell_read_status, +@@ -2863,9 +2738,10 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E1540, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1540", ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), + /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, +- .probe = m88e1510_probe, ++ .probe = marvell_probe, + .config_init = marvell_config_init, + .config_aneg = m88e1510_config_aneg, + .read_status = marvell_read_status, +@@ -2889,7 +2765,8 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E1545, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1545", +- .probe = m88e1510_probe, ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), ++ .probe = marvell_probe, + /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, + .config_init = marvell_config_init, +@@ -2935,9 +2812,10 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E6341_FAMILY, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E6341 Family", ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), + /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, +- .probe = m88e1510_probe, ++ .probe = marvell_probe, + .config_init = marvell_config_init, + .config_aneg = m88e6390_config_aneg, + .read_status = marvell_read_status, +@@ -2961,9 +2839,10 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E6390_FAMILY, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E6390 Family", ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e6390_hwmon_ops), + /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, +- .probe = m88e6390_probe, ++ .probe = marvell_probe, + .config_init = marvell_config_init, + .config_aneg = m88e6390_config_aneg, + .read_status = marvell_read_status, +@@ -2987,7 +2866,8 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E1340S, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1340S", +- .probe = m88e1510_probe, ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), ++ .probe = marvell_probe, + /* PHY_GBIT_FEATURES */ + .config_init = marvell_config_init, + .config_aneg = m88e1510_config_aneg, +@@ -3009,7 +2889,8 @@ static struct phy_driver marvell_drivers + .phy_id = MARVELL_PHY_ID_88E1548P, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1548P", +- .probe = m88e1510_probe, ++ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), ++ .probe = marvell_probe, + .features = PHY_GBIT_FIBRE_FEATURES, + .config_init = marvell_config_init, + .config_aneg = m88e1510_config_aneg, diff --git a/target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch b/target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch new file mode 100644 index 0000000000..b86e9bf640 --- /dev/null +++ b/target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch @@ -0,0 +1,161 @@ +From b697d9d38a5a5ab405d7cc4743d39fe2c5d7517c Mon Sep 17 00:00:00 2001 +From: Ivan Bornyakov +Date: Thu, 12 Aug 2021 16:42:56 +0300 +Subject: [PATCH] net: phy: marvell: add SFP support for 88E1510 + +Add support for SFP cages connected to the Marvell 88E1512 transceiver. +88E1512 supports for SGMII/1000Base-X/100Base-FX media type with RGMII +on system interface. Configure PHY to appropriate mode depending on the +type of SFP inserted. On SFP removal configure PHY to the RGMII-copper +mode so RJ-45 port can still work. + +Signed-off-by: Ivan Bornyakov +Link: https://lore.kernel.org/r/20210812134256.2436-1-i.bornyakov@metrotek.ru +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/marvell.c | 105 +++++++++++++++++++++++++++++++++++++- + 1 file changed, 104 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -46,6 +47,7 @@ + #define MII_MARVELL_MISC_TEST_PAGE 0x06 + #define MII_MARVELL_VCT7_PAGE 0x07 + #define MII_MARVELL_WOL_PAGE 0x11 ++#define MII_MARVELL_MODE_PAGE 0x12 + + #define MII_M1011_IEVENT 0x13 + #define MII_M1011_IEVENT_CLEAR 0x0000 +@@ -162,7 +164,14 @@ + + #define MII_88E1510_GEN_CTRL_REG_1 0x14 + #define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7 ++#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII 0x0 /* RGMII to copper */ + #define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */ ++/* RGMII to 1000BASE-X */ ++#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X 0x2 ++/* RGMII to 100BASE-FX */ ++#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX 0x3 ++/* RGMII to SGMII */ ++#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII 0x4 + #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */ + + #define MII_VCT5_TX_RX_MDI0_COUPLING 0x10 +@@ -2505,6 +2514,100 @@ static int marvell_probe(struct phy_devi + return marvell_hwmon_probe(phydev); + } + ++static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ phy_interface_t interface; ++ struct device *dev; ++ int oldpage; ++ int ret = 0; ++ u16 mode; ++ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; ++ ++ dev = &phydev->mdio.dev; ++ ++ sfp_parse_support(phydev->sfp_bus, id, supported); ++ interface = sfp_select_interface(phydev->sfp_bus, supported); ++ ++ dev_info(dev, "%s SFP module inserted\n", phy_modes(interface)); ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; ++ ++ break; ++ case PHY_INTERFACE_MODE_100BASEX: ++ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; ++ ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; ++ ++ break; ++ default: ++ dev_err(dev, "Incompatible SFP module inserted\n"); ++ ++ return -EINVAL; ++ } ++ ++ oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); ++ if (oldpage < 0) ++ goto error; ++ ++ ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, ++ MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, mode); ++ if (ret < 0) ++ goto error; ++ ++ ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, ++ MII_88E1510_GEN_CTRL_REG_1_RESET); ++ ++error: ++ return phy_restore_page(phydev, oldpage, ret); ++} ++ ++static void m88e1510_sfp_remove(void *upstream) ++{ ++ struct phy_device *phydev = upstream; ++ int oldpage; ++ int ret = 0; ++ ++ oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); ++ if (oldpage < 0) ++ goto error; ++ ++ ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, ++ MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, ++ MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII); ++ if (ret < 0) ++ goto error; ++ ++ ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, ++ MII_88E1510_GEN_CTRL_REG_1_RESET); ++ ++error: ++ phy_restore_page(phydev, oldpage, ret); ++} ++ ++static const struct sfp_upstream_ops m88e1510_sfp_ops = { ++ .module_insert = m88e1510_sfp_insert, ++ .module_remove = m88e1510_sfp_remove, ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++}; ++ ++static int m88e1510_probe(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = marvell_probe(phydev); ++ if (err) ++ return err; ++ ++ return phy_sfp_probe(phydev, &m88e1510_sfp_ops); ++} ++ + static struct phy_driver marvell_drivers[] = { + { + .phy_id = MARVELL_PHY_ID_88E1101, +@@ -2711,7 +2814,7 @@ static struct phy_driver marvell_drivers + .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), + .features = PHY_GBIT_FIBRE_FEATURES, + .flags = PHY_POLL_CABLE_TEST, +- .probe = marvell_probe, ++ .probe = m88e1510_probe, + .config_init = m88e1510_config_init, + .config_aneg = m88e1510_config_aneg, + .read_status = marvell_read_status, diff --git a/target/linux/generic/backport-5.15/719-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch b/target/linux/generic/backport-5.15/719-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.15/719-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.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch b/target/linux/generic/backport-5.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch new file mode 100644 index 0000000000..c43cb4d1f2 --- /dev/null +++ b/target/linux/generic/backport-5.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch @@ -0,0 +1,126 @@ +From 90dc8fd36078a536671adae884d0b929cce6480a Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 6 Jan 2021 11:51:30 +0200 +Subject: [PATCH] net: bridge: notify switchdev of disappearance of old FDB + entry upon migration + +Currently the bridge emits atomic switchdev notifications for +dynamically learnt FDB entries. Monitoring these notifications works +wonders for switchdev drivers that want to keep their hardware FDB in +sync with the bridge's FDB. + +For example station A wants to talk to station B in the diagram below, +and we are concerned with the behavior of the bridge on the DUT device: + + DUT + +-------------------------------------+ + | br0 | + | +------+ +------+ +------+ +------+ | + | | | | | | | | | | + | | swp0 | | swp1 | | swp2 | | eth0 | | + +-------------------------------------+ + | | | + Station A | | + | | + +--+------+--+ +--+------+--+ + | | | | | | | | + | | swp0 | | | | swp0 | | + Another | +------+ | | +------+ | Another + switch | br0 | | br0 | switch + | +------+ | | +------+ | + | | | | | | | | + | | swp1 | | | | swp1 | | + +--+------+--+ +--+------+--+ + | + Station B + +Interfaces swp0, swp1, swp2 are handled by a switchdev driver that has +the following property: frames injected from its control interface bypass +the internal address analyzer logic, and therefore, this hardware does +not learn from the source address of packets transmitted by the network +stack through it. So, since bridging between eth0 (where Station B is +attached) and swp0 (where Station A is attached) is done in software, +the switchdev hardware will never learn the source address of Station B. +So the traffic towards that destination will be treated as unknown, i.e. +flooded. + +This is where the bridge notifications come in handy. When br0 on the +DUT sees frames with Station B's MAC address on eth0, the switchdev +driver gets these notifications and can install a rule to send frames +towards Station B's address that are incoming from swp0, swp1, swp2, +only towards the control interface. This is all switchdev driver private +business, which the notification makes possible. + +All is fine until someone unplugs Station B's cable and moves it to the +other switch: + + DUT + +-------------------------------------+ + | br0 | + | +------+ +------+ +------+ +------+ | + | | | | | | | | | | + | | swp0 | | swp1 | | swp2 | | eth0 | | + +-------------------------------------+ + | | | + Station A | | + | | + +--+------+--+ +--+------+--+ + | | | | | | | | + | | swp0 | | | | swp0 | | + Another | +------+ | | +------+ | Another + switch | br0 | | br0 | switch + | +------+ | | +------+ | + | | | | | | | | + | | swp1 | | | | swp1 | | + +--+------+--+ +--+------+--+ + | + Station B + +Luckily for the use cases we care about, Station B is noisy enough that +the DUT hears it (on swp1 this time). swp1 receives the frames and +delivers them to the bridge, who enters the unlikely path in br_fdb_update +of updating an existing entry. It moves the entry in the software bridge +to swp1 and emits an addition notification towards that. + +As far as the switchdev driver is concerned, all that it needs to ensure +is that traffic between Station A and Station B is not forever broken. +If it does nothing, then the stale rule to send frames for Station B +towards the control interface remains in place. But Station B is no +longer reachable via the control interface, but via a port that can +offload the bridge port learning attribute. It's just that the port is +prevented from learning this address, since the rule overrides FDB +updates. So the rule needs to go. The question is via what mechanism. + +It sure would be possible for this switchdev driver to keep track of all +addresses which are sent to the control interface, and then also listen +for bridge notifier events on its own ports, searching for the ones that +have a MAC address which was previously sent to the control interface. +But this is cumbersome and inefficient. Instead, with one small change, +the bridge could notify of the address deletion from the old port, in a +symmetrical manner with how it did for the insertion. Then the switchdev +driver would not be required to monitor learn/forget events for its own +ports. It could just delete the rule towards the control interface upon +bridge entry migration. This would make hardware address learning be +possible again. Then it would take a few more packets until the hardware +and software FDB would be in sync again. + +Signed-off-by: Vladimir Oltean +Acked-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + net/bridge/br_fdb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -602,6 +602,7 @@ void br_fdb_update(struct net_bridge *br + /* fastpath: update of existing entry */ + if (unlikely(source != fdb->dst && + !test_bit(BR_FDB_STICKY, &fdb->flags))) { ++ br_switchdev_fdb_notify(fdb, RTM_DELNEIGH); + fdb->dst = source; + fdb_modified = true; + /* Take over HW learned entry */ diff --git a/target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch b/target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch new file mode 100644 index 0000000000..f9337590f7 --- /dev/null +++ b/target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch @@ -0,0 +1,52 @@ +From 2fd186501b1cff155cc4a755c210793cfc0dffb5 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 6 Jan 2021 11:51:31 +0200 +Subject: [PATCH] net: dsa: be louder when a non-legacy FDB operation fails + +The dev_close() call was added in commit c9eb3e0f8701 ("net: dsa: Add +support for learning FDB through notification") "to indicate inconsistent +situation" when we could not delete an FDB entry from the port. + +bridge fdb del d8:58:d7:00:ca:6d dev swp0 self master + +It is a bit drastic and at the same time not helpful if the above fails +to only print with netdev_dbg log level, but on the other hand to bring +the interface down. + +So increase the verbosity of the error message, and drop dev_close(). + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + net/dsa/slave.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2112,7 +2112,9 @@ static void dsa_slave_switchdev_event_wo + + err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); + if (err) { +- netdev_dbg(dev, "fdb add failed err=%d\n", err); ++ netdev_err(dev, ++ "failed to add %pM vid %d to fdb: %d\n", ++ fdb_info->addr, fdb_info->vid, err); + break; + } + fdb_info->offloaded = true; +@@ -2127,9 +2129,11 @@ static void dsa_slave_switchdev_event_wo + + err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); + if (err) { +- netdev_dbg(dev, "fdb del failed err=%d\n", err); +- dev_close(dev); ++ netdev_err(dev, ++ "failed to delete %pM vid %d from fdb: %d\n", ++ fdb_info->addr, fdb_info->vid, err); + } ++ + break; + } + rtnl_unlock(); diff --git a/target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch b/target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch new file mode 100644 index 0000000000..c1aa8fda82 --- /dev/null +++ b/target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch @@ -0,0 +1,226 @@ +From c4bb76a9a0ef87c4cc1f636defed5f12deb9f5a7 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 6 Jan 2021 11:51:32 +0200 +Subject: [PATCH] net: dsa: don't use switchdev_notifier_fdb_info in + dsa_switchdev_event_work + +Currently DSA doesn't add FDB entries on the CPU port, because it only +does so through switchdev, which is associated with a net_device, and +there are none of those for the CPU port. + +But actually FDB addresses on the CPU port have some use cases of their +own, if the switchdev operations are initiated from within the DSA +layer. There is just one problem with the existing code: it passes a +structure in dsa_switchdev_event_work which was retrieved directly from +switchdev, so it contains a net_device. We need to generalize the +contents to something that covers the CPU port as well: the "ds, port" +tuple is fine for that. + +Note that the new procedure for notifying the successful FDB offload is +inspired from the rocker model. + +Also, nothing was being done if added_by_user was false. Let's check for +that a lot earlier, and don't actually bother to schedule the worker +for nothing. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + net/dsa/dsa_priv.h | 12 +++++ + net/dsa/slave.c | 106 ++++++++++++++++++++++----------------------- + 2 files changed, 65 insertions(+), 53 deletions(-) + +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -73,6 +73,18 @@ struct dsa_notifier_mtu_info { + int mtu; + }; + ++struct dsa_switchdev_event_work { ++ struct dsa_switch *ds; ++ int port; ++ struct work_struct work; ++ unsigned long event; ++ /* Specific for SWITCHDEV_FDB_ADD_TO_DEVICE and ++ * SWITCHDEV_FDB_DEL_TO_DEVICE ++ */ ++ unsigned char addr[ETH_ALEN]; ++ u16 vid; ++}; ++ + struct dsa_slave_priv { + /* Copy of CPU port xmit for faster access in slave transmit hot path */ + struct sk_buff * (*xmit)(struct sk_buff *skb, +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2087,76 +2087,66 @@ static int dsa_slave_netdevice_event(str + return NOTIFY_DONE; + } + +-struct dsa_switchdev_event_work { +- struct work_struct work; +- struct switchdev_notifier_fdb_info fdb_info; +- struct net_device *dev; +- unsigned long event; +-}; ++static void ++dsa_fdb_offload_notify(struct dsa_switchdev_event_work *switchdev_work) ++{ ++ struct dsa_switch *ds = switchdev_work->ds; ++ struct switchdev_notifier_fdb_info info; ++ struct dsa_port *dp; ++ ++ if (!dsa_is_user_port(ds, switchdev_work->port)) ++ return; ++ ++ info.addr = switchdev_work->addr; ++ info.vid = switchdev_work->vid; ++ info.offloaded = true; ++ dp = dsa_to_port(ds, switchdev_work->port); ++ call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, ++ dp->slave, &info.info, NULL); ++} + + static void dsa_slave_switchdev_event_work(struct work_struct *work) + { + struct dsa_switchdev_event_work *switchdev_work = + container_of(work, struct dsa_switchdev_event_work, work); +- struct net_device *dev = switchdev_work->dev; +- struct switchdev_notifier_fdb_info *fdb_info; +- struct dsa_port *dp = dsa_slave_to_port(dev); ++ struct dsa_switch *ds = switchdev_work->ds; ++ struct dsa_port *dp; + int err; + ++ dp = dsa_to_port(ds, switchdev_work->port); ++ + rtnl_lock(); + switch (switchdev_work->event) { + case SWITCHDEV_FDB_ADD_TO_DEVICE: +- fdb_info = &switchdev_work->fdb_info; +- if (!fdb_info->added_by_user) +- break; +- +- err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); ++ err = dsa_port_fdb_add(dp, switchdev_work->addr, ++ switchdev_work->vid); + if (err) { +- netdev_err(dev, +- "failed to add %pM vid %d to fdb: %d\n", +- fdb_info->addr, fdb_info->vid, err); ++ dev_err(ds->dev, ++ "port %d failed to add %pM vid %d to fdb: %d\n", ++ dp->index, switchdev_work->addr, ++ switchdev_work->vid, err); + break; + } +- fdb_info->offloaded = true; +- call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, +- &fdb_info->info, NULL); ++ dsa_fdb_offload_notify(switchdev_work); + break; + + case SWITCHDEV_FDB_DEL_TO_DEVICE: +- fdb_info = &switchdev_work->fdb_info; +- if (!fdb_info->added_by_user) +- break; +- +- err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); ++ err = dsa_port_fdb_del(dp, switchdev_work->addr, ++ switchdev_work->vid); + if (err) { +- netdev_err(dev, +- "failed to delete %pM vid %d from fdb: %d\n", +- fdb_info->addr, fdb_info->vid, err); ++ dev_err(ds->dev, ++ "port %d failed to delete %pM vid %d from fdb: %d\n", ++ dp->index, switchdev_work->addr, ++ switchdev_work->vid, err); + } + + break; + } + rtnl_unlock(); + +- kfree(switchdev_work->fdb_info.addr); + kfree(switchdev_work); +- dev_put(dev); +-} +- +-static int +-dsa_slave_switchdev_fdb_work_init(struct dsa_switchdev_event_work * +- switchdev_work, +- const struct switchdev_notifier_fdb_info * +- fdb_info) +-{ +- memcpy(&switchdev_work->fdb_info, fdb_info, +- sizeof(switchdev_work->fdb_info)); +- switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); +- if (!switchdev_work->fdb_info.addr) +- return -ENOMEM; +- ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, +- fdb_info->addr); +- return 0; ++ if (dsa_is_user_port(ds, dp->index)) ++ dev_put(dp->slave); + } + + /* Called under rcu_read_lock() */ +@@ -2164,7 +2154,9 @@ static int dsa_slave_switchdev_event(str + unsigned long event, void *ptr) + { + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); ++ const struct switchdev_notifier_fdb_info *fdb_info; + struct dsa_switchdev_event_work *switchdev_work; ++ struct dsa_port *dp; + int err; + + if (event == SWITCHDEV_PORT_ATTR_SET) { +@@ -2177,20 +2169,32 @@ static int dsa_slave_switchdev_event(str + if (!dsa_slave_dev_check(dev)) + return NOTIFY_DONE; + ++ dp = dsa_slave_to_port(dev); ++ + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); + if (!switchdev_work) + return NOTIFY_BAD; + + INIT_WORK(&switchdev_work->work, + dsa_slave_switchdev_event_work); +- switchdev_work->dev = dev; ++ switchdev_work->ds = dp->ds; ++ switchdev_work->port = dp->index; + switchdev_work->event = event; + + switch (event) { + case SWITCHDEV_FDB_ADD_TO_DEVICE: + case SWITCHDEV_FDB_DEL_TO_DEVICE: +- if (dsa_slave_switchdev_fdb_work_init(switchdev_work, ptr)) +- goto err_fdb_work_init; ++ fdb_info = ptr; ++ ++ if (!fdb_info->added_by_user) { ++ kfree(switchdev_work); ++ return NOTIFY_OK; ++ } ++ ++ ether_addr_copy(switchdev_work->addr, ++ fdb_info->addr); ++ switchdev_work->vid = fdb_info->vid; ++ + dev_hold(dev); + break; + default: +@@ -2200,10 +2204,6 @@ static int dsa_slave_switchdev_event(str + + dsa_schedule_work(&switchdev_work->work); + return NOTIFY_OK; +- +-err_fdb_work_init: +- kfree(switchdev_work); +- return NOTIFY_BAD; + } + + static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, diff --git a/target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch b/target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch new file mode 100644 index 0000000000..9131df70d3 --- /dev/null +++ b/target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch @@ -0,0 +1,85 @@ +From 447d290a58bd335d68f665713842365d3d6447df Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 6 Jan 2021 11:51:33 +0200 +Subject: [PATCH] net: dsa: move switchdev event implementation under the same + switch/case statement + +We'll need to start listening to SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE +events even for interfaces where dsa_slave_dev_check returns false, so +we need that check inside the switch-case statement for SWITCHDEV_FDB_*. + +This movement also avoids a useless allocation / free of switchdev_work +on the untreated "default event" case. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + net/dsa/slave.c | 35 ++++++++++++++++------------------- + 1 file changed, 16 insertions(+), 19 deletions(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2159,31 +2159,29 @@ static int dsa_slave_switchdev_event(str + struct dsa_port *dp; + int err; + +- if (event == SWITCHDEV_PORT_ATTR_SET) { ++ switch (event) { ++ case SWITCHDEV_PORT_ATTR_SET: + err = switchdev_handle_port_attr_set(dev, ptr, + dsa_slave_dev_check, + dsa_slave_port_attr_set); + return notifier_from_errno(err); +- } +- +- if (!dsa_slave_dev_check(dev)) +- return NOTIFY_DONE; ++ case SWITCHDEV_FDB_ADD_TO_DEVICE: ++ case SWITCHDEV_FDB_DEL_TO_DEVICE: ++ if (!dsa_slave_dev_check(dev)) ++ return NOTIFY_DONE; + +- dp = dsa_slave_to_port(dev); ++ dp = dsa_slave_to_port(dev); + +- switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); +- if (!switchdev_work) +- return NOTIFY_BAD; +- +- INIT_WORK(&switchdev_work->work, +- dsa_slave_switchdev_event_work); +- switchdev_work->ds = dp->ds; +- switchdev_work->port = dp->index; +- switchdev_work->event = event; ++ switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); ++ if (!switchdev_work) ++ return NOTIFY_BAD; ++ ++ INIT_WORK(&switchdev_work->work, ++ dsa_slave_switchdev_event_work); ++ switchdev_work->ds = dp->ds; ++ switchdev_work->port = dp->index; ++ switchdev_work->event = event; + +- switch (event) { +- case SWITCHDEV_FDB_ADD_TO_DEVICE: +- case SWITCHDEV_FDB_DEL_TO_DEVICE: + fdb_info = ptr; + + if (!fdb_info->added_by_user) { +@@ -2196,13 +2194,12 @@ static int dsa_slave_switchdev_event(str + switchdev_work->vid = fdb_info->vid; + + dev_hold(dev); ++ dsa_schedule_work(&switchdev_work->work); + break; + default: +- kfree(switchdev_work); + return NOTIFY_DONE; + } + +- dsa_schedule_work(&switchdev_work->work); + return NOTIFY_OK; + } + diff --git a/target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch b/target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch new file mode 100644 index 0000000000..b7b6ebe461 --- /dev/null +++ b/target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch @@ -0,0 +1,42 @@ +From 5fb4a451a87d8ed3363d28b63a3295399373d6c4 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 6 Jan 2021 11:51:34 +0200 +Subject: [PATCH] net: dsa: exit early in dsa_slave_switchdev_event if we can't + program the FDB + +Right now, the following would happen for a switch driver that does not +implement .port_fdb_add or .port_fdb_del. + +dsa_slave_switchdev_event returns NOTIFY_OK and schedules: +-> dsa_slave_switchdev_event_work + -> dsa_port_fdb_add + -> dsa_port_notify(DSA_NOTIFIER_FDB_ADD) + -> dsa_switch_fdb_add + -> if (!ds->ops->port_fdb_add) return -EOPNOTSUPP; + -> an error is printed with dev_dbg, and + dsa_fdb_offload_notify(switchdev_work) is not called. + +We can avoid scheduling the worker for nothing and say NOTIFY_DONE. +Because we don't call dsa_fdb_offload_notify, the static FDB entry will +remain just in the software bridge. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + net/dsa/slave.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2172,6 +2172,9 @@ static int dsa_slave_switchdev_event(str + + dp = dsa_slave_to_port(dev); + ++ if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) ++ return NOTIFY_DONE; ++ + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); + if (!switchdev_work) + return NOTIFY_BAD; diff --git a/target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch b/target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch new file mode 100644 index 0000000000..e7b9af1951 --- /dev/null +++ b/target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch @@ -0,0 +1,264 @@ +From d5f19486cee79d04c054427577ac96ed123706db Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 6 Jan 2021 11:51:35 +0200 +Subject: [PATCH] net: dsa: listen for SWITCHDEV_{FDB,DEL}_ADD_TO_DEVICE on + foreign bridge neighbors + +Some DSA switches (and not only) cannot learn source MAC addresses from +packets injected from the CPU. They only perform hardware address +learning from inbound traffic. + +This can be problematic when we have a bridge spanning some DSA switch +ports and some non-DSA ports (which we'll call "foreign interfaces" from +DSA's perspective). + +There are 2 classes of problems created by the lack of learning on +CPU-injected traffic: +- excessive flooding, due to the fact that DSA treats those addresses as + unknown +- the risk of stale routes, which can lead to temporary packet loss + +To illustrate the second class, consider the following situation, which +is common in production equipment (wireless access points, where there +is a WLAN interface and an Ethernet switch, and these form a single +bridging domain). + + AP 1: + +------------------------------------------------------------------------+ + | br0 | + +------------------------------------------------------------------------+ + +------------+ +------------+ +------------+ +------------+ +------------+ + | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | + +------------+ +------------+ +------------+ +------------+ +------------+ + | ^ ^ + | | | + | | | + | Client A Client B + | + | + | + +------------+ +------------+ +------------+ +------------+ +------------+ + | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | + +------------+ +------------+ +------------+ +------------+ +------------+ + +------------------------------------------------------------------------+ + | br0 | + +------------------------------------------------------------------------+ + AP 2 + +- br0 of AP 1 will know that Clients A and B are reachable via wlan0 +- the hardware fdb of a DSA switch driver today is not kept in sync with + the software entries on other bridge ports, so it will not know that + clients A and B are reachable via the CPU port UNLESS the hardware + switch itself performs SA learning from traffic injected from the CPU. + Nonetheless, a substantial number of switches don't. +- the hardware fdb of the DSA switch on AP 2 may autonomously learn that + Client A and B are reachable through swp0. Therefore, the software br0 + of AP 2 also may or may not learn this. In the example we're + illustrating, some Ethernet traffic has been going on, and br0 from AP + 2 has indeed learnt that it can reach Client B through swp0. + +One of the wireless clients, say Client B, disconnects from AP 1 and +roams to AP 2. The topology now looks like this: + + AP 1: + +------------------------------------------------------------------------+ + | br0 | + +------------------------------------------------------------------------+ + +------------+ +------------+ +------------+ +------------+ +------------+ + | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | + +------------+ +------------+ +------------+ +------------+ +------------+ + | ^ + | | + | Client A + | + | + | Client B + | | + | v + +------------+ +------------+ +------------+ +------------+ +------------+ + | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | + +------------+ +------------+ +------------+ +------------+ +------------+ + +------------------------------------------------------------------------+ + | br0 | + +------------------------------------------------------------------------+ + AP 2 + +- br0 of AP 1 still knows that Client A is reachable via wlan0 (no change) +- br0 of AP 1 will (possibly) know that Client B has left wlan0. There + are cases where it might never find out though. Either way, DSA today + does not process that notification in any way. +- the hardware FDB of the DSA switch on AP 1 may learn autonomously that + Client B can be reached via swp0, if it receives any packet with + Client 1's source MAC address over Ethernet. +- the hardware FDB of the DSA switch on AP 2 still thinks that Client B + can be reached via swp0. It does not know that it has roamed to wlan0, + because it doesn't perform SA learning from the CPU port. + +Now Client A contacts Client B. +AP 1 routes the packet fine towards swp0 and delivers it on the Ethernet +segment. +AP 2 sees a frame on swp0 and its fdb says that the destination is swp0. +Hairpinning is disabled => drop. + +This problem comes from the fact that these switches have a 'blind spot' +for addresses coming from software bridging. The generic solution is not +to assume that hardware learning can be enabled somehow, but to listen +to more bridge learning events. It turns out that the bridge driver does +learn in software from all inbound frames, in __br_handle_local_finish. +A proper SWITCHDEV_FDB_ADD_TO_DEVICE notification is emitted for the +addresses serviced by the bridge on 'foreign' interfaces. The software +bridge also does the right thing on migration, by notifying that the old +entry is deleted, so that does not need to be special-cased in DSA. When +it is deleted, we just need to delete our static FDB entry towards the +CPU too, and wait. + +The problem is that DSA currently only cares about SWITCHDEV_FDB_ADD_TO_DEVICE +events received on its own interfaces, such as static FDB entries. + +Luckily we can change that, and DSA can listen to all switchdev FDB +add/del events in the system and figure out if those events were emitted +by a bridge that spans at least one of DSA's own ports. In case that is +true, DSA will also offload that address towards its own CPU port, in +the eventuality that there might be bridge clients attached to the DSA +switch who want to talk to the station connected to the foreign +interface. + +In terms of implementation, we need to keep the fdb_info->added_by_user +check for the case where the switchdev event was targeted directly at a +DSA switch port. But we don't need to look at that flag for snooped +events. So the check is currently too late, we need to move it earlier. +This also simplifies the code a bit, since we avoid uselessly allocating +and freeing switchdev_work. + +We could probably do some improvements in the future. For example, +multi-bridge support is rudimentary at the moment. If there are two +bridges spanning a DSA switch's ports, and both of them need to service +the same MAC address, then what will happen is that the migration of one +of those stations will trigger the deletion of the FDB entry from the +CPU port while it is still used by other bridge. That could be improved +with reference counting but is left for another time. + +This behavior needs to be enabled at driver level by setting +ds->assisted_learning_on_cpu_port = true. This is because we don't want +to inflict a potential performance penalty (accesses through +MDIO/I2C/SPI are expensive) to hardware that really doesn't need it +because address learning on the CPU port works there. + +Reported-by: DENG Qingfang +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 5 +++++ + net/dsa/slave.c | 66 +++++++++++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 60 insertions(+), 11 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -317,6 +317,11 @@ struct dsa_switch { + */ + bool untag_bridge_pvid; + ++ /* Let DSA manage the FDB entries towards the CPU, based on the ++ * software bridge database. ++ */ ++ bool assisted_learning_on_cpu_port; ++ + /* In case vlan_filtering_is_global is set, the VLAN awareness state + * should be retrieved from here and not from the per-port settings. + */ +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2149,6 +2149,28 @@ static void dsa_slave_switchdev_event_wo + dev_put(dp->slave); + } + ++static int dsa_lower_dev_walk(struct net_device *lower_dev, ++ struct netdev_nested_priv *priv) ++{ ++ if (dsa_slave_dev_check(lower_dev)) { ++ priv->data = (void *)netdev_priv(lower_dev); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static struct dsa_slave_priv *dsa_slave_dev_lower_find(struct net_device *dev) ++{ ++ struct netdev_nested_priv priv = { ++ .data = NULL, ++ }; ++ ++ netdev_walk_all_lower_dev_rcu(dev, dsa_lower_dev_walk, &priv); ++ ++ return (struct dsa_slave_priv *)priv.data; ++} ++ + /* Called under rcu_read_lock() */ + static int dsa_slave_switchdev_event(struct notifier_block *unused, + unsigned long event, void *ptr) +@@ -2167,10 +2189,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: +- if (!dsa_slave_dev_check(dev)) +- return NOTIFY_DONE; ++ fdb_info = ptr; ++ ++ if (dsa_slave_dev_check(dev)) { ++ if (!fdb_info->added_by_user) ++ return NOTIFY_OK; ++ ++ dp = dsa_slave_to_port(dev); ++ } else { ++ /* Snoop addresses learnt on foreign interfaces ++ * bridged with us, for switches that don't ++ * automatically learn SA from CPU-injected traffic ++ */ ++ struct net_device *br_dev; ++ struct dsa_slave_priv *p; ++ ++ br_dev = netdev_master_upper_dev_get_rcu(dev); ++ if (!br_dev) ++ return NOTIFY_DONE; ++ ++ if (!netif_is_bridge_master(br_dev)) ++ return NOTIFY_DONE; ++ ++ p = dsa_slave_dev_lower_find(br_dev); ++ if (!p) ++ return NOTIFY_DONE; + +- dp = dsa_slave_to_port(dev); ++ dp = p->dp->cpu_dp; ++ ++ if (!dp->ds->assisted_learning_on_cpu_port) ++ return NOTIFY_DONE; ++ } + + if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) + return NOTIFY_DONE; +@@ -2185,18 +2234,13 @@ static int dsa_slave_switchdev_event(str + switchdev_work->port = dp->index; + switchdev_work->event = event; + +- fdb_info = ptr; +- +- if (!fdb_info->added_by_user) { +- kfree(switchdev_work); +- return NOTIFY_OK; +- } +- + ether_addr_copy(switchdev_work->addr, + fdb_info->addr); + switchdev_work->vid = fdb_info->vid; + +- dev_hold(dev); ++ /* Hold a reference on the slave for dsa_fdb_offload_notify */ ++ if (dsa_is_user_port(dp->ds, dp->index)) ++ dev_hold(dev); + dsa_schedule_work(&switchdev_work->work); + break; + default: diff --git a/target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch b/target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch new file mode 100644 index 0000000000..f3a6f948ad --- /dev/null +++ b/target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch @@ -0,0 +1,84 @@ +From c3b8e07909dbe67b0d580416c1a5257643a73be7 Mon Sep 17 00:00:00 2001 +From: Ilya Lipnitskiy +Date: Fri, 12 Mar 2021 00:07:03 -0800 +Subject: [PATCH] net: dsa: mt7530: setup core clock even in TRGMII mode + +A recent change to MIPS ralink reset logic made it so mt7530 actually +resets the switch on platforms such as mt7621 (where bit 2 is the reset +line for the switch). That exposed an issue where the switch would not +function properly in TRGMII mode after a reset. + +Reconfigure core clock in TRGMII mode to fix the issue. + +Tested on Ubiquiti ER-X (MT7621) with TRGMII mode enabled. + +Fixes: 3f9ef7785a9c ("MIPS: ralink: manage low reset lines") +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 52 +++++++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 27 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -436,34 +436,32 @@ mt7530_pad_clk_setup(struct dsa_switch * + TD_DM_DRVP(8) | TD_DM_DRVN(8)); + + /* Setup core clock for MT7530 */ +- if (!trgint) { +- /* Disable MT7530 core clock */ +- core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); +- +- /* Disable PLL, since phy_device has not yet been created +- * provided for phy_[read,write]_mmd_indirect is called, we +- * provide our own core_write_mmd_indirect to complete this +- * function. +- */ +- core_write_mmd_indirect(priv, +- CORE_GSWPLL_GRP1, +- MDIO_MMD_VEND2, +- 0); +- +- /* Set core clock into 500Mhz */ +- core_write(priv, CORE_GSWPLL_GRP2, +- RG_GSWPLL_POSDIV_500M(1) | +- RG_GSWPLL_FBKDIV_500M(25)); +- +- /* Enable PLL */ +- core_write(priv, CORE_GSWPLL_GRP1, +- RG_GSWPLL_EN_PRE | +- RG_GSWPLL_POSDIV_200M(2) | +- RG_GSWPLL_FBKDIV_200M(32)); +- +- /* Enable MT7530 core clock */ +- core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); +- } ++ /* Disable MT7530 core clock */ ++ core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); ++ ++ /* Disable PLL, since phy_device has not yet been created ++ * provided for phy_[read,write]_mmd_indirect is called, we ++ * provide our own core_write_mmd_indirect to complete this ++ * function. ++ */ ++ core_write_mmd_indirect(priv, ++ CORE_GSWPLL_GRP1, ++ MDIO_MMD_VEND2, ++ 0); ++ ++ /* Set core clock into 500Mhz */ ++ core_write(priv, CORE_GSWPLL_GRP2, ++ RG_GSWPLL_POSDIV_500M(1) | ++ RG_GSWPLL_FBKDIV_500M(25)); ++ ++ /* Enable PLL */ ++ core_write(priv, CORE_GSWPLL_GRP1, ++ RG_GSWPLL_EN_PRE | ++ RG_GSWPLL_POSDIV_200M(2) | ++ RG_GSWPLL_FBKDIV_200M(32)); ++ ++ /* Enable MT7530 core clock */ ++ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); + + /* Setup the MT7530 TRGMII Tx Clock */ + core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); diff --git a/target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch b/target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch new file mode 100644 index 0000000000..9e5047a16b --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch @@ -0,0 +1,181 @@ +From 429a0edeefd88cbfca5c417dfb8561047bb50769 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Mon, 25 Jan 2021 12:43:22 +0800 +Subject: [PATCH] net: dsa: mt7530: MT7530 optional GPIO support + +MT7530's LED controller can drive up to 15 LED/GPIOs. + +Add support for GPIO control and allow users to use its GPIOs by +setting gpio-controller property in device tree. + +Signed-off-by: DENG Qingfang +Reviewed-by: Linus Walleij +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 110 +++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 20 +++++++ + 2 files changed, 130 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + + #include "mt7530.h" +@@ -1534,6 +1535,109 @@ mtk_get_tag_protocol(struct dsa_switch * + } + } + ++static inline u32 ++mt7530_gpio_to_bit(unsigned int offset) ++{ ++ /* Map GPIO offset to register bit ++ * [ 2: 0] port 0 LED 0..2 as GPIO 0..2 ++ * [ 6: 4] port 1 LED 0..2 as GPIO 3..5 ++ * [10: 8] port 2 LED 0..2 as GPIO 6..8 ++ * [14:12] port 3 LED 0..2 as GPIO 9..11 ++ * [18:16] port 4 LED 0..2 as GPIO 12..14 ++ */ ++ return BIT(offset + offset / 3); ++} ++ ++static int ++mt7530_gpio_get(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct mt7530_priv *priv = gpiochip_get_data(gc); ++ u32 bit = mt7530_gpio_to_bit(offset); ++ ++ return !!(mt7530_read(priv, MT7530_LED_GPIO_DATA) & bit); ++} ++ ++static void ++mt7530_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ struct mt7530_priv *priv = gpiochip_get_data(gc); ++ u32 bit = mt7530_gpio_to_bit(offset); ++ ++ if (value) ++ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit); ++ else ++ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit); ++} ++ ++static int ++mt7530_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct mt7530_priv *priv = gpiochip_get_data(gc); ++ u32 bit = mt7530_gpio_to_bit(offset); ++ ++ return (mt7530_read(priv, MT7530_LED_GPIO_DIR) & bit) ? ++ GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; ++} ++ ++static int ++mt7530_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct mt7530_priv *priv = gpiochip_get_data(gc); ++ u32 bit = mt7530_gpio_to_bit(offset); ++ ++ mt7530_clear(priv, MT7530_LED_GPIO_OE, bit); ++ mt7530_clear(priv, MT7530_LED_GPIO_DIR, bit); ++ ++ return 0; ++} ++ ++static int ++mt7530_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ struct mt7530_priv *priv = gpiochip_get_data(gc); ++ u32 bit = mt7530_gpio_to_bit(offset); ++ ++ mt7530_set(priv, MT7530_LED_GPIO_DIR, bit); ++ ++ if (value) ++ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit); ++ else ++ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit); ++ ++ mt7530_set(priv, MT7530_LED_GPIO_OE, bit); ++ ++ return 0; ++} ++ ++static int ++mt7530_setup_gpio(struct mt7530_priv *priv) ++{ ++ struct device *dev = priv->dev; ++ struct gpio_chip *gc; ++ ++ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); ++ if (!gc) ++ return -ENOMEM; ++ ++ mt7530_write(priv, MT7530_LED_GPIO_OE, 0); ++ mt7530_write(priv, MT7530_LED_GPIO_DIR, 0); ++ mt7530_write(priv, MT7530_LED_IO_MODE, 0); ++ ++ gc->label = "mt7530"; ++ gc->parent = dev; ++ gc->owner = THIS_MODULE; ++ gc->get_direction = mt7530_gpio_get_direction; ++ gc->direction_input = mt7530_gpio_direction_input; ++ gc->direction_output = mt7530_gpio_direction_output; ++ gc->get = mt7530_gpio_get; ++ gc->set = mt7530_gpio_set; ++ gc->base = -1; ++ gc->ngpio = 15; ++ gc->can_sleep = true; ++ ++ return devm_gpiochip_add_data(dev, gc, priv); ++} ++ + static int + mt7530_setup(struct dsa_switch *ds) + { +@@ -1675,6 +1779,12 @@ mt7530_setup(struct dsa_switch *ds) + } + } + ++ if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) { ++ ret = mt7530_setup_gpio(priv); ++ if (ret) ++ return ret; ++ } ++ + mt7530_setup_port5(ds, interface); + + /* Flush the FDB table */ +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -529,6 +529,26 @@ enum mt7531_clk_skew { + #define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16) + #define MT7531_EXT_P_MDIO_12 (2 << 16) + ++/* Registers for LED GPIO control (MT7530 only) ++ * All registers follow this pattern: ++ * [ 2: 0] port 0 ++ * [ 6: 4] port 1 ++ * [10: 8] port 2 ++ * [14:12] port 3 ++ * [18:16] port 4 ++ */ ++ ++/* LED enable, 0: Disable, 1: Enable (Default) */ ++#define MT7530_LED_EN 0x7d00 ++/* LED mode, 0: GPIO mode, 1: PHY mode (Default) */ ++#define MT7530_LED_IO_MODE 0x7d04 ++/* GPIO direction, 0: Input, 1: Output */ ++#define MT7530_LED_GPIO_DIR 0x7d10 ++/* GPIO output enable, 0: Disable, 1: Enable */ ++#define MT7530_LED_GPIO_OE 0x7d14 ++/* GPIO value, 0: Low, 1: High */ ++#define MT7530_LED_GPIO_DATA 0x7d18 ++ + #define MT7530_CREV 0x7ffc + #define CHIP_NAME_SHIFT 16 + #define MT7530_ID 0x7530 diff --git a/target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch b/target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch new file mode 100644 index 0000000000..38dd8a7296 --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch @@ -0,0 +1,120 @@ +From 40b5d2f15c091fa9c854acde91ad2acb504027d7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= +Date: Mon, 12 Apr 2021 08:50:31 +0200 +Subject: [PATCH] net: dsa: mt7530: Add support for EEE features +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds EEE support. + +Signed-off-by: René van Dorst +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 43 ++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 14 ++++++++++++- + 2 files changed, 56 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2371,6 +2371,17 @@ static void mt753x_phylink_mac_link_up(s + mcr |= PMCR_RX_FC_EN; + } + ++ if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, 0) >= 0) { ++ switch (speed) { ++ case SPEED_1000: ++ mcr |= PMCR_FORCE_EEE1G; ++ break; ++ case SPEED_100: ++ mcr |= PMCR_FORCE_EEE100; ++ break; ++ } ++ } ++ + mt7530_set(priv, MT7530_PMCR_P(port), mcr); + } + +@@ -2601,6 +2612,36 @@ mt753x_phy_write(struct dsa_switch *ds, + return priv->info->phy_write(ds, port, regnum, val); + } + ++static int mt753x_get_mac_eee(struct dsa_switch *ds, int port, ++ struct ethtool_eee *e) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 eeecr = mt7530_read(priv, MT7530_PMEEECR_P(port)); ++ ++ e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN); ++ e->tx_lpi_timer = GET_LPI_THRESH(eeecr); ++ ++ return 0; ++} ++ ++static int mt753x_set_mac_eee(struct dsa_switch *ds, int port, ++ struct ethtool_eee *e) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 set, mask = LPI_THRESH_MASK | LPI_MODE_EN; ++ ++ if (e->tx_lpi_timer > 0xFFF) ++ return -EINVAL; ++ ++ set = SET_LPI_THRESH(e->tx_lpi_timer); ++ if (!e->tx_lpi_enabled) ++ /* Force LPI Mode without a delay */ ++ set |= LPI_MODE_EN; ++ mt7530_rmw(priv, MT7530_PMEEECR_P(port), mask, set); ++ ++ return 0; ++} ++ + static const struct dsa_switch_ops mt7530_switch_ops = { + .get_tag_protocol = mtk_get_tag_protocol, + .setup = mt753x_setup, +@@ -2629,6 +2670,8 @@ static const struct dsa_switch_ops mt753 + .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, + .phylink_mac_link_down = mt753x_phylink_mac_link_down, + .phylink_mac_link_up = mt753x_phylink_mac_link_up, ++ .get_mac_eee = mt753x_get_mac_eee, ++ .set_mac_eee = mt753x_set_mac_eee, + }; + + static const struct mt753x_info mt753x_table[] = { +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -240,6 +240,8 @@ enum mt7530_vlan_port_attr { + #define PMCR_RX_EN BIT(13) + #define PMCR_BACKOFF_EN BIT(9) + #define PMCR_BACKPR_EN BIT(8) ++#define PMCR_FORCE_EEE1G BIT(7) ++#define PMCR_FORCE_EEE100 BIT(6) + #define PMCR_TX_FC_EN BIT(5) + #define PMCR_RX_FC_EN BIT(4) + #define PMCR_FORCE_SPEED_1000 BIT(3) +@@ -264,7 +266,8 @@ enum mt7530_vlan_port_attr { + #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ + PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ +- PMCR_FORCE_FDX | PMCR_FORCE_LNK) ++ PMCR_FORCE_FDX | PMCR_FORCE_LNK | \ ++ PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100) + #define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \ + PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ + PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ +@@ -273,6 +276,15 @@ enum mt7530_vlan_port_attr { + PMCR_FORCE_SPEED_1000 | \ + PMCR_FORCE_FDX | PMCR_FORCE_LNK) + ++#define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100) ++#define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24) ++#define WAKEUP_TIME_100(x) (((x) & 0xFF) << 16) ++#define LPI_THRESH_MASK GENMASK(15, 4) ++#define LPI_THRESH_SHT 4 ++#define SET_LPI_THRESH(x) (((x) << LPI_THRESH_SHT) & LPI_THRESH_MASK) ++#define GET_LPI_THRESH(x) (((x) & LPI_THRESH_MASK) >> LPI_THRESH_SHT) ++#define LPI_MODE_EN BIT(0) ++ + #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) + #define PMSR_EEE1G BIT(7) + #define PMSR_EEE100M BIT(6) diff --git a/target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch b/target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch new file mode 100644 index 0000000000..60b07e5a3e --- /dev/null +++ b/target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch @@ -0,0 +1,1935 @@ +From 83216e3988cd196183542937c9bd58b279f946af Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 12 Apr 2021 19:47:17 +0200 +Subject: of: net: pass the dst buffer to of_get_mac_address() + +of_get_mac_address() returns a "const void*" pointer to a MAC address. +Lately, support to fetch the MAC address by an NVMEM provider was added. +But this will only work with platform devices. It will not work with +PCI devices (e.g. of an integrated root complex) and esp. not with DSA +ports. + +There is an of_* variant of the nvmem binding which works without +devices. The returned data of a nvmem_cell_read() has to be freed after +use. On the other hand the return of_get_mac_address() points to some +static data without a lifetime. The trick for now, was to allocate a +device resource managed buffer which is then returned. This will only +work if we have an actual device. + +Change it, so that the caller of of_get_mac_address() has to supply a +buffer where the MAC address is written to. Unfortunately, this will +touch all drivers which use the of_get_mac_address(). + +Usually the code looks like: + + const char *addr; + addr = of_get_mac_address(np); + if (!IS_ERR(addr)) + ether_addr_copy(ndev->dev_addr, addr); + +This can then be simply rewritten as: + + of_get_mac_address(np, ndev->dev_addr); + +Sometimes is_valid_ether_addr() is used to test the MAC address. +of_get_mac_address() already makes sure, it just returns a valid MAC +address. Thus we can just test its return code. But we have to be +careful if there are still other sources for the MAC address before the +of_get_mac_address(). In this case we have to keep the +is_valid_ether_addr() call. + +The following coccinelle patch was used to convert common cases to the +new style. Afterwards, I've manually gone over the drivers and fixed the +return code variable: either used a new one or if one was already +available use that. Mansour Moufid, thanks for that coccinelle patch! + + +@a@ +identifier x; +expression y, z; +@@ +- x = of_get_mac_address(y); ++ x = of_get_mac_address(y, z); + <... +- ether_addr_copy(z, x); + ...> + +@@ +identifier a.x; +@@ +- if (<+... x ...+>) {} + +@@ +identifier a.x; +@@ + if (<+... x ...+>) { + ... + } +- else {} + +@@ +identifier a.x; +expression e; +@@ +- if (<+... x ...+>@e) +- {} +- else ++ if (!(e)) + {...} + +@@ +expression x, y, z; +@@ +- x = of_get_mac_address(y, z); ++ of_get_mac_address(y, z); + ... when != x + + +All drivers, except drivers/net/ethernet/aeroflex/greth.c, were +compile-time tested. + +Suggested-by: Andrew Lunn +Signed-off-by: Michael Walle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + arch/arm/mach-mvebu/kirkwood.c | 3 +- + arch/powerpc/sysdev/tsi108_dev.c | 5 +- + drivers/net/ethernet/aeroflex/greth.c | 6 +-- + drivers/net/ethernet/allwinner/sun4i-emac.c | 10 ++-- + drivers/net/ethernet/altera/altera_tse_main.c | 7 +-- + drivers/net/ethernet/arc/emac_main.c | 8 +-- + drivers/net/ethernet/atheros/ag71xx.c | 7 +-- + drivers/net/ethernet/broadcom/bcm4908_enet.c | 7 +-- + drivers/net/ethernet/broadcom/bcmsysport.c | 7 +-- + drivers/net/ethernet/broadcom/bgmac-bcma.c | 10 ++-- + drivers/net/ethernet/broadcom/bgmac-platform.c | 11 ++-- + drivers/net/ethernet/cadence/macb_main.c | 11 ++-- + drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 8 +-- + drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 5 +- + drivers/net/ethernet/davicom/dm9000.c | 10 ++-- + drivers/net/ethernet/ethoc.c | 6 +-- + drivers/net/ethernet/ezchip/nps_enet.c | 7 +-- + drivers/net/ethernet/freescale/fec_main.c | 7 +-- + drivers/net/ethernet/freescale/fec_mpc52xx.c | 7 +-- + drivers/net/ethernet/freescale/fman/mac.c | 9 ++-- + .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 5 +- + drivers/net/ethernet/freescale/gianfar.c | 8 +-- + drivers/net/ethernet/freescale/ucc_geth.c | 5 +- + drivers/net/ethernet/hisilicon/hisi_femac.c | 7 +-- + drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 7 +-- + drivers/net/ethernet/lantiq_xrx200.c | 7 +-- + drivers/net/ethernet/marvell/mv643xx_eth.c | 5 +- + drivers/net/ethernet/marvell/mvneta.c | 6 +-- + .../net/ethernet/marvell/prestera/prestera_main.c | 11 ++-- + drivers/net/ethernet/marvell/pxa168_eth.c | 9 +--- + drivers/net/ethernet/marvell/sky2.c | 8 ++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 ++-- + drivers/net/ethernet/micrel/ks8851_common.c | 7 ++- + drivers/net/ethernet/microchip/lan743x_main.c | 5 +- + drivers/net/ethernet/nxp/lpc_eth.c | 4 +- + drivers/net/ethernet/qualcomm/qca_spi.c | 10 ++-- + drivers/net/ethernet/qualcomm/qca_uart.c | 9 +--- + drivers/net/ethernet/renesas/ravb_main.c | 12 +++-- + drivers/net/ethernet/renesas/sh_eth.c | 5 +- + .../net/ethernet/samsung/sxgbe/sxgbe_platform.c | 13 ++--- + drivers/net/ethernet/socionext/sni_ave.c | 10 ++-- + .../net/ethernet/stmicro/stmmac/dwmac-anarion.c | 2 +- + .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-generic.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-intel-plat.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 2 +- + .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac-visconti.c | 2 +- + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 14 ++--- + .../net/ethernet/stmicro/stmmac/stmmac_platform.h | 2 +- + drivers/net/ethernet/ti/am65-cpsw-nuss.c | 19 ++++--- + drivers/net/ethernet/ti/cpsw.c | 7 +-- + drivers/net/ethernet/ti/cpsw_new.c | 7 +-- + drivers/net/ethernet/ti/davinci_emac.c | 8 +-- + drivers/net/ethernet/ti/netcp_core.c | 7 +-- + drivers/net/ethernet/wiznet/w5100-spi.c | 8 ++- + drivers/net/ethernet/wiznet/w5100.c | 2 +- + drivers/net/ethernet/xilinx/ll_temac_main.c | 8 +-- + drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 15 +++--- + drivers/net/ethernet/xilinx/xilinx_emaclite.c | 8 +-- + drivers/net/wireless/ath/ath9k/init.c | 5 +- + drivers/net/wireless/mediatek/mt76/eeprom.c | 9 +--- + drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 6 +-- + drivers/of/of_net.c | 60 ++++++++++------------ + drivers/staging/octeon/ethernet.c | 10 ++-- + drivers/staging/wfx/main.c | 7 ++- + include/linux/of_net.h | 6 +-- + include/net/dsa.h | 2 +- + net/dsa/dsa2.c | 2 +- + net/dsa/slave.c | 2 +- + net/ethernet/eth.c | 11 ++-- + 85 files changed, 218 insertions(+), 364 deletions(-) + +--- a/arch/arm/mach-mvebu/kirkwood.c ++++ b/arch/arm/mach-mvebu/kirkwood.c +@@ -84,6 +84,7 @@ static void __init kirkwood_dt_eth_fixup + struct device_node *pnp = of_get_parent(np); + struct clk *clk; + struct property *pmac; ++ u8 tmpmac[ETH_ALEN]; + void __iomem *io; + u8 *macaddr; + u32 reg; +@@ -93,7 +94,7 @@ static void __init kirkwood_dt_eth_fixup + + /* skip disabled nodes or nodes with valid MAC address*/ + if (!of_device_is_available(pnp) || +- !IS_ERR(of_get_mac_address(np))) ++ !of_get_mac_address(np, tmpmac)) + goto eth_fixup_skip; + + clk = of_clk_get(pnp, 0); +--- a/arch/powerpc/sysdev/tsi108_dev.c ++++ b/arch/powerpc/sysdev/tsi108_dev.c +@@ -73,7 +73,6 @@ static int __init tsi108_eth_of_init(voi + struct device_node *phy, *mdio; + hw_info tsi_eth_data; + const unsigned int *phy_id; +- const void *mac_addr; + const phandle *ph; + + memset(r, 0, sizeof(r)); +@@ -101,9 +100,7 @@ static int __init tsi108_eth_of_init(voi + goto err; + } + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(tsi_eth_data.mac_addr, mac_addr); ++ of_get_mac_address(np, tsi_eth_data.mac_addr); + + ph = of_get_property(np, "mdio-handle", NULL); + mdio = of_find_node_by_phandle(*ph); +--- a/drivers/net/ethernet/aeroflex/greth.c ++++ b/drivers/net/ethernet/aeroflex/greth.c +@@ -1449,10 +1449,10 @@ static int greth_of_probe(struct platfor + break; + } + if (i == 6) { +- const u8 *addr; ++ u8 addr[ETH_ALEN]; + +- addr = of_get_mac_address(ofdev->dev.of_node); +- if (!IS_ERR(addr)) { ++ err = of_get_mac_address(ofdev->dev.of_node, addr); ++ if (!err) { + for (i = 0; i < 6; i++) + macaddr[i] = (unsigned int) addr[i]; + } else { +--- a/drivers/net/ethernet/allwinner/sun4i-emac.c ++++ b/drivers/net/ethernet/allwinner/sun4i-emac.c +@@ -790,7 +790,6 @@ static int emac_probe(struct platform_de + struct emac_board_info *db; + struct net_device *ndev; + int ret = 0; +- const char *mac_addr; + + ndev = alloc_etherdev(sizeof(struct emac_board_info)); + if (!ndev) { +@@ -853,12 +852,9 @@ static int emac_probe(struct platform_de + } + + /* Read MAC-address from DT */ +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- +- /* Check if the MAC address is valid, if not get a random one */ +- if (!is_valid_ether_addr(ndev->dev_addr)) { ++ ret = of_get_mac_address(np, ndev->dev_addr); ++ if (ret) { ++ /* if the MAC address is invalid get a random one */ + eth_hw_addr_random(ndev); + dev_warn(&pdev->dev, "using random MAC address %pM\n", + ndev->dev_addr); +--- a/drivers/net/ethernet/altera/altera_tse_main.c ++++ b/drivers/net/ethernet/altera/altera_tse_main.c +@@ -1351,7 +1351,6 @@ static int altera_tse_probe(struct platf + struct resource *control_port; + struct resource *dma_res; + struct altera_tse_private *priv; +- const unsigned char *macaddr; + void __iomem *descmap; + const struct of_device_id *of_id = NULL; + +@@ -1528,10 +1527,8 @@ static int altera_tse_probe(struct platf + priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE; + + /* get default MAC address from device tree */ +- macaddr = of_get_mac_address(pdev->dev.of_node); +- if (!IS_ERR(macaddr)) +- ether_addr_copy(ndev->dev_addr, macaddr); +- else ++ ret = of_get_mac_address(pdev->dev.of_node, ndev->dev_addr); ++ if (ret) + eth_hw_addr_random(ndev); + + /* get phy addr and create mdio */ +--- a/drivers/net/ethernet/arc/emac_main.c ++++ b/drivers/net/ethernet/arc/emac_main.c +@@ -857,7 +857,6 @@ int arc_emac_probe(struct net_device *nd + struct device_node *phy_node; + struct phy_device *phydev = NULL; + struct arc_emac_priv *priv; +- const char *mac_addr; + unsigned int id, clock_frequency, irq; + int err; + +@@ -942,11 +941,8 @@ int arc_emac_probe(struct net_device *nd + } + + /* Get MAC address from device tree */ +- mac_addr = of_get_mac_address(dev->of_node); +- +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- else ++ err = of_get_mac_address(dev->of_node, ndev->dev_addr); ++ if (err) + eth_hw_addr_random(ndev); + + arc_emac_set_address_internal(ndev); +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -1856,7 +1856,6 @@ static int ag71xx_probe(struct platform_ + const struct ag71xx_dcfg *dcfg; + struct net_device *ndev; + struct resource *res; +- const void *mac_addr; + int tx_size, err, i; + struct ag71xx *ag; + +@@ -1952,10 +1951,8 @@ static int ag71xx_probe(struct platform_ + ag->stop_desc->ctrl = 0; + ag->stop_desc->next = (u32)ag->stop_desc_dma; + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); +- if (IS_ERR(mac_addr) || !is_valid_ether_addr(ndev->dev_addr)) { ++ err = of_get_mac_address(np, ndev->dev_addr); ++ if (err) { + netif_err(ag, probe, ndev, "invalid MAC address, using random address\n"); + eth_random_addr(ndev->dev_addr); + } +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -2468,7 +2468,6 @@ static int bcm_sysport_probe(struct plat + struct bcm_sysport_priv *priv; + struct device_node *dn; + struct net_device *dev; +- const void *macaddr; + u32 txq, rxq; + int ret; + +@@ -2563,12 +2562,10 @@ static int bcm_sysport_probe(struct plat + } + + /* Initialize netdevice members */ +- macaddr = of_get_mac_address(dn); +- if (IS_ERR(macaddr)) { ++ ret = of_get_mac_address(dn, dev->dev_addr); ++ if (ret) { + dev_warn(&pdev->dev, "using random Ethernet MAC\n"); + eth_hw_addr_random(dev); +- } else { +- ether_addr_copy(dev->dev_addr, macaddr); + } + + SET_NETDEV_DEV(dev, &pdev->dev); +--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c +@@ -115,7 +115,7 @@ static int bgmac_probe(struct bcma_devic + struct ssb_sprom *sprom = &core->bus->sprom; + struct mii_bus *mii_bus; + struct bgmac *bgmac; +- const u8 *mac = NULL; ++ const u8 *mac; + int err; + + bgmac = bgmac_alloc(&core->dev); +@@ -128,11 +128,10 @@ static int bgmac_probe(struct bcma_devic + + bcma_set_drvdata(core, bgmac); + +- if (bgmac->dev->of_node) +- mac = of_get_mac_address(bgmac->dev->of_node); ++ err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); + + /* If no MAC address assigned via device tree, check SPROM */ +- if (IS_ERR_OR_NULL(mac)) { ++ if (err) { + switch (core->core_unit) { + case 0: + mac = sprom->et0mac; +@@ -149,10 +148,9 @@ static int bgmac_probe(struct bcma_devic + err = -ENOTSUPP; + goto err; + } ++ ether_addr_copy(bgmac->net_dev->dev_addr, mac); + } + +- ether_addr_copy(bgmac->net_dev->dev_addr, mac); +- + /* On BCM4706 we need common core to access PHY */ + if (core->id.id == BCMA_CORE_4706_MAC_GBIT && + !core->bus->drv_gmac_cmn.core) { +--- a/drivers/net/ethernet/broadcom/bgmac-platform.c ++++ b/drivers/net/ethernet/broadcom/bgmac-platform.c +@@ -173,7 +173,7 @@ static int bgmac_probe(struct platform_d + struct device_node *np = pdev->dev.of_node; + struct bgmac *bgmac; + struct resource *regs; +- const u8 *mac_addr; ++ int ret; + + bgmac = bgmac_alloc(&pdev->dev); + if (!bgmac) +@@ -192,11 +192,10 @@ static int bgmac_probe(struct platform_d + bgmac->dev = &pdev->dev; + bgmac->dma_dev = &pdev->dev; + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(bgmac->net_dev->dev_addr, mac_addr); +- else +- dev_warn(&pdev->dev, "MAC address not present in device tree\n"); ++ ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); ++ if (ret) ++ dev_warn(&pdev->dev, ++ "MAC address not present in device tree\n"); + + bgmac->irq = platform_get_irq(pdev, 0); + if (bgmac->irq < 0) +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -4479,7 +4479,6 @@ static int macb_probe(struct platform_de + struct net_device *dev; + struct resource *regs; + void __iomem *mem; +- const char *mac; + struct macb *bp; + int err, val; + +@@ -4592,15 +4591,11 @@ static int macb_probe(struct platform_de + if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR) + bp->rx_intr_mask |= MACB_BIT(RXUBR); + +- mac = of_get_mac_address(np); +- if (PTR_ERR(mac) == -EPROBE_DEFER) { +- err = -EPROBE_DEFER; ++ err = of_get_mac_address(np, bp->dev->dev_addr); ++ if (err == -EPROBE_DEFER) + goto err_out_free_netdev; +- } else if (!IS_ERR_OR_NULL(mac)) { +- ether_addr_copy(bp->dev->dev_addr, mac); +- } else { ++ else if (err) + macb_get_hwaddr(bp); +- } + + err = of_get_phy_mode(np, &interface); + if (err) +--- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c ++++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +@@ -1385,7 +1385,6 @@ static int octeon_mgmt_probe(struct plat + struct net_device *netdev; + struct octeon_mgmt *p; + const __be32 *data; +- const u8 *mac; + struct resource *res_mix; + struct resource *res_agl; + struct resource *res_agl_prt_ctl; +@@ -1502,11 +1501,8 @@ static int octeon_mgmt_probe(struct plat + netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM; + netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM - VLAN_HLEN; + +- mac = of_get_mac_address(pdev->dev.of_node); +- +- if (!IS_ERR(mac)) +- ether_addr_copy(netdev->dev_addr, mac); +- else ++ result = of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); ++ if (result) + eth_hw_addr_random(netdev); + + p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); +--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c ++++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +@@ -1474,7 +1474,6 @@ static int bgx_init_of_phy(struct bgx *b + device_for_each_child_node(&bgx->pdev->dev, fwn) { + struct phy_device *pd; + struct device_node *phy_np; +- const char *mac; + + /* Should always be an OF node. But if it is not, we + * cannot handle it, so exit the loop. +@@ -1483,9 +1482,7 @@ static int bgx_init_of_phy(struct bgx *b + if (!node) + break; + +- mac = of_get_mac_address(node); +- if (!IS_ERR(mac)) +- ether_addr_copy(bgx->lmac[lmac].mac, mac); ++ of_get_mac_address(node, bgx->lmac[lmac].mac); + + SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev); + bgx->lmac[lmac].lmacid = lmac; +--- a/drivers/net/ethernet/davicom/dm9000.c ++++ b/drivers/net/ethernet/davicom/dm9000.c +@@ -1388,7 +1388,7 @@ static struct dm9000_plat_data *dm9000_p + { + struct dm9000_plat_data *pdata; + struct device_node *np = dev->of_node; +- const void *mac_addr; ++ int ret; + + if (!IS_ENABLED(CONFIG_OF) || !np) + return ERR_PTR(-ENXIO); +@@ -1402,11 +1402,9 @@ static struct dm9000_plat_data *dm9000_p + if (of_find_property(np, "davicom,no-eeprom", NULL)) + pdata->flags |= DM9000_PLATF_NO_EEPROM; + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(pdata->dev_addr, mac_addr); +- else if (PTR_ERR(mac_addr) == -EPROBE_DEFER) +- return ERR_CAST(mac_addr); ++ ret = of_get_mac_address(np, pdata->dev_addr); ++ if (ret == -EPROBE_DEFER) ++ return ERR_PTR(ret); + + return pdata; + } +--- a/drivers/net/ethernet/ethoc.c ++++ b/drivers/net/ethernet/ethoc.c +@@ -1151,11 +1151,7 @@ static int ethoc_probe(struct platform_d + ether_addr_copy(netdev->dev_addr, pdata->hwaddr); + priv->phy_id = pdata->phy_id; + } else { +- const void *mac; +- +- mac = of_get_mac_address(pdev->dev.of_node); +- if (!IS_ERR(mac)) +- ether_addr_copy(netdev->dev_addr, mac); ++ of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); + priv->phy_id = -1; + } + +--- a/drivers/net/ethernet/ezchip/nps_enet.c ++++ b/drivers/net/ethernet/ezchip/nps_enet.c +@@ -575,7 +575,6 @@ static s32 nps_enet_probe(struct platfor + struct net_device *ndev; + struct nps_enet_priv *priv; + s32 err = 0; +- const char *mac_addr; + + if (!dev->of_node) + return -ENODEV; +@@ -602,10 +601,8 @@ static s32 nps_enet_probe(struct platfor + dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs_base); + + /* set kernel MAC address to dev */ +- mac_addr = of_get_mac_address(dev->of_node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- else ++ err = of_get_mac_address(dev->of_node, ndev->dev_addr); ++ if (err) + eth_hw_addr_random(ndev); + + /* Get IRQ number */ +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1666,6 +1666,7 @@ static void fec_get_mac(struct net_devic + struct fec_enet_private *fep = netdev_priv(ndev); + struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev); + unsigned char *iap, tmpaddr[ETH_ALEN]; ++ int ret; + + /* + * try to get mac address in following order: +@@ -1681,9 +1682,9 @@ static void fec_get_mac(struct net_devic + if (!is_valid_ether_addr(iap)) { + struct device_node *np = fep->pdev->dev.of_node; + if (np) { +- const char *mac = of_get_mac_address(np); +- if (!IS_ERR(mac)) +- iap = (unsigned char *) mac; ++ ret = of_get_mac_address(np, tmpaddr); ++ if (!ret) ++ iap = tmpaddr; + } + } + +--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c ++++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c +@@ -813,7 +813,6 @@ static int mpc52xx_fec_probe(struct plat + const u32 *prop; + int prop_size; + struct device_node *np = op->dev.of_node; +- const char *mac_addr; + + phys_addr_t rx_fifo; + phys_addr_t tx_fifo; +@@ -891,10 +890,8 @@ static int mpc52xx_fec_probe(struct plat + * + * First try to read MAC address from DT + */ +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) { +- ether_addr_copy(ndev->dev_addr, mac_addr); +- } else { ++ rv = of_get_mac_address(np, ndev->dev_addr); ++ if (rv) { + struct mpc52xx_fec __iomem *fec = priv->fec; + + /* +--- a/drivers/net/ethernet/freescale/fman/mac.c ++++ b/drivers/net/ethernet/freescale/fman/mac.c +@@ -616,7 +616,6 @@ static int mac_probe(struct platform_dev + struct platform_device *of_dev; + struct resource res; + struct mac_priv_s *priv; +- const u8 *mac_addr; + u32 val; + u8 fman_id; + phy_interface_t phy_if; +@@ -734,11 +733,9 @@ static int mac_probe(struct platform_dev + priv->cell_index = (u8)val; + + /* Get the MAC address */ +- mac_addr = of_get_mac_address(mac_node); +- if (IS_ERR(mac_addr)) ++ err = of_get_mac_address(mac_node, mac_dev->addr); ++ if (err) + dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node); +- else +- ether_addr_copy(mac_dev->addr, mac_addr); + + /* Get the port handles */ + nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL); +@@ -864,7 +861,7 @@ static int mac_probe(struct platform_dev + if (err < 0) + dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); + +- if (!IS_ERR(mac_addr)) ++ if (!is_zero_ether_addr(mac_dev->addr)) + dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); + + priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); +--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c ++++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +@@ -918,7 +918,6 @@ static int fs_enet_probe(struct platform + const u32 *data; + struct clk *clk; + int err; +- const u8 *mac_addr; + const char *phy_connection_type; + int privsize, len, ret = -ENODEV; + +@@ -1006,9 +1005,7 @@ static int fs_enet_probe(struct platform + spin_lock_init(&fep->lock); + spin_lock_init(&fep->tx_lock); + +- mac_addr = of_get_mac_address(ofdev->dev.of_node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); ++ of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr); + + ret = fep->ops->allocate_bd(ndev); + if (ret) +--- a/drivers/net/ethernet/freescale/gianfar.c ++++ b/drivers/net/ethernet/freescale/gianfar.c +@@ -641,7 +641,6 @@ static phy_interface_t gfar_get_interfac + static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) + { + const char *model; +- const void *mac_addr; + int err = 0, i; + phy_interface_t interface; + struct net_device *dev = NULL; +@@ -783,11 +782,8 @@ static int gfar_of_init(struct platform_ + if (stash_len || stash_idx) + priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING; + +- mac_addr = of_get_mac_address(np); +- +- if (!IS_ERR(mac_addr)) { +- ether_addr_copy(dev->dev_addr, mac_addr); +- } else { ++ err = of_get_mac_address(np, dev->dev_addr); ++ if (err) { + eth_hw_addr_random(dev); + dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr); + } +--- a/drivers/net/ethernet/freescale/ucc_geth.c ++++ b/drivers/net/ethernet/freescale/ucc_geth.c +@@ -3696,7 +3696,6 @@ static int ucc_geth_probe(struct platfor + int err, ucc_num, max_speed = 0; + const unsigned int *prop; + const char *sprop; +- const void *mac_addr; + phy_interface_t phy_interface; + static const int enet_to_speed[] = { + SPEED_10, SPEED_10, SPEED_10, +@@ -3906,9 +3905,7 @@ static int ucc_geth_probe(struct platfor + goto err_free_netdev; + } + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(dev->dev_addr, mac_addr); ++ of_get_mac_address(np, dev->dev_addr); + + ugeth->ug_info = ug_info; + ugeth->dev = device; +--- a/drivers/net/ethernet/hisilicon/hisi_femac.c ++++ b/drivers/net/ethernet/hisilicon/hisi_femac.c +@@ -772,7 +772,6 @@ static int hisi_femac_drv_probe(struct p + struct net_device *ndev; + struct hisi_femac_priv *priv; + struct phy_device *phy; +- const char *mac_addr; + int ret; + + ndev = alloc_etherdev(sizeof(*priv)); +@@ -842,10 +841,8 @@ static int hisi_femac_drv_probe(struct p + (unsigned long)phy->phy_id, + phy_modes(phy->interface)); + +- mac_addr = of_get_mac_address(node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- if (!is_valid_ether_addr(ndev->dev_addr)) { ++ ret = of_get_mac_address(node, ndev->dev_addr); ++ if (ret) { + eth_hw_addr_random(ndev); + dev_warn(dev, "using random MAC address %pM\n", + ndev->dev_addr); +--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c ++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +@@ -1098,7 +1098,6 @@ static int hix5hd2_dev_probe(struct plat + struct net_device *ndev; + struct hix5hd2_priv *priv; + struct mii_bus *bus; +- const char *mac_addr; + int ret; + + ndev = alloc_etherdev(sizeof(struct hix5hd2_priv)); +@@ -1220,10 +1219,8 @@ static int hix5hd2_dev_probe(struct plat + goto out_phy_node; + } + +- mac_addr = of_get_mac_address(node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- if (!is_valid_ether_addr(ndev->dev_addr)) { ++ ret = of_get_mac_address(node, ndev->dev_addr); ++ if (ret) { + eth_hw_addr_random(ndev); + netdev_warn(ndev, "using random MAC address %pM\n", + ndev->dev_addr); +--- a/drivers/net/ethernet/lantiq_xrx200.c ++++ b/drivers/net/ethernet/lantiq_xrx200.c +@@ -440,7 +440,6 @@ static int xrx200_probe(struct platform_ + struct resource *res; + struct xrx200_priv *priv; + struct net_device *net_dev; +- const u8 *mac; + int err; + + /* alloc the network device */ +@@ -484,10 +483,8 @@ static int xrx200_probe(struct platform_ + return PTR_ERR(priv->clk); + } + +- mac = of_get_mac_address(np); +- if (!IS_ERR(mac)) +- ether_addr_copy(net_dev->dev_addr, mac); +- else ++ err = of_get_mac_address(np, net_dev->dev_addr); ++ if (err) + eth_hw_addr_random(net_dev); + + /* bring up the dma engine and IP core */ +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -2700,7 +2700,6 @@ static int mv643xx_eth_shared_of_add_por + struct platform_device *ppdev; + struct mv643xx_eth_platform_data ppd; + struct resource res; +- const char *mac_addr; + int ret; + int dev_num = 0; + +@@ -2731,9 +2730,7 @@ static int mv643xx_eth_shared_of_add_por + return -EINVAL; + } + +- mac_addr = of_get_mac_address(pnp); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ppd.mac_addr, mac_addr); ++ of_get_mac_address(pnp, ppd.mac_addr); + + mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size); + mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr); +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -5062,7 +5062,6 @@ static int mvneta_probe(struct platform_ + struct net_device *dev; + struct phylink *phylink; + struct phy *comphy; +- const char *dt_mac_addr; + char hw_mac_addr[ETH_ALEN]; + phy_interface_t phy_mode; + const char *mac_from; +@@ -5158,10 +5157,9 @@ static int mvneta_probe(struct platform_ + goto err_free_ports; + } + +- dt_mac_addr = of_get_mac_address(dn); +- if (!IS_ERR(dt_mac_addr)) { ++ err = of_get_mac_address(dn, dev->dev_addr); ++ if (!err) { + mac_from = "device tree"; +- ether_addr_copy(dev->dev_addr, dt_mac_addr); + } else { + mvneta_get_mac_addr(pp, hw_mac_addr); + if (is_valid_ether_addr(hw_mac_addr)) { +--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c +@@ -466,20 +466,17 @@ static int prestera_switch_set_base_mac_ + { + struct device_node *base_mac_np; + struct device_node *np; +- const char *base_mac; ++ int ret; + + np = of_find_compatible_node(NULL, NULL, "marvell,prestera"); + base_mac_np = of_parse_phandle(np, "base-mac-provider", 0); + +- base_mac = of_get_mac_address(base_mac_np); +- of_node_put(base_mac_np); +- if (!IS_ERR(base_mac)) +- ether_addr_copy(sw->base_mac, base_mac); +- +- if (!is_valid_ether_addr(sw->base_mac)) { ++ ret = of_get_mac_address(base_mac_np, sw->base_mac); ++ if (ret) { + eth_random_addr(sw->base_mac); + dev_info(prestera_dev(sw), "using random base mac address\n"); + } ++ of_node_put(base_mac_np); + + return prestera_hw_switch_mac_set(sw, sw->base_mac); + } +--- a/drivers/net/ethernet/marvell/pxa168_eth.c ++++ b/drivers/net/ethernet/marvell/pxa168_eth.c +@@ -1392,7 +1392,6 @@ static int pxa168_eth_probe(struct platf + struct resource *res; + struct clk *clk; + struct device_node *np; +- const unsigned char *mac_addr = NULL; + int err; + + printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n"); +@@ -1435,12 +1434,8 @@ static int pxa168_eth_probe(struct platf + + INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); + +- if (pdev->dev.of_node) +- mac_addr = of_get_mac_address(pdev->dev.of_node); +- +- if (!IS_ERR_OR_NULL(mac_addr)) { +- ether_addr_copy(dev->dev_addr, mac_addr); +- } else { ++ err = of_get_mac_address(pdev->dev.of_node, dev->dev_addr); ++ if (err) { + /* try reading the mac address, if set by the bootloader */ + pxa168_eth_get_mac_address(dev, dev->dev_addr); + if (!is_valid_ether_addr(dev->dev_addr)) { +--- a/drivers/net/ethernet/marvell/sky2.c ++++ b/drivers/net/ethernet/marvell/sky2.c +@@ -4725,7 +4725,7 @@ static struct net_device *sky2_init_netd + { + struct sky2_port *sky2; + struct net_device *dev = alloc_etherdev(sizeof(*sky2)); +- const void *iap; ++ int ret; + + if (!dev) + return NULL; +@@ -4795,10 +4795,8 @@ static struct net_device *sky2_init_netd + * 1) from device tree data + * 2) from internal registers set by bootloader + */ +- iap = of_get_mac_address(hw->pdev->dev.of_node); +- if (!IS_ERR(iap)) +- ether_addr_copy(dev->dev_addr, iap); +- else ++ ret = of_get_mac_address(hw->pdev->dev.of_node, dev->dev_addr); ++ if (ret) + memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, + ETH_ALEN); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2580,14 +2580,11 @@ static int __init mtk_init(struct net_de + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; +- const char *mac_addr; ++ int ret; + +- mac_addr = of_get_mac_address(mac->of_node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(dev->dev_addr, mac_addr); +- +- /* If the mac address is invalid, use random mac address */ +- if (!is_valid_ether_addr(dev->dev_addr)) { ++ ret = of_get_mac_address(mac->of_node, dev->dev_addr); ++ if (ret) { ++ /* If the mac address is invalid, use random mac address */ + eth_hw_addr_random(dev); + dev_err(eth->dev, "generated random MAC address %pM\n", + dev->dev_addr); +--- a/drivers/net/ethernet/micrel/ks8851_common.c ++++ b/drivers/net/ethernet/micrel/ks8851_common.c +@@ -194,11 +194,10 @@ static void ks8851_read_mac_addr(struct + static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) + { + struct net_device *dev = ks->netdev; +- const u8 *mac_addr; ++ int ret; + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) { +- ether_addr_copy(dev->dev_addr, mac_addr); ++ ret = of_get_mac_address(np, dev->dev_addr); ++ if (!ret) { + ks8851_write_mac_addr(dev); + return; + } +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -2831,7 +2831,6 @@ static int lan743x_pcidev_probe(struct p + { + struct lan743x_adapter *adapter = NULL; + struct net_device *netdev = NULL; +- const void *mac_addr; + int ret = -ENODEV; + + netdev = devm_alloc_etherdev(&pdev->dev, +@@ -2848,9 +2847,7 @@ static int lan743x_pcidev_probe(struct p + NETIF_MSG_IFDOWN | NETIF_MSG_TX_QUEUED; + netdev->max_mtu = LAN743X_MAX_FRAME_SIZE; + +- mac_addr = of_get_mac_address(pdev->dev.of_node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(adapter->mac_address, mac_addr); ++ of_get_mac_address(pdev->dev.of_node, adapter->mac_address); + + ret = lan743x_pci_init(adapter, pdev); + if (ret) +--- a/drivers/net/ethernet/nxp/lpc_eth.c ++++ b/drivers/net/ethernet/nxp/lpc_eth.c +@@ -1347,9 +1347,7 @@ static int lpc_eth_drv_probe(struct plat + __lpc_get_mac(pldat, ndev->dev_addr); + + if (!is_valid_ether_addr(ndev->dev_addr)) { +- const char *macaddr = of_get_mac_address(np); +- if (!IS_ERR(macaddr)) +- ether_addr_copy(ndev->dev_addr, macaddr); ++ of_get_mac_address(np, ndev->dev_addr); + } + if (!is_valid_ether_addr(ndev->dev_addr)) + eth_hw_addr_random(ndev); +--- a/drivers/net/ethernet/qualcomm/qca_spi.c ++++ b/drivers/net/ethernet/qualcomm/qca_spi.c +@@ -885,7 +885,7 @@ qca_spi_probe(struct spi_device *spi) + struct net_device *qcaspi_devs = NULL; + u8 legacy_mode = 0; + u16 signature; +- const char *mac; ++ int ret; + + if (!spi->dev.of_node) { + dev_err(&spi->dev, "Missing device tree\n"); +@@ -962,12 +962,8 @@ qca_spi_probe(struct spi_device *spi) + + spi_set_drvdata(spi, qcaspi_devs); + +- mac = of_get_mac_address(spi->dev.of_node); +- +- if (!IS_ERR(mac)) +- ether_addr_copy(qca->net_dev->dev_addr, mac); +- +- if (!is_valid_ether_addr(qca->net_dev->dev_addr)) { ++ ret = of_get_mac_address(spi->dev.of_node, qca->net_dev->dev_addr); ++ if (ret) { + eth_hw_addr_random(qca->net_dev); + dev_info(&spi->dev, "Using random MAC address: %pM\n", + qca->net_dev->dev_addr); +--- a/drivers/net/ethernet/qualcomm/qca_uart.c ++++ b/drivers/net/ethernet/qualcomm/qca_uart.c +@@ -323,7 +323,6 @@ static int qca_uart_probe(struct serdev_ + { + struct net_device *qcauart_dev = alloc_etherdev(sizeof(struct qcauart)); + struct qcauart *qca; +- const char *mac; + u32 speed = 115200; + int ret; + +@@ -348,12 +347,8 @@ static int qca_uart_probe(struct serdev_ + + of_property_read_u32(serdev->dev.of_node, "current-speed", &speed); + +- mac = of_get_mac_address(serdev->dev.of_node); +- +- if (!IS_ERR(mac)) +- ether_addr_copy(qca->net_dev->dev_addr, mac); +- +- if (!is_valid_ether_addr(qca->net_dev->dev_addr)) { ++ ret = of_get_mac_address(serdev->dev.of_node, qca->net_dev->dev_addr); ++ if (ret) { + eth_hw_addr_random(qca->net_dev); + dev_info(&serdev->dev, "Using random MAC address: %pM\n", + qca->net_dev->dev_addr); +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -109,11 +109,13 @@ static void ravb_set_buffer_align(struct + * Ethernet AVB device doesn't have ROM for MAC address. + * This function gets the MAC address that was used by a bootloader. + */ +-static void ravb_read_mac_address(struct net_device *ndev, const u8 *mac) ++static void ravb_read_mac_address(struct device_node *np, ++ struct net_device *ndev) + { +- if (!IS_ERR(mac)) { +- ether_addr_copy(ndev->dev_addr, mac); +- } else { ++ int ret; ++ ++ ret = of_get_mac_address(np, ndev->dev_addr); ++ if (ret) { + u32 mahr = ravb_read(ndev, MAHR); + u32 malr = ravb_read(ndev, MALR); + +@@ -2189,7 +2191,7 @@ static int ravb_probe(struct platform_de + priv->msg_enable = RAVB_DEF_MSG_ENABLE; + + /* Read and set MAC address */ +- ravb_read_mac_address(ndev, of_get_mac_address(np)); ++ ravb_read_mac_address(np, ndev); + if (!is_valid_ether_addr(ndev->dev_addr)) { + dev_warn(&pdev->dev, + "no valid MAC address supplied, using a random one\n"); +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -3145,7 +3145,6 @@ static struct sh_eth_plat_data *sh_eth_p + struct device_node *np = dev->of_node; + struct sh_eth_plat_data *pdata; + phy_interface_t interface; +- const char *mac_addr; + int ret; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); +@@ -3157,9 +3156,7 @@ static struct sh_eth_plat_data *sh_eth_p + return NULL; + pdata->phy_interface = interface; + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(pdata->mac_addr, mac_addr); ++ of_get_mac_address(np, pdata->mac_addr); + + pdata->no_ether_link = + of_property_read_bool(np, "renesas,no-ether-link"); +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +@@ -25,8 +25,7 @@ + + #ifdef CONFIG_OF + static int sxgbe_probe_config_dt(struct platform_device *pdev, +- struct sxgbe_plat_data *plat, +- const char **mac) ++ struct sxgbe_plat_data *plat) + { + struct device_node *np = pdev->dev.of_node; + struct sxgbe_dma_cfg *dma_cfg; +@@ -35,7 +34,6 @@ static int sxgbe_probe_config_dt(struct + if (!np) + return -ENODEV; + +- *mac = of_get_mac_address(np); + err = of_get_phy_mode(np, &plat->interface); + if (err && err != -ENODEV) + return err; +@@ -63,8 +61,7 @@ static int sxgbe_probe_config_dt(struct + } + #else + static int sxgbe_probe_config_dt(struct platform_device *pdev, +- struct sxgbe_plat_data *plat, +- const char **mac) ++ struct sxgbe_plat_data *plat) + { + return -ENOSYS; + } +@@ -85,7 +82,6 @@ static int sxgbe_platform_probe(struct p + void __iomem *addr; + struct sxgbe_priv_data *priv = NULL; + struct sxgbe_plat_data *plat_dat = NULL; +- const char *mac = NULL; + struct net_device *ndev = platform_get_drvdata(pdev); + struct device_node *node = dev->of_node; + +@@ -101,7 +97,7 @@ static int sxgbe_platform_probe(struct p + if (!plat_dat) + return -ENOMEM; + +- ret = sxgbe_probe_config_dt(pdev, plat_dat, &mac); ++ ret = sxgbe_probe_config_dt(pdev, plat_dat); + if (ret) { + pr_err("%s: main dt probe failed\n", __func__); + return ret; +@@ -122,8 +118,7 @@ static int sxgbe_platform_probe(struct p + } + + /* Get MAC address if available (DT) */ +- if (!IS_ERR_OR_NULL(mac)) +- ether_addr_copy(priv->dev->dev_addr, mac); ++ of_get_mac_address(node, priv->dev->dev_addr); + + /* Get the TX/RX IRQ numbers */ + for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) { +--- a/drivers/net/ethernet/socionext/sni_ave.c ++++ b/drivers/net/ethernet/socionext/sni_ave.c +@@ -1559,7 +1559,6 @@ static int ave_probe(struct platform_dev + struct ave_private *priv; + struct net_device *ndev; + struct device_node *np; +- const void *mac_addr; + void __iomem *base; + const char *name; + int i, irq, ret; +@@ -1600,12 +1599,9 @@ static int ave_probe(struct platform_dev + + ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN); + +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- +- /* if the mac address is invalid, use random mac address */ +- if (!is_valid_ether_addr(ndev->dev_addr)) { ++ ret = of_get_mac_address(np, ndev->dev_addr); ++ if (ret) { ++ /* if the mac address is invalid, use random mac address */ + eth_hw_addr_random(ndev); + dev_warn(dev, "Using random MAC address: %pM\n", + ndev->dev_addr); +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c +@@ -115,7 +115,7 @@ static int anarion_dwmac_probe(struct pl + if (IS_ERR(gmac)) + return PTR_ERR(gmac); + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +@@ -444,7 +444,7 @@ static int dwc_eth_dwmac_probe(struct pl + if (IS_ERR(stmmac_res.addr)) + return PTR_ERR(stmmac_res.addr); + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +@@ -27,7 +27,7 @@ static int dwmac_generic_probe(struct pl + return ret; + + if (pdev->dev.of_node) { +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) { + dev_err(&pdev->dev, "dt configuration failed\n"); + return PTR_ERR(plat_dat); +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +@@ -226,7 +226,7 @@ static int imx_dwmac_probe(struct platfo + if (!dwmac) + return -ENOMEM; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c +@@ -88,7 +88,7 @@ static int intel_eth_plat_probe(struct p + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) { + dev_err(&pdev->dev, "dt configuration failed\n"); + return PTR_ERR(plat_dat); +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +@@ -255,7 +255,7 @@ static int ipq806x_gmac_probe(struct pla + if (val) + return val; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +@@ -37,7 +37,7 @@ static int lpc18xx_dwmac_probe(struct pl + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +@@ -407,7 +407,7 @@ static int mediatek_dwmac_probe(struct p + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +@@ -52,7 +52,7 @@ static int meson6_dwmac_probe(struct pla + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +@@ -372,7 +372,7 @@ static int meson8b_dwmac_probe(struct pl + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c +@@ -118,7 +118,7 @@ static int oxnas_dwmac_probe(struct plat + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +@@ -461,7 +461,7 @@ static int qcom_ethqos_probe(struct plat + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) { + dev_err(&pdev->dev, "dt configuration failed\n"); + return PTR_ERR(plat_dat); +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +@@ -1392,7 +1392,7 @@ static int rk_gmac_probe(struct platform + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -398,7 +398,7 @@ static int socfpga_dwmac_probe(struct pl + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +@@ -325,7 +325,7 @@ static int sti_dwmac_probe(struct platfo + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +@@ -371,7 +371,7 @@ static int stm32_dwmac_probe(struct plat + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -1202,7 +1202,7 @@ static int sun8i_dwmac_probe(struct plat + if (ret) + return -EINVAL; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +@@ -108,7 +108,7 @@ static int sun7i_gmac_probe(struct platf + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -25,7 +25,7 @@ + + struct stmmac_resources { + void __iomem *addr; +- const char *mac; ++ u8 mac[ETH_ALEN]; + int wol_irq; + int lpi_irq; + int irq; +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -4988,7 +4988,7 @@ int stmmac_dvr_probe(struct device *devi + priv->wol_irq = res->wol_irq; + priv->lpi_irq = res->lpi_irq; + +- if (!IS_ERR_OR_NULL(res->mac)) ++ if (!is_zero_ether_addr(res->mac)) + memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); + + dev_set_drvdata(device, priv->dev); +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -395,7 +395,7 @@ static int stmmac_of_get_mac_mode(struct + * set some private fields that will be used by the main at runtime. + */ + struct plat_stmmacenet_data * +-stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) ++stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) + { + struct device_node *np = pdev->dev.of_node; + struct plat_stmmacenet_data *plat; +@@ -407,12 +407,12 @@ stmmac_probe_config_dt(struct platform_d + if (!plat) + return ERR_PTR(-ENOMEM); + +- *mac = of_get_mac_address(np); +- if (IS_ERR(*mac)) { +- if (PTR_ERR(*mac) == -EPROBE_DEFER) +- return ERR_CAST(*mac); ++ rc = of_get_mac_address(np, mac); ++ if (rc) { ++ if (rc == -EPROBE_DEFER) ++ return ERR_PTR(rc); + +- *mac = NULL; ++ eth_zero_addr(mac); + } + + phy_mode = device_get_phy_mode(&pdev->dev); +@@ -644,7 +644,7 @@ void stmmac_remove_config_dt(struct plat + } + #else + struct plat_stmmacenet_data * +-stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) ++stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) + { + return ERR_PTR(-EINVAL); + } +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +@@ -12,7 +12,7 @@ + #include "stmmac.h" + + struct plat_stmmacenet_data * +-stmmac_probe_config_dt(struct platform_device *pdev, const char **mac); ++stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); + void stmmac_remove_config_dt(struct platform_device *pdev, + struct plat_stmmacenet_data *plat); + +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -1741,7 +1741,6 @@ static int am65_cpsw_nuss_init_slave_por + + for_each_child_of_node(node, port_np) { + struct am65_cpsw_port *port; +- const void *mac_addr; + u32 port_id; + + /* it is not a slave port node, continue */ +@@ -1820,15 +1819,15 @@ static int am65_cpsw_nuss_init_slave_por + return ret; + } + +- mac_addr = of_get_mac_address(port_np); +- if (!IS_ERR(mac_addr)) { +- ether_addr_copy(port->slave.mac_addr, mac_addr); +- } else if (am65_cpsw_am654_get_efuse_macid(port_np, +- port->port_id, +- port->slave.mac_addr) || +- !is_valid_ether_addr(port->slave.mac_addr)) { +- random_ether_addr(port->slave.mac_addr); +- dev_err(dev, "Use random MAC address\n"); ++ ret = of_get_mac_address(port_np, port->slave.mac_addr); ++ if (ret) { ++ am65_cpsw_am654_get_efuse_macid(port_np, ++ port->port_id, ++ port->slave.mac_addr); ++ if (!is_valid_ether_addr(port->slave.mac_addr)) { ++ random_ether_addr(port->slave.mac_addr); ++ dev_err(dev, "Use random MAC address\n"); ++ } + } + } + of_node_put(node); +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -1306,7 +1306,6 @@ static int cpsw_probe_dt(struct cpsw_pla + + for_each_available_child_of_node(node, slave_node) { + struct cpsw_slave_data *slave_data = data->slave_data + i; +- const void *mac_addr = NULL; + int lenp; + const __be32 *parp; + +@@ -1378,10 +1377,8 @@ static int cpsw_probe_dt(struct cpsw_pla + } + + no_phy_slave: +- mac_addr = of_get_mac_address(slave_node); +- if (!IS_ERR(mac_addr)) { +- ether_addr_copy(slave_data->mac_addr, mac_addr); +- } else { ++ ret = of_get_mac_address(slave_node, slave_data->mac_addr); ++ if (ret) { + ret = ti_cm_get_macid(&pdev->dev, i, + slave_data->mac_addr); + if (ret) +--- a/drivers/net/ethernet/ti/cpsw_new.c ++++ b/drivers/net/ethernet/ti/cpsw_new.c +@@ -1267,7 +1267,6 @@ static int cpsw_probe_dt(struct cpsw_com + + for_each_child_of_node(tmp_node, port_np) { + struct cpsw_slave_data *slave_data; +- const void *mac_addr; + u32 port_id; + + ret = of_property_read_u32(port_np, "reg", &port_id); +@@ -1326,10 +1325,8 @@ static int cpsw_probe_dt(struct cpsw_com + goto err_node_put; + } + +- mac_addr = of_get_mac_address(port_np); +- if (!IS_ERR(mac_addr)) { +- ether_addr_copy(slave_data->mac_addr, mac_addr); +- } else { ++ ret = of_get_mac_address(port_np, slave_data->mac_addr); ++ if (ret) { + ret = ti_cm_get_macid(dev, port_id - 1, + slave_data->mac_addr); + if (ret) +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -1699,7 +1699,6 @@ davinci_emac_of_get_pdata(struct platfor + const struct of_device_id *match; + const struct emac_platform_data *auxdata; + struct emac_platform_data *pdata = NULL; +- const u8 *mac_addr; + + if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) + return dev_get_platdata(&pdev->dev); +@@ -1711,11 +1710,8 @@ davinci_emac_of_get_pdata(struct platfor + np = pdev->dev.of_node; + pdata->version = EMAC_VERSION_2; + +- if (!is_valid_ether_addr(pdata->mac_addr)) { +- mac_addr = of_get_mac_address(np); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(pdata->mac_addr, mac_addr); +- } ++ if (!is_valid_ether_addr(pdata->mac_addr)) ++ of_get_mac_address(np, pdata->mac_addr); + + of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", + &pdata->ctrl_reg_offset); +--- a/drivers/net/ethernet/ti/netcp_core.c ++++ b/drivers/net/ethernet/ti/netcp_core.c +@@ -1966,7 +1966,6 @@ static int netcp_create_interface(struct + struct resource res; + void __iomem *efuse = NULL; + u32 efuse_mac = 0; +- const void *mac_addr; + u8 efuse_mac_addr[6]; + u32 temp[2]; + int ret = 0; +@@ -2036,10 +2035,8 @@ static int netcp_create_interface(struct + devm_iounmap(dev, efuse); + devm_release_mem_region(dev, res.start, size); + } else { +- mac_addr = of_get_mac_address(node_interface); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- else ++ ret = of_get_mac_address(node_interface, ndev->dev_addr); ++ if (ret) + eth_random_addr(ndev->dev_addr); + } + +--- a/drivers/net/ethernet/wiznet/w5100-spi.c ++++ b/drivers/net/ethernet/wiznet/w5100-spi.c +@@ -423,8 +423,14 @@ static int w5100_spi_probe(struct spi_de + const struct of_device_id *of_id; + const struct w5100_ops *ops; + kernel_ulong_t driver_data; ++ const void *mac = NULL; ++ u8 tmpmac[ETH_ALEN]; + int priv_size; +- const void *mac = of_get_mac_address(spi->dev.of_node); ++ int ret; ++ ++ ret = of_get_mac_address(spi->dev.of_node, tmpmac); ++ if (!ret) ++ mac = tmpmac; + + if (spi->dev.of_node) { + of_id = of_match_device(w5100_of_match, &spi->dev); +--- a/drivers/net/ethernet/wiznet/w5100.c ++++ b/drivers/net/ethernet/wiznet/w5100.c +@@ -1159,7 +1159,7 @@ int w5100_probe(struct device *dev, cons + INIT_WORK(&priv->setrx_work, w5100_setrx_work); + INIT_WORK(&priv->restart_work, w5100_restart_work); + +- if (!IS_ERR_OR_NULL(mac_addr)) ++ if (mac_addr) + memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); + else + eth_hw_addr_random(ndev); +--- a/drivers/net/ethernet/xilinx/ll_temac_main.c ++++ b/drivers/net/ethernet/xilinx/ll_temac_main.c +@@ -438,7 +438,7 @@ static void temac_do_set_mac_address(str + + static int temac_init_mac_address(struct net_device *ndev, const void *address) + { +- ether_addr_copy(ndev->dev_addr, address); ++ memcpy(ndev->dev_addr, address, ETH_ALEN); + if (!is_valid_ether_addr(ndev->dev_addr)) + eth_hw_addr_random(ndev); + temac_do_set_mac_address(ndev); +@@ -1370,7 +1370,7 @@ static int temac_probe(struct platform_d + struct device_node *temac_np = dev_of_node(&pdev->dev), *dma_np; + struct temac_local *lp; + struct net_device *ndev; +- const void *addr; ++ u8 addr[ETH_ALEN]; + __be32 *p; + bool little_endian; + int rc = 0; +@@ -1563,8 +1563,8 @@ static int temac_probe(struct platform_d + + if (temac_np) { + /* Retrieve the MAC address */ +- addr = of_get_mac_address(temac_np); +- if (IS_ERR(addr)) { ++ rc = of_get_mac_address(temac_np, addr); ++ if (rc) { + dev_err(&pdev->dev, "could not find MAC address\n"); + return -ENODEV; + } +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1831,8 +1831,8 @@ static int axienet_probe(struct platform + struct device_node *np; + struct axienet_local *lp; + struct net_device *ndev; +- const void *mac_addr; + struct resource *ethres; ++ u8 mac_addr[ETH_ALEN]; + int addr_width = 32; + u32 value; + +@@ -2032,13 +2032,14 @@ static int axienet_probe(struct platform + dev_info(&pdev->dev, "Ethernet core IRQ not defined\n"); + + /* Retrieve the MAC address */ +- mac_addr = of_get_mac_address(pdev->dev.of_node); +- if (IS_ERR(mac_addr)) { +- dev_warn(&pdev->dev, "could not find MAC address property: %ld\n", +- PTR_ERR(mac_addr)); +- mac_addr = NULL; ++ ret = of_get_mac_address(pdev->dev.of_node, mac_addr); ++ if (!ret) { ++ axienet_set_mac_address(ndev, mac_addr); ++ } else { ++ dev_warn(&pdev->dev, "could not find MAC address property: %d\n", ++ ret); ++ axienet_set_mac_address(ndev, NULL); + } +- axienet_set_mac_address(ndev, mac_addr); + + lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; + lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; +--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c ++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +@@ -1113,7 +1113,6 @@ static int xemaclite_of_probe(struct pla + struct net_device *ndev = NULL; + struct net_local *lp = NULL; + struct device *dev = &ofdev->dev; +- const void *mac_address; + + int rc = 0; + +@@ -1155,12 +1154,9 @@ static int xemaclite_of_probe(struct pla + lp->next_rx_buf_to_use = 0x0; + lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong"); + lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong"); +- mac_address = of_get_mac_address(ofdev->dev.of_node); + +- if (!IS_ERR(mac_address)) { +- /* Set the MAC address. */ +- ether_addr_copy(ndev->dev_addr, mac_address); +- } else { ++ rc = of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr); ++ if (rc) { + dev_warn(dev, "No MAC address found, using random\n"); + eth_hw_addr_random(ndev); + } +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -618,7 +618,6 @@ static int ath9k_of_init(struct ath_soft + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + enum ath_bus_type bus_type = common->bus_ops->ath_bus_type; +- const char *mac; + char eeprom_name[100]; + int ret; + +@@ -641,9 +640,7 @@ static int ath9k_of_init(struct ath_soft + ah->ah_flags |= AH_NO_EEP_SWAP; + } + +- mac = of_get_mac_address(np); +- if (!IS_ERR(mac)) +- ether_addr_copy(common->macaddr, mac); ++ of_get_mac_address(np, common->macaddr); + + return 0; + } +--- a/drivers/net/wireless/mediatek/mt76/eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/eeprom.c +@@ -90,15 +90,9 @@ out_put_node: + void + mt76_eeprom_override(struct mt76_dev *dev) + { +-#ifdef CONFIG_OF + struct device_node *np = dev->dev->of_node; +- const u8 *mac = NULL; + +- if (np) +- mac = of_get_mac_address(np); +- if (!IS_ERR_OR_NULL(mac)) +- ether_addr_copy(dev->macaddr, mac); +-#endif ++ of_get_mac_address(np, dev->macaddr); + + if (!is_valid_ether_addr(dev->macaddr)) { + eth_random_addr(dev->macaddr); +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -990,11 +990,7 @@ static void rt2x00lib_rate(struct ieee80 + + void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) + { +- const char *mac_addr; +- +- mac_addr = of_get_mac_address(rt2x00dev->dev->of_node); +- if (!IS_ERR(mac_addr)) +- ether_addr_copy(eeprom_mac_addr, mac_addr); ++ of_get_mac_address(rt2x00dev->dev->of_node, eeprom_mac_addr); + + if (!is_valid_ether_addr(eeprom_mac_addr)) { + eth_random_addr(eeprom_mac_addr); +--- a/drivers/of/of_net.c ++++ b/drivers/of/of_net.c +@@ -45,37 +45,29 @@ int of_get_phy_mode(struct device_node * + } + EXPORT_SYMBOL_GPL(of_get_phy_mode); + +-static const void *of_get_mac_addr(struct device_node *np, const char *name) ++static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) + { + struct property *pp = of_find_property(np, name, NULL); + +- if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) +- return pp->value; +- return NULL; ++ if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) { ++ memcpy(addr, pp->value, ETH_ALEN); ++ return 0; ++ } ++ return -ENODEV; + } + +-static const void *of_get_mac_addr_nvmem(struct device_node *np) ++static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) + { +- int ret; +- const void *mac; +- u8 nvmem_mac[ETH_ALEN]; + struct platform_device *pdev = of_find_device_by_node(np); ++ int ret; + + if (!pdev) +- return ERR_PTR(-ENODEV); ++ return -ENODEV; + +- ret = nvmem_get_mac_address(&pdev->dev, &nvmem_mac); +- if (ret) { +- put_device(&pdev->dev); +- return ERR_PTR(ret); +- } +- +- mac = devm_kmemdup(&pdev->dev, nvmem_mac, ETH_ALEN, GFP_KERNEL); ++ ret = nvmem_get_mac_address(&pdev->dev, addr); + put_device(&pdev->dev); +- if (!mac) +- return ERR_PTR(-ENOMEM); + +- return mac; ++ return ret; + } + + /** +@@ -98,24 +90,27 @@ static const void *of_get_mac_addr_nvmem + * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists + * but is all zeros. + * +- * Return: Will be a valid pointer on success and ERR_PTR in case of error. ++ * Return: 0 on success and errno in case of error. + */ +-const void *of_get_mac_address(struct device_node *np) ++int of_get_mac_address(struct device_node *np, u8 *addr) + { +- const void *addr; +- +- addr = of_get_mac_addr(np, "mac-address"); +- if (addr) +- return addr; ++ int ret; + +- addr = of_get_mac_addr(np, "local-mac-address"); +- if (addr) +- return addr; ++ if (!np) ++ return -ENODEV; + +- addr = of_get_mac_addr(np, "address"); +- if (addr) +- return addr; ++ ret = of_get_mac_addr(np, "mac-address", addr); ++ if (!ret) ++ return 0; ++ ++ ret = of_get_mac_addr(np, "local-mac-address", addr); ++ if (!ret) ++ return 0; ++ ++ ret = of_get_mac_addr(np, "address", addr); ++ if (!ret) ++ return 0; + +- return of_get_mac_addr_nvmem(np); ++ return of_get_mac_addr_nvmem(np, addr); + } + EXPORT_SYMBOL(of_get_mac_address); +--- a/drivers/staging/octeon/ethernet.c ++++ b/drivers/staging/octeon/ethernet.c +@@ -407,14 +407,10 @@ static int cvm_oct_common_set_mac_addres + int cvm_oct_common_init(struct net_device *dev) + { + struct octeon_ethernet *priv = netdev_priv(dev); +- const u8 *mac = NULL; ++ int ret; + +- if (priv->of_node) +- mac = of_get_mac_address(priv->of_node); +- +- if (!IS_ERR_OR_NULL(mac)) +- ether_addr_copy(dev->dev_addr, mac); +- else ++ ret = of_get_mac_address(priv->of_node, dev->dev_addr); ++ if (ret) + eth_hw_addr_random(dev); + + /* +--- a/drivers/staging/wfx/main.c ++++ b/drivers/staging/wfx/main.c +@@ -334,7 +334,6 @@ int wfx_probe(struct wfx_dev *wdev) + { + int i; + int err; +- const void *macaddr; + struct gpio_desc *gpio_saved; + + // During first part of boot, gpio_wakeup cannot yet been used. So +@@ -423,9 +422,9 @@ int wfx_probe(struct wfx_dev *wdev) + + for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { + eth_zero_addr(wdev->addresses[i].addr); +- macaddr = of_get_mac_address(wdev->dev->of_node); +- if (!IS_ERR_OR_NULL(macaddr)) { +- ether_addr_copy(wdev->addresses[i].addr, macaddr); ++ err = of_get_mac_address(wdev->dev->of_node, ++ wdev->addresses[i].addr); ++ if (!err) { + wdev->addresses[i].addr[ETH_ALEN - 1] += i; + } else { + ether_addr_copy(wdev->addresses[i].addr, +--- a/include/linux/of_net.h ++++ b/include/linux/of_net.h +@@ -13,7 +13,7 @@ + + struct net_device; + extern int of_get_phy_mode(struct device_node *np, phy_interface_t *interface); +-extern const void *of_get_mac_address(struct device_node *np); ++extern int of_get_mac_address(struct device_node *np, u8 *mac); + extern struct net_device *of_find_net_device_by_node(struct device_node *np); + #else + static inline int of_get_phy_mode(struct device_node *np, +@@ -22,9 +22,9 @@ static inline int of_get_phy_mode(struct + return -ENODEV; + } + +-static inline const void *of_get_mac_address(struct device_node *np) ++static inline int of_get_mac_address(struct device_node *np, u8 *mac) + { +- return ERR_PTR(-ENODEV); ++ return -ENODEV; + } + + static inline struct net_device *of_find_net_device_by_node(struct device_node *np) +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -208,7 +208,7 @@ struct dsa_port { + unsigned int index; + const char *name; + struct dsa_port *cpu_dp; +- const char *mac; ++ u8 mac[ETH_ALEN]; + struct device_node *dn; + unsigned int ageing_time; + bool vlan_filtering; +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -288,7 +288,7 @@ static int dsa_port_setup(struct dsa_por + + break; + case DSA_PORT_TYPE_USER: +- dp->mac = of_get_mac_address(dp->dn); ++ of_get_mac_address(dp->dn, dp->mac); + err = dsa_slave_create(dp); + if (err) + break; +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -1855,7 +1855,7 @@ int dsa_slave_create(struct dsa_port *po + slave_dev->hw_features |= NETIF_F_HW_TC; + slave_dev->features |= NETIF_F_LLTX; + slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; +- if (!IS_ERR_OR_NULL(port->mac)) ++ if (!is_zero_ether_addr(port->mac)) + ether_addr_copy(slave_dev->dev_addr, port->mac); + else + eth_hw_addr_inherit(slave_dev, master); +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -506,13 +506,14 @@ unsigned char * __weak arch_get_platform + + int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr) + { +- const unsigned char *addr = NULL; ++ unsigned char *addr; ++ int ret; + +- if (dev->of_node) +- addr = of_get_mac_address(dev->of_node); +- if (IS_ERR_OR_NULL(addr)) +- addr = arch_get_platform_mac_address(); ++ ret = of_get_mac_address(dev->of_node, mac_addr); ++ if (!ret) ++ return 0; + ++ addr = arch_get_platform_mac_address(); + if (!addr) + return -ENODEV; + diff --git a/target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch b/target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch new file mode 100644 index 0000000000..245c5f3bd6 --- /dev/null +++ b/target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch @@ -0,0 +1,77 @@ +From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Mon, 12 Apr 2021 19:47:18 +0200 +Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices + +of_get_mac_address() already supports fetching the MAC address by an +nvmem provider. But until now, it was just working for platform devices. +Esp. it was not working for DSA ports and PCI devices. It gets more +common that PCI devices have a device tree binding since SoCs contain +integrated root complexes. + +Use the nvmem of_* binding to fetch the nvmem cells by a struct +device_node. We still have to try to read the cell by device first +because there might be a nvmem_cell_lookup associated with that device. + +Signed-off-by: Michael Walle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +--- a/drivers/of/of_net.c ++++ b/drivers/of/of_net.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + /** + * of_get_phy_mode - Get phy mode for given device_node +@@ -59,15 +60,39 @@ static int of_get_mac_addr(struct device + static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) + { + struct platform_device *pdev = of_find_device_by_node(np); ++ struct nvmem_cell *cell; ++ const void *mac; ++ size_t len; + int ret; + +- if (!pdev) +- return -ENODEV; ++ /* Try lookup by device first, there might be a nvmem_cell_lookup ++ * associated with a given device. ++ */ ++ if (pdev) { ++ ret = nvmem_get_mac_address(&pdev->dev, addr); ++ put_device(&pdev->dev); ++ return ret; ++ } ++ ++ cell = of_nvmem_cell_get(np, "mac-address"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ mac = nvmem_cell_read(cell, &len); ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(mac)) ++ return PTR_ERR(mac); ++ ++ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) { ++ kfree(mac); ++ return -EINVAL; ++ } + +- ret = nvmem_get_mac_address(&pdev->dev, addr); +- put_device(&pdev->dev); ++ memcpy(addr, mac, ETH_ALEN); ++ kfree(mac); + +- return ret; ++ return 0; + } + + /** diff --git a/target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch b/target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch new file mode 100644 index 0000000000..6e7f20634f --- /dev/null +++ b/target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch @@ -0,0 +1,42 @@ +From 029497e66bdc762e001880e4c85a91f35a54b1e2 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 19 Sep 2021 13:57:25 +0200 +Subject: [PATCH] net: bgmac-bcma: handle deferred probe error due to + mac-address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Due to the inclusion of nvmem handling into the mac-address getter +function of_get_mac_address() by +commit d01f449c008a ("of_net: add NVMEM support to of_get_mac_address") +it is now possible to get a -EPROBE_DEFER return code. Which did cause +bgmac to assign a random ethernet address. + +This exact issue happened on my Meraki MR32. The nvmem provider is +an EEPROM (at24c64) which gets instantiated once the module +driver is loaded... This happens once the filesystem becomes available. + +With this patch, bgmac_probe() will propagate the -EPROBE_DEFER error. +Then the driver subsystem will reschedule the probe at a later time. + +Cc: Petr Štetiar +Cc: Michael Walle +Fixes: d01f449c008a ("of_net: add NVMEM support to of_get_mac_address") +Signed-off-by: Christian Lamparter +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/bgmac-bcma.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c +@@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_devic + bcma_set_drvdata(core, bgmac); + + err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); ++ if (err == -EPROBE_DEFER) ++ return err; + + /* If no MAC address assigned via device tree, check SPROM */ + if (err) { diff --git a/target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch b/target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch new file mode 100644 index 0000000000..bde62f3b1b --- /dev/null +++ b/target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch @@ -0,0 +1,36 @@ +From 763716a55cb1f480ffe1a9702e6b5d9ea1a80a24 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Sat, 25 Sep 2021 11:36:27 +0000 +Subject: [PATCH] net: bgmac-platform: handle mac-address deferral + +This patch is a replication of Christian Lamparter's "net: bgmac-bcma: +handle deferred probe error due to mac-address" patch for the +bgmac-platform driver [1]. + +As is the case with the bgmac-bcma driver, this change is to cover the +scenario where the MAC address cannot yet be discovered due to reliance +on an nvmem provider which is yet to be instantiated, resulting in a +random address being assigned that has to be manually overridden. + +[1] https://lore.kernel.org/netdev/20210919115725.29064-1-chunkeey@gmail.com + +Signed-off-by: Matthew Hagan +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/bgmac-platform.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bgmac-platform.c ++++ b/drivers/net/ethernet/broadcom/bgmac-platform.c +@@ -193,6 +193,9 @@ static int bgmac_probe(struct platform_d + bgmac->dma_dev = &pdev->dev; + + ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); ++ if (ret == -EPROBE_DEFER) ++ return ret; ++ + if (ret) + dev_warn(&pdev->dev, + "MAC address not present in device tree\n"); diff --git a/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch b/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch new file mode 100644 index 0000000000..6788a2ec35 --- /dev/null +++ b/target/linux/generic/backport-5.15/734-v5.16-0001-net-bgmac-improve-handling-PHY.patch @@ -0,0 +1,84 @@ +From b5375509184dc23d2b7fa0c5ed8763899ccc9674 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 2 Oct 2021 19:58:11 +0200 +Subject: [PATCH] net: bgmac: improve handling PHY +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Use info from DT if available + +It allows describing for example a fixed link. It's more accurate than +just guessing there may be one (depending on a chipset). + +2. Verify PHY ID before trying to connect PHY + +PHY addr 0x1e (30) is special in Broadcom routers and means a switch +connected as MDIO devices instead of a real PHY. Don't try connecting to +it. + +Signed-off-by: Rafał Miłecki +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/bgmac-bcma.c | 33 ++++++++++++++-------- + 1 file changed, 21 insertions(+), 12 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include "bgmac.h" + +@@ -86,17 +87,28 @@ static int bcma_phy_connect(struct bgmac + struct phy_device *phy_dev; + char bus_id[MII_BUS_ID_SIZE + 3]; + ++ /* DT info should be the most accurate */ ++ phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node, ++ bgmac_adjust_link); ++ if (phy_dev) ++ return 0; ++ + /* Connect to the PHY */ +- snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id, +- bgmac->phyaddr); +- phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link, +- PHY_INTERFACE_MODE_MII); +- if (IS_ERR(phy_dev)) { +- dev_err(bgmac->dev, "PHY connection failed\n"); +- return PTR_ERR(phy_dev); ++ if (bgmac->mii_bus && bgmac->phyaddr != BGMAC_PHY_NOREGS) { ++ snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id, ++ bgmac->phyaddr); ++ phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link, ++ PHY_INTERFACE_MODE_MII); ++ if (IS_ERR(phy_dev)) { ++ dev_err(bgmac->dev, "PHY connection failed\n"); ++ return PTR_ERR(phy_dev); ++ } ++ ++ return 0; + } + +- return 0; ++ /* Assume a fixed link to the switch port */ ++ return bgmac_phy_connect_direct(bgmac); + } + + static const struct bcma_device_id bgmac_bcma_tbl[] = { +@@ -297,10 +309,7 @@ static int bgmac_probe(struct bcma_devic + bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset; + bgmac->get_bus_clock = bcma_bgmac_get_bus_clock; + bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32; +- if (bgmac->mii_bus) +- bgmac->phy_connect = bcma_phy_connect; +- else +- bgmac->phy_connect = bgmac_phy_connect_direct; ++ bgmac->phy_connect = bcma_phy_connect; + + err = bgmac_enet_probe(bgmac); + if (err) diff --git a/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch b/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch new file mode 100644 index 0000000000..f134828273 --- /dev/null +++ b/target/linux/generic/backport-5.15/734-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch @@ -0,0 +1,54 @@ +From 45c9d966688e7fad7f24bfc450547d91e4304d0b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 2 Oct 2021 19:58:12 +0200 +Subject: [PATCH] net: bgmac: support MDIO described in DT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Check ethernet controller DT node for "mdio" subnode and use it with +of_mdiobus_register() when present. That allows specifying MDIO and its +PHY devices in a standard DT based way. + +This is required for BCM53573 SoC support. That family is sometimes +called Northstar (by marketing?) but is quite different from it. It uses +different CPU(s) and many different hw blocks. + +One of shared blocks in BCM53573 is Ethernet controller. Switch however +is not SRAB accessible (as it Northstar) but is MDIO attached. + +Signed-off-by: Rafał Miłecki +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c +@@ -10,6 +10,7 @@ + + #include + #include ++#include + #include "bgmac.h" + + static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask, +@@ -211,6 +212,7 @@ struct mii_bus *bcma_mdio_mii_register(s + { + struct bcma_device *core = bgmac->bcma.core; + struct mii_bus *mii_bus; ++ struct device_node *np; + int err; + + mii_bus = mdiobus_alloc(); +@@ -229,7 +231,9 @@ struct mii_bus *bcma_mdio_mii_register(s + mii_bus->parent = &core->dev; + mii_bus->phy_mask = ~(1 << bgmac->phyaddr); + +- err = mdiobus_register(mii_bus); ++ np = of_get_child_by_name(core->dev.of_node, "mdio"); ++ ++ err = of_mdiobus_register(mii_bus, np); + if (err) { + dev_err(&core->dev, "Registration of mii bus failed\n"); + goto err_free_bus; diff --git a/target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch b/target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch new file mode 100644 index 0000000000..b8e6d9b613 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch @@ -0,0 +1,35 @@ +From 5d9e068402dcf7354cc8ee66c2152845306d2ccb Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:51 +0200 +Subject: [PATCH] net: dsa: qca8k: change simple print to dev variant + +Change pr_err and pr_warn to dev variant. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -701,7 +701,7 @@ qca8k_setup(struct dsa_switch *ds) + + /* Make sure that port 0 is the cpu port */ + if (!dsa_is_cpu_port(ds, 0)) { +- pr_err("port 0 is not the CPU port\n"); ++ dev_err(priv->dev, "port 0 is not the CPU port"); + return -EINVAL; + } + +@@ -711,7 +711,7 @@ qca8k_setup(struct dsa_switch *ds) + priv->regmap = devm_regmap_init(ds->dev, NULL, priv, + &qca8k_regmap_config); + if (IS_ERR(priv->regmap)) +- pr_warn("regmap initialization failed"); ++ dev_warn(priv->dev, "regmap initialization failed"); + + ret = qca8k_setup_mdio_bus(priv); + if (ret) diff --git a/target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch b/target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch new file mode 100644 index 0000000000..ff8288d484 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch @@ -0,0 +1,61 @@ +From 2ad255f2faaffb3af786031fba2e7955454b558a Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:52 +0200 +Subject: [PATCH] net: dsa: qca8k: use iopoll macro for qca8k_busy_wait + +Use iopoll macro instead of while loop. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 23 +++++++++++------------ + drivers/net/dsa/qca8k.h | 2 ++ + 2 files changed, 13 insertions(+), 12 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -262,21 +262,20 @@ static struct regmap_config qca8k_regmap + static int + qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + { +- unsigned long timeout; ++ u32 val; ++ int ret; + +- timeout = jiffies + msecs_to_jiffies(20); ++ ret = read_poll_timeout(qca8k_read, val, !(val & mask), ++ 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, ++ priv, reg); + +- /* loop until the busy flag has cleared */ +- do { +- u32 val = qca8k_read(priv, reg); +- int busy = val & mask; ++ /* Check if qca8k_read has failed for a different reason ++ * before returning -ETIMEDOUT ++ */ ++ if (ret < 0 && val < 0) ++ return val; + +- if (!busy) +- break; +- cond_resched(); +- } while (!time_after_eq(jiffies, timeout)); +- +- return time_after_eq(jiffies, timeout); ++ return ret; + } + + static void +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -18,6 +18,8 @@ + #define PHY_ID_QCA8337 0x004dd036 + #define QCA8K_ID_QCA8337 0x13 + ++#define QCA8K_BUSY_WAIT_TIMEOUT 20 ++ + #define QCA8K_NUM_FDB_RECORDS 2048 + + #define QCA8K_CPU_PORT 0 diff --git a/target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch b/target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch new file mode 100644 index 0000000000..c403589874 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch @@ -0,0 +1,86 @@ +From 504bf65931824eda83494e5b5d75686e27ace03e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:53 +0200 +Subject: [PATCH] net: dsa: qca8k: improve qca8k read/write/rmw bus access + +Put bus in local variable to improve faster access to the mdio bus. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 29 ++++++++++++++++------------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -142,17 +142,18 @@ qca8k_set_page(struct mii_bus *bus, u16 + static u32 + qca8k_read(struct qca8k_priv *priv, u32 reg) + { ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + + qca8k_split_addr(reg, &r1, &r2, &page); + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- qca8k_set_page(priv->bus, page); +- val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); ++ qca8k_set_page(bus, page); ++ val = qca8k_mii_read32(bus, 0x10 | r2, r1); + +- mutex_unlock(&priv->bus->mdio_lock); ++ mutex_unlock(&bus->mdio_lock); + + return val; + } +@@ -160,35 +161,37 @@ qca8k_read(struct qca8k_priv *priv, u32 + static void + qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) + { ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + + qca8k_split_addr(reg, &r1, &r2, &page); + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- qca8k_set_page(priv->bus, page); +- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); ++ qca8k_set_page(bus, page); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + +- mutex_unlock(&priv->bus->mdio_lock); ++ mutex_unlock(&bus->mdio_lock); + } + + static u32 + qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val) + { ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 ret; + + qca8k_split_addr(reg, &r1, &r2, &page); + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- qca8k_set_page(priv->bus, page); +- ret = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); ++ qca8k_set_page(bus, page); ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1); + ret &= ~mask; + ret |= val; +- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, ret); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, ret); + +- mutex_unlock(&priv->bus->mdio_lock); ++ mutex_unlock(&bus->mdio_lock); + + return ret; + } diff --git a/target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch b/target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch new file mode 100644 index 0000000000..6be494a8c7 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch @@ -0,0 +1,101 @@ +From ba5707ec58cfb6853dff41c2aae72deb6a03d389 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:54 +0200 +Subject: [PATCH] net: dsa: qca8k: handle qca8k_set_page errors + +With a remote possibility, the set_page function can fail. Since this is +a critical part of the write/read qca8k regs, propagate the error and +terminate any read/write operation. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 33 ++++++++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 7 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -127,16 +127,23 @@ qca8k_mii_write32(struct mii_bus *bus, i + "failed to write qca8k 32bit register\n"); + } + +-static void ++static int + qca8k_set_page(struct mii_bus *bus, u16 page) + { ++ int ret; ++ + if (page == qca8k_current_page) +- return; ++ return 0; + +- if (bus->write(bus, 0x18, 0, page) < 0) ++ ret = bus->write(bus, 0x18, 0, page); ++ if (ret < 0) { + dev_err_ratelimited(&bus->dev, + "failed to set qca8k page\n"); ++ return ret; ++ } ++ + qca8k_current_page = page; ++ return 0; + } + + static u32 +@@ -150,11 +157,14 @@ qca8k_read(struct qca8k_priv *priv, u32 + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- qca8k_set_page(bus, page); ++ val = qca8k_set_page(bus, page); ++ if (val < 0) ++ goto exit; ++ + val = qca8k_mii_read32(bus, 0x10 | r2, r1); + ++exit: + mutex_unlock(&bus->mdio_lock); +- + return val; + } + +@@ -163,14 +173,19 @@ qca8k_write(struct qca8k_priv *priv, u32 + { + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; ++ int ret; + + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- qca8k_set_page(bus, page); ++ ret = qca8k_set_page(bus, page); ++ if (ret < 0) ++ goto exit; ++ + qca8k_mii_write32(bus, 0x10 | r2, r1, val); + ++exit: + mutex_unlock(&bus->mdio_lock); + } + +@@ -185,12 +200,16 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- qca8k_set_page(bus, page); ++ ret = qca8k_set_page(bus, page); ++ if (ret < 0) ++ goto exit; ++ + ret = qca8k_mii_read32(bus, 0x10 | r2, r1); + ret &= ~mask; + ret |= val; + qca8k_mii_write32(bus, 0x10 | r2, r1, ret); + ++exit: + mutex_unlock(&bus->mdio_lock); + + return ret; diff --git a/target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch b/target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch new file mode 100644 index 0000000000..3349b7897a --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch @@ -0,0 +1,207 @@ +From 028f5f8ef44fcf87a456772cbb9f0d90a0a22884 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:55 +0200 +Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_read operation + +qca8k_read can fail. Rework any user to handle error values and +correctly return. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 73 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 58 insertions(+), 15 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -231,8 +231,13 @@ static int + qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ctx; ++ int ret; ++ ++ ret = qca8k_read(priv, reg); ++ if (ret < 0) ++ return ret; + +- *val = qca8k_read(priv, reg); ++ *val = ret; + + return 0; + } +@@ -300,15 +305,20 @@ qca8k_busy_wait(struct qca8k_priv *priv, + return ret; + } + +-static void ++static int + qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) + { +- u32 reg[4]; ++ u32 reg[4], val; + int i; + + /* load the ARL table into an array */ +- for (i = 0; i < 4; i++) +- reg[i] = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4)); ++ for (i = 0; i < 4; i++) { ++ val = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4)); ++ if (val < 0) ++ return val; ++ ++ reg[i] = val; ++ } + + /* vid - 83:72 */ + fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M; +@@ -323,6 +333,8 @@ qca8k_fdb_read(struct qca8k_priv *priv, + fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff; + fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff; + fdb->mac[5] = reg[0] & 0xff; ++ ++ return 0; + } + + static void +@@ -374,6 +386,8 @@ qca8k_fdb_access(struct qca8k_priv *priv + /* Check for table full violation when adding an entry */ + if (cmd == QCA8K_FDB_LOAD) { + reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC); ++ if (reg < 0) ++ return reg; + if (reg & QCA8K_ATU_FUNC_FULL) + return -1; + } +@@ -388,10 +402,10 @@ qca8k_fdb_next(struct qca8k_priv *priv, + + qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging); + ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port); +- if (ret >= 0) +- qca8k_fdb_read(priv, fdb); ++ if (ret < 0) ++ return ret; + +- return ret; ++ return qca8k_fdb_read(priv, fdb); + } + + static int +@@ -449,6 +463,8 @@ qca8k_vlan_access(struct qca8k_priv *pri + /* Check for table full violation when adding an entry */ + if (cmd == QCA8K_VLAN_LOAD) { + reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1); ++ if (reg < 0) ++ return reg; + if (reg & QCA8K_VTU_FUNC1_FULL) + return -ENOMEM; + } +@@ -475,6 +491,8 @@ qca8k_vlan_add(struct qca8k_priv *priv, + goto out; + + reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); ++ if (reg < 0) ++ return reg; + reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; + reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); + if (untagged) +@@ -506,6 +524,8 @@ qca8k_vlan_del(struct qca8k_priv *priv, + goto out; + + reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); ++ if (reg < 0) ++ return reg; + reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); + reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << + QCA8K_VTU_FUNC0_EG_MODE_S(port); +@@ -621,8 +641,11 @@ qca8k_mdio_read(struct qca8k_priv *priv, + QCA8K_MDIO_MASTER_BUSY)) + return -ETIMEDOUT; + +- val = (qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL) & +- QCA8K_MDIO_MASTER_DATA_MASK); ++ val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL); ++ if (val < 0) ++ return val; ++ ++ val &= QCA8K_MDIO_MASTER_DATA_MASK; + + return val; + } +@@ -978,6 +1001,8 @@ qca8k_phylink_mac_link_state(struct dsa_ + u32 reg; + + reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port)); ++ if (reg < 0) ++ return reg; + + state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); + state->an_complete = state->link; +@@ -1078,18 +1103,26 @@ qca8k_get_ethtool_stats(struct dsa_switc + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + const struct qca8k_mib_desc *mib; +- u32 reg, i; ++ u32 reg, i, val; + u64 hi; + + for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { + mib = &ar8327_mib[i]; + reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; + +- data[i] = qca8k_read(priv, reg); ++ val = qca8k_read(priv, reg); ++ if (val < 0) ++ continue; ++ + if (mib->size == 2) { + hi = qca8k_read(priv, reg + 4); +- data[i] |= hi << 32; ++ if (hi < 0) ++ continue; + } ++ ++ data[i] = val; ++ if (mib->size == 2) ++ data[i] |= hi << 32; + } + } + +@@ -1107,18 +1140,25 @@ qca8k_set_mac_eee(struct dsa_switch *ds, + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port); ++ int ret = 0; + u32 reg; + + mutex_lock(&priv->reg_mutex); + reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL); ++ if (reg < 0) { ++ ret = reg; ++ goto exit; ++ } ++ + if (eee->eee_enabled) + reg |= lpi_en; + else + reg &= ~lpi_en; + qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); +- mutex_unlock(&priv->reg_mutex); + +- return 0; ++exit: ++ mutex_unlock(&priv->reg_mutex); ++ return ret; + } + + static int +@@ -1456,6 +1496,9 @@ qca8k_sw_probe(struct mdio_device *mdiod + + /* read the switches ID register */ + id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); ++ if (id < 0) ++ return id; ++ + id >>= QCA8K_MASK_CTRL_ID_S; + id &= QCA8K_MASK_CTRL_ID_M; + if (id != QCA8K_ID_QCA8337) diff --git a/target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch b/target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch new file mode 100644 index 0000000000..1e0e224c39 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch @@ -0,0 +1,263 @@ +From d7805757c75c76e9518fc1023a29f0c4eed5b581 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:56 +0200 +Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_write operation + +qca8k_write can fail. Rework any user to handle error values and +correctly return. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 102 ++++++++++++++++++++++++++-------------- + 1 file changed, 67 insertions(+), 35 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -168,7 +168,7 @@ exit: + return val; + } + +-static void ++static int + qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) + { + struct mii_bus *bus = priv->bus; +@@ -187,6 +187,7 @@ qca8k_write(struct qca8k_priv *priv, u32 + + exit: + mutex_unlock(&bus->mdio_lock); ++ return ret; + } + + static u32 +@@ -247,9 +248,7 @@ qca8k_regmap_write(void *ctx, uint32_t r + { + struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + +- qca8k_write(priv, reg, val); +- +- return 0; ++ return qca8k_write(priv, reg, val); + } + + static const struct regmap_range qca8k_readable_ranges[] = { +@@ -367,6 +366,7 @@ static int + qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port) + { + u32 reg; ++ int ret; + + /* Set the command and FDB index */ + reg = QCA8K_ATU_FUNC_BUSY; +@@ -377,7 +377,9 @@ qca8k_fdb_access(struct qca8k_priv *priv + } + + /* Write the function register triggering the table access */ +- qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg); ++ ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg); ++ if (ret) ++ return ret; + + /* wait for completion */ + if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY)) +@@ -447,6 +449,7 @@ static int + qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) + { + u32 reg; ++ int ret; + + /* Set the command and VLAN index */ + reg = QCA8K_VTU_FUNC1_BUSY; +@@ -454,7 +457,9 @@ qca8k_vlan_access(struct qca8k_priv *pri + reg |= vid << QCA8K_VTU_FUNC1_VID_S; + + /* Write the function register triggering the table access */ +- qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); ++ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); ++ if (ret) ++ return ret; + + /* wait for completion */ + if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY)) +@@ -502,7 +507,9 @@ qca8k_vlan_add(struct qca8k_priv *priv, + reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG << + QCA8K_VTU_FUNC0_EG_MODE_S(port); + +- qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); ++ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); ++ if (ret) ++ return ret; + ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); + + out: +@@ -545,7 +552,9 @@ qca8k_vlan_del(struct qca8k_priv *priv, + if (del) { + ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid); + } else { +- qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); ++ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); ++ if (ret) ++ return ret; + ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); + } + +@@ -555,15 +564,20 @@ out: + return ret; + } + +-static void ++static int + qca8k_mib_init(struct qca8k_priv *priv) + { ++ int ret; ++ + mutex_lock(&priv->reg_mutex); + qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); + qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); + qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); +- qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); ++ ++ ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); ++ + mutex_unlock(&priv->reg_mutex); ++ return ret; + } + + static void +@@ -600,6 +614,7 @@ static int + qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) + { + u32 phy, val; ++ int ret; + + if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) + return -EINVAL; +@@ -613,7 +628,9 @@ qca8k_mdio_write(struct qca8k_priv *priv + QCA8K_MDIO_MASTER_REG_ADDR(regnum) | + QCA8K_MDIO_MASTER_DATA(data); + +- qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); ++ ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); ++ if (ret) ++ return ret; + + return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); +@@ -623,6 +640,7 @@ static int + qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) + { + u32 phy, val; ++ int ret; + + if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) + return -EINVAL; +@@ -635,7 +653,9 @@ qca8k_mdio_read(struct qca8k_priv *priv, + QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | + QCA8K_MDIO_MASTER_REG_ADDR(regnum); + +- qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); ++ ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); ++ if (ret) ++ return ret; + + if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY)) +@@ -766,12 +786,18 @@ qca8k_setup(struct dsa_switch *ds) + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); + + /* Enable MIB counters */ +- qca8k_mib_init(priv); ++ ret = qca8k_mib_init(priv); ++ if (ret) ++ dev_warn(priv->dev, "mib init failed"); + + /* Enable QCA header mode on the cpu port */ +- qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT), +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT), ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode"); ++ return ret; ++ } + + /* Disable forwarding by default on all ports */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) +@@ -783,11 +809,13 @@ qca8k_setup(struct dsa_switch *ds) + qca8k_port_set_status(priv, i, 0); + + /* Forward all unknown frames to CPU port for Linux processing */ +- qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); ++ ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, ++ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | ++ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | ++ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | ++ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); ++ if (ret) ++ return ret; + + /* Setup connection between CPU port & user ports */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { +@@ -815,16 +843,20 @@ qca8k_setup(struct dsa_switch *ds) + qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), + 0xfff << shift, + QCA8K_PORT_VID_DEF << shift); +- qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), +- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | +- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), ++ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | ++ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; + } + } + + /* Setup our port MTUs to match power on defaults */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) + priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; +- qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); ++ ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); ++ if (ret) ++ dev_warn(priv->dev, "failed setting MTU settings"); + + /* Flush the FDB table */ + qca8k_fdb_flush(priv); +@@ -1140,8 +1172,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds, + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port); +- int ret = 0; + u32 reg; ++ int ret; + + mutex_lock(&priv->reg_mutex); + reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL); +@@ -1154,7 +1186,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds, + reg |= lpi_en; + else + reg &= ~lpi_en; +- qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); ++ ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); + + exit: + mutex_unlock(&priv->reg_mutex); +@@ -1284,9 +1316,7 @@ qca8k_port_change_mtu(struct dsa_switch + mtu = priv->port_mtu[i]; + + /* Include L2 header / FCS length */ +- qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN); +- +- return 0; ++ return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN); + } + + static int diff --git a/target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch b/target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch new file mode 100644 index 0000000000..506966f1af --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch @@ -0,0 +1,226 @@ +From aaf421425cbdec4eb6fd75a29e65c2867b0b7bbd Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:57 +0200 +Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_rmw operation + +qca8k_rmw can fail. Rework any user to handle error values and +correctly return. Change qca8k_rmw to return the error code or 0 instead +of the reg value. The reg returned by qca8k_rmw wasn't used anywhere, +so this doesn't cause any functional change. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 133 +++++++++++++++++++++++++--------------- + 1 file changed, 83 insertions(+), 50 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -190,12 +190,13 @@ exit: + return ret; + } + +-static u32 +-qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val) ++static int ++qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) + { + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; +- u32 ret; ++ u32 val; ++ int ret; + + qca8k_split_addr(reg, &r1, &r2, &page); + +@@ -205,10 +206,15 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r + if (ret < 0) + goto exit; + +- ret = qca8k_mii_read32(bus, 0x10 | r2, r1); +- ret &= ~mask; +- ret |= val; +- qca8k_mii_write32(bus, 0x10 | r2, r1, ret); ++ val = qca8k_mii_read32(bus, 0x10 | r2, r1); ++ if (val < 0) { ++ ret = val; ++ goto exit; ++ } ++ ++ val &= ~mask; ++ val |= write_val; ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + + exit: + mutex_unlock(&bus->mdio_lock); +@@ -216,16 +222,16 @@ exit: + return ret; + } + +-static void ++static int + qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val) + { +- qca8k_rmw(priv, reg, 0, val); ++ return qca8k_rmw(priv, reg, 0, val); + } + +-static void ++static int + qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val) + { +- qca8k_rmw(priv, reg, val, 0); ++ return qca8k_rmw(priv, reg, val, 0); + } + + static int +@@ -570,12 +576,19 @@ qca8k_mib_init(struct qca8k_priv *priv) + int ret; + + mutex_lock(&priv->reg_mutex); +- qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); ++ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); ++ if (ret) ++ goto exit; ++ + qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); +- qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); ++ ++ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); ++ if (ret) ++ goto exit; + + ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); + ++exit: + mutex_unlock(&priv->reg_mutex); + return ret; + } +@@ -747,9 +760,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + * a dt-overlay and driver reload changed the configuration + */ + +- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_EN); +- return 0; ++ return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_EN); + } + + priv->ops.phy_read = qca8k_phy_read; +@@ -782,8 +794,12 @@ qca8k_setup(struct dsa_switch *ds) + return ret; + + /* Enable CPU Port */ +- qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, +- QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); ++ ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, ++ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling CPU port"); ++ return ret; ++ } + + /* Enable MIB counters */ + ret = qca8k_mib_init(priv); +@@ -800,9 +816,12 @@ qca8k_setup(struct dsa_switch *ds) + } + + /* Disable forwarding by default on all ports */ +- for (i = 0; i < QCA8K_NUM_PORTS; i++) +- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, 0); ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_MEMBER, 0); ++ if (ret) ++ return ret; ++ } + + /* Disable MAC by default on all ports */ + for (i = 1; i < QCA8K_NUM_PORTS; i++) +@@ -821,28 +840,37 @@ qca8k_setup(struct dsa_switch *ds) + for (i = 0; i < QCA8K_NUM_PORTS; i++) { + /* CPU port gets connected to all user ports of the switch */ + if (dsa_is_cpu_port(ds, i)) { +- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), +- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), ++ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); ++ if (ret) ++ return ret; + } + + /* Individual user ports get connected to CPU port only */ + if (dsa_is_user_port(ds, i)) { + int shift = 16 * (i % 2); + +- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, +- BIT(QCA8K_CPU_PORT)); ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ BIT(QCA8K_CPU_PORT)); ++ if (ret) ++ return ret; + + /* Enable ARP Auto-learning by default */ +- qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); ++ ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; + + /* For port based vlans to work we need to set the + * default egress vid + */ +- qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), +- 0xfff << shift, +- QCA8K_PORT_VID_DEF << shift); ++ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), ++ 0xfff << shift, ++ QCA8K_PORT_VID_DEF << shift); ++ if (ret) ++ return ret; ++ + ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), + QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | + QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); +@@ -1234,7 +1262,7 @@ qca8k_port_bridge_join(struct dsa_switch + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + int port_mask = BIT(QCA8K_CPU_PORT); +- int i; ++ int i, ret; + + for (i = 1; i < QCA8K_NUM_PORTS; i++) { + if (dsa_to_port(ds, i)->bridge_dev != br) +@@ -1242,17 +1270,20 @@ qca8k_port_bridge_join(struct dsa_switch + /* Add this port to the portvlan mask of the other ports + * in the bridge + */ +- qca8k_reg_set(priv, +- QCA8K_PORT_LOOKUP_CTRL(i), +- BIT(port)); ++ ret = qca8k_reg_set(priv, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); ++ if (ret) ++ return ret; + if (i != port) + port_mask |= BIT(i); + } ++ + /* Add all other ports to this ports portvlan mask */ +- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_MEMBER, port_mask); ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, port_mask); + +- return 0; ++ return ret; + } + + static void diff --git a/target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch b/target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch new file mode 100644 index 0000000000..360ce1d947 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch @@ -0,0 +1,66 @@ +From b7c818d194927bdc60ed15db55bb8654496a36b7 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:58 +0200 +Subject: [PATCH] net: dsa: qca8k: handle error from qca8k_busy_wait + +Propagate errors from qca8k_busy_wait instead of hardcoding return +value. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -388,8 +388,9 @@ qca8k_fdb_access(struct qca8k_priv *priv + return ret; + + /* wait for completion */ +- if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY)) +- return -1; ++ ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY); ++ if (ret) ++ return ret; + + /* Check for table full violation when adding an entry */ + if (cmd == QCA8K_FDB_LOAD) { +@@ -468,8 +469,9 @@ qca8k_vlan_access(struct qca8k_priv *pri + return ret; + + /* wait for completion */ +- if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY)) +- return -ETIMEDOUT; ++ ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY); ++ if (ret) ++ return ret; + + /* Check for table full violation when adding an entry */ + if (cmd == QCA8K_VLAN_LOAD) { +@@ -580,7 +582,9 @@ qca8k_mib_init(struct qca8k_priv *priv) + if (ret) + goto exit; + +- qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); ++ ret = qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); ++ if (ret) ++ goto exit; + + ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); + if (ret) +@@ -670,9 +674,10 @@ qca8k_mdio_read(struct qca8k_priv *priv, + if (ret) + return ret; + +- if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_BUSY)) +- return -ETIMEDOUT; ++ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_BUSY); ++ if (ret) ++ return ret; + + val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL); + if (val < 0) diff --git a/target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch b/target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch new file mode 100644 index 0000000000..72305850ca --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch @@ -0,0 +1,96 @@ +From 6e82a457e06252b59102486767539cc9c2aba60b Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 22:59:59 +0200 +Subject: [PATCH] net: dsa: qca8k: add support for qca8327 switch + +qca8327 switch is a low tier version of the more recent qca8337. +It does share the same regs used by the qca8k driver and can be +supported with minimal change. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 23 ++++++++++++++++++++--- + drivers/net/dsa/qca8k.h | 6 ++++++ + 2 files changed, 26 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1533,6 +1533,7 @@ static const struct dsa_switch_ops qca8k + static int + qca8k_sw_probe(struct mdio_device *mdiodev) + { ++ const struct qca8k_match_data *data; + struct qca8k_priv *priv; + u32 id; + +@@ -1560,6 +1561,11 @@ qca8k_sw_probe(struct mdio_device *mdiod + gpiod_set_value_cansleep(priv->reset_gpio, 0); + } + ++ /* get the switches ID from the compatible */ ++ data = of_device_get_match_data(&mdiodev->dev); ++ if (!data) ++ return -ENODEV; ++ + /* read the switches ID register */ + id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); + if (id < 0) +@@ -1567,8 +1573,10 @@ qca8k_sw_probe(struct mdio_device *mdiod + + id >>= QCA8K_MASK_CTRL_ID_S; + id &= QCA8K_MASK_CTRL_ID_M; +- if (id != QCA8K_ID_QCA8337) ++ if (id != data->id) { ++ dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id); + return -ENODEV; ++ } + + priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) +@@ -1634,9 +1642,18 @@ static int qca8k_resume(struct device *d + static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, + qca8k_suspend, qca8k_resume); + ++static const struct qca8k_match_data qca832x = { ++ .id = QCA8K_ID_QCA8327, ++}; ++ ++static const struct qca8k_match_data qca833x = { ++ .id = QCA8K_ID_QCA8337, ++}; ++ + static const struct of_device_id qca8k_of_match[] = { +- { .compatible = "qca,qca8334" }, +- { .compatible = "qca,qca8337" }, ++ { .compatible = "qca,qca8327", .data = &qca832x }, ++ { .compatible = "qca,qca8334", .data = &qca833x }, ++ { .compatible = "qca,qca8337", .data = &qca833x }, + { /* sentinel */ }, + }; + +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -15,6 +15,8 @@ + #define QCA8K_NUM_PORTS 7 + #define QCA8K_MAX_MTU 9000 + ++#define PHY_ID_QCA8327 0x004dd034 ++#define QCA8K_ID_QCA8327 0x12 + #define PHY_ID_QCA8337 0x004dd036 + #define QCA8K_ID_QCA8337 0x13 + +@@ -213,6 +215,10 @@ struct ar8xxx_port_status { + int enabled; + }; + ++struct qca8k_match_data { ++ u8 id; ++}; ++ + struct qca8k_priv { + struct regmap *regmap; + struct mii_bus *bus; diff --git a/target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch b/target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch new file mode 100644 index 0000000000..3c4a14bd0b --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch @@ -0,0 +1,26 @@ +From 227a9ffc1bc77037339530607fe129af3824620e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:00 +0200 +Subject: [PATCH] devicetree: net: dsa: qca8k: Document new compatible qca8327 + +Add support for qca8327 in the compatible list. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Acked-by: Rob Herring +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/dsa/qca8k.txt | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -3,6 +3,7 @@ + Required properties: + + - compatible: should be one of: ++ "qca,qca8327" + "qca,qca8334" + "qca,qca8337" + diff --git a/target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch b/target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch new file mode 100644 index 0000000000..cd3050ef71 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch @@ -0,0 +1,130 @@ +From 83a3ceb39b2495171aabe9446271b94c678354f3 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:01 +0200 +Subject: [PATCH] net: dsa: qca8k: add priority tweak to qca8337 switch + +The port 5 of the qca8337 have some problem in flood condition. The +original legacy driver had some specific buffer and priority settings +for the different port suggested by the QCA switch team. Add this +missing settings to improve switch stability under load condition. +The packet priority tweak is only needed for the qca8337 switch and +other qca8k switch are not affected. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 47 +++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 25 ++++++++++++++++++++++ + 2 files changed, 72 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -779,6 +779,7 @@ qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + int ret, i; ++ u32 mask; + + /* Make sure that port 0 is the cpu port */ + if (!dsa_is_cpu_port(ds, 0)) { +@@ -884,6 +885,51 @@ qca8k_setup(struct dsa_switch *ds) + } + } + ++ /* The port 5 of the qca8337 have some problem in flood condition. The ++ * original legacy driver had some specific buffer and priority settings ++ * for the different port suggested by the QCA switch team. Add this ++ * missing settings to improve switch stability under load condition. ++ * This problem is limited to qca8337 and other qca8k switch are not affected. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) { ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ switch (i) { ++ /* The 2 CPU port and port 5 requires some different ++ * priority than any other ports. ++ */ ++ case 0: ++ case 5: ++ case 6: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); ++ break; ++ default: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); ++ } ++ qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); ++ ++ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN; ++ qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), ++ QCA8K_PORT_HOL_CTRL1_ING_BUF | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN, ++ mask); ++ } ++ } ++ + /* Setup our port MTUs to match power on defaults */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) + priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; +@@ -1578,6 +1624,7 @@ qca8k_sw_probe(struct mdio_device *mdiod + return -ENODEV; + } + ++ priv->switch_id = id; + priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) + return -ENOMEM; +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -168,6 +168,30 @@ + #define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) + ++#define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF GENMASK(7, 4) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) ((x) << 4) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF GENMASK(11, 8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) ((x) << 8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF GENMASK(15, 12) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) ((x) << 12) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF GENMASK(19, 16) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) ((x) << 16) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF GENMASK(23, 20) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) ((x) << 20) ++#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF GENMASK(29, 24) ++#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) ((x) << 24) ++ ++#define QCA8K_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) ++#define QCA8K_PORT_HOL_CTRL1_ING_BUF GENMASK(3, 0) ++#define QCA8K_PORT_HOL_CTRL1_ING(x) ((x) << 0) ++#define QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN BIT(6) ++#define QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN BIT(7) ++#define QCA8K_PORT_HOL_CTRL1_WRED_EN BIT(8) ++#define QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) ++ + /* Pkt edit registers */ + #define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2))) + +@@ -220,6 +244,7 @@ struct qca8k_match_data { + }; + + struct qca8k_priv { ++ u8 switch_id; + struct regmap *regmap; + struct mii_bus *bus; + struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch b/target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch new file mode 100644 index 0000000000..d25edbb1aa --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch @@ -0,0 +1,31 @@ +From 5bf9ff3b9fb5ecb67a1a3517b26db3a00f2a2f11 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:02 +0200 +Subject: [PATCH] net: dsa: qca8k: limit port5 delay to qca8337 + +Limit port5 rx delay to qca8337. This is taken from the legacy QSDK code +that limits the rx delay on port5 to only this particular switch version, +on other switch only the tx and rx delay for port0 are needed. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1003,8 +1003,10 @@ qca8k_phylink_mac_config(struct dsa_swit + QCA8K_PORT_PAD_RGMII_EN | + QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) | + QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY)); +- qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, +- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); ++ /* QCA8337 requires to set rgmii rx delay */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) ++ qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); + break; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: diff --git a/target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch b/target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch new file mode 100644 index 0000000000..2b393d242a --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch @@ -0,0 +1,48 @@ +From 0fc57e4b5e39461fc0a54aae0afe4241363a7267 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:03 +0200 +Subject: [PATCH] net: dsa: qca8k: add GLOBAL_FC settings needed for qca8327 + +Switch qca8327 needs special settings for the GLOBAL_FC_THRES regs. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 10 ++++++++++ + drivers/net/dsa/qca8k.h | 6 ++++++ + 2 files changed, 16 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -930,6 +930,16 @@ qca8k_setup(struct dsa_switch *ds) + } + } + ++ /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ ++ if (priv->switch_id == QCA8K_ID_QCA8327) { ++ mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | ++ QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); ++ qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, ++ QCA8K_GLOBAL_FC_GOL_XON_THRES_S | ++ QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S, ++ mask); ++ } ++ + /* Setup our port MTUs to match power on defaults */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) + priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -168,6 +168,12 @@ + #define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) + ++#define QCA8K_REG_GLOBAL_FC_THRESH 0x800 ++#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16) ++#define QCA8K_GLOBAL_FC_GOL_XON_THRES_S GENMASK(24, 16) ++#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) ((x) << 0) ++#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S GENMASK(8, 0) ++ + #define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8) + #define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0) + #define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0) diff --git a/target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch b/target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch new file mode 100644 index 0000000000..ed9b8188de --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch @@ -0,0 +1,114 @@ +From 95ffeaf18b3bb90eeef52cbf7d79ccc9d0345ff5 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:04 +0200 +Subject: [PATCH] net: dsa: qca8k: add support for switch rev + +qca8k internal phy driver require some special debug value to be set +based on the switch revision. Rework the switch id read function to +also read the chip revision. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 53 ++++++++++++++++++++++++++--------------- + drivers/net/dsa/qca8k.h | 7 ++++-- + 2 files changed, 39 insertions(+), 21 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1588,12 +1588,40 @@ static const struct dsa_switch_ops qca8k + .phylink_mac_link_up = qca8k_phylink_mac_link_up, + }; + ++static int qca8k_read_switch_id(struct qca8k_priv *priv) ++{ ++ const struct qca8k_match_data *data; ++ u32 val; ++ u8 id; ++ ++ /* get the switches ID from the compatible */ ++ data = of_device_get_match_data(priv->dev); ++ if (!data) ++ return -ENODEV; ++ ++ val = qca8k_read(priv, QCA8K_REG_MASK_CTRL); ++ if (val < 0) ++ return -ENODEV; ++ ++ id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); ++ if (id != data->id) { ++ dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); ++ return -ENODEV; ++ } ++ ++ priv->switch_id = id; ++ ++ /* Save revision to communicate to the internal PHY driver */ ++ priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK); ++ ++ return 0; ++} ++ + static int + qca8k_sw_probe(struct mdio_device *mdiodev) + { +- const struct qca8k_match_data *data; + struct qca8k_priv *priv; +- u32 id; ++ int ret; + + /* allocate the private data struct so that we can probe the switches + * ID register +@@ -1619,24 +1647,11 @@ qca8k_sw_probe(struct mdio_device *mdiod + gpiod_set_value_cansleep(priv->reset_gpio, 0); + } + +- /* get the switches ID from the compatible */ +- data = of_device_get_match_data(&mdiodev->dev); +- if (!data) +- return -ENODEV; ++ /* Check the detected switch id */ ++ ret = qca8k_read_switch_id(priv); ++ if (ret) ++ return ret; + +- /* read the switches ID register */ +- id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); +- if (id < 0) +- return id; +- +- id >>= QCA8K_MASK_CTRL_ID_S; +- id &= QCA8K_MASK_CTRL_ID_M; +- if (id != data->id) { +- dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id); +- return -ENODEV; +- } +- +- priv->switch_id = id; + priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) + return -ENOMEM; +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -30,8 +30,10 @@ + + /* Global control registers */ + #define QCA8K_REG_MASK_CTRL 0x000 +-#define QCA8K_MASK_CTRL_ID_M 0xff +-#define QCA8K_MASK_CTRL_ID_S 8 ++#define QCA8K_MASK_CTRL_REV_ID_MASK GENMASK(7, 0) ++#define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0) ++#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) ++#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) + #define QCA8K_REG_PORT0_PAD_CTRL 0x004 + #define QCA8K_REG_PORT5_PAD_CTRL 0x008 + #define QCA8K_REG_PORT6_PAD_CTRL 0x00c +@@ -251,6 +253,7 @@ struct qca8k_match_data { + + struct qca8k_priv { + u8 switch_id; ++ u8 switch_revision; + struct regmap *regmap; + struct mii_bus *bus; + struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch b/target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch new file mode 100644 index 0000000000..629cb324e0 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch @@ -0,0 +1,28 @@ +From 1ee0591a1093c2448642c33433483e9260275f7b Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:05 +0200 +Subject: [PATCH] net: dsa: qca8k: add ethernet-ports fallback to + setup_mdio_bus + +Dsa now also supports ethernet-ports. Add this new binding as a fallback +if the ports node can't be found. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -719,6 +719,9 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + + ports = of_get_child_by_name(priv->dev->of_node, "ports"); + if (!ports) ++ ports = of_get_child_by_name(priv->dev->of_node, "ethernet-ports"); ++ ++ if (!ports) + return -EINVAL; + + for_each_available_child_of_node(ports, port) { diff --git a/target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch b/target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch new file mode 100644 index 0000000000..6dc2dc6e3e --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch @@ -0,0 +1,188 @@ +From e4b9977cee1583da38a6e9118078bb728aaccf7b Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:06 +0200 +Subject: [PATCH] net: dsa: qca8k: make rgmii delay configurable + +The legacy qsdk code used a different delay instead of the max value. +Qsdk use 1 ns for rx and 2 ns for tx. Make these values configurable +using the standard rx/tx-internal-delay-ps ethernet binding and apply +qsdk values by default. The connected gmac doesn't add any delay so no +additional delay is added to tx/rx. +On this switch the delay is actually in ns so value should be in the +1000 order. Any value converted from ps to ns by dividing it by 1000 +as the switch max value for delay is 3ns. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 82 ++++++++++++++++++++++++++++++++++++++++- + drivers/net/dsa/qca8k.h | 11 +++--- + 2 files changed, 86 insertions(+), 7 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -778,6 +778,68 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + } + + static int ++qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv) ++{ ++ struct device_node *port_dn; ++ phy_interface_t mode; ++ struct dsa_port *dp; ++ u32 val; ++ ++ /* CPU port is already checked */ ++ dp = dsa_to_port(priv->ds, 0); ++ ++ port_dn = dp->dn; ++ ++ /* Check if port 0 is set to the correct type */ ++ of_get_phy_mode(port_dn, &mode); ++ if (mode != PHY_INTERFACE_MODE_RGMII_ID && ++ mode != PHY_INTERFACE_MODE_RGMII_RXID && ++ mode != PHY_INTERFACE_MODE_RGMII_TXID) { ++ return 0; ++ } ++ ++ switch (mode) { ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val)) ++ val = 2; ++ else ++ /* Switch regs accept value in ns, convert ps to ns */ ++ val = val / 1000; ++ ++ if (val > QCA8K_MAX_DELAY) { ++ dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); ++ val = 3; ++ } ++ ++ priv->rgmii_rx_delay = val; ++ /* Stop here if we need to check only for rx delay */ ++ if (mode != PHY_INTERFACE_MODE_RGMII_ID) ++ break; ++ ++ fallthrough; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val)) ++ val = 1; ++ else ++ /* Switch regs accept value in ns, convert ps to ns */ ++ val = val / 1000; ++ ++ if (val > QCA8K_MAX_DELAY) { ++ dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); ++ val = 3; ++ } ++ ++ priv->rgmii_tx_delay = val; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +@@ -802,6 +864,10 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ ret = qca8k_setup_of_rgmii_delay(priv); ++ if (ret) ++ return ret; ++ + /* Enable CPU Port */ + ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); +@@ -970,6 +1036,8 @@ qca8k_phylink_mac_config(struct dsa_swit + case 0: /* 1st CPU port */ + if (state->interface != PHY_INTERFACE_MODE_RGMII && + state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && + state->interface != PHY_INTERFACE_MODE_SGMII) + return; + +@@ -985,6 +1053,8 @@ qca8k_phylink_mac_config(struct dsa_swit + case 6: /* 2nd CPU port / external PHY */ + if (state->interface != PHY_INTERFACE_MODE_RGMII && + state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && + state->interface != PHY_INTERFACE_MODE_SGMII && + state->interface != PHY_INTERFACE_MODE_1000BASEX) + return; +@@ -1008,14 +1078,18 @@ qca8k_phylink_mac_config(struct dsa_swit + qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN); + break; + case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: + /* RGMII_ID needs internal delay. This is enabled through + * PORT5_PAD_CTRL for all ports, rather than individual port + * registers + */ + qca8k_write(priv, reg, + QCA8K_PORT_PAD_RGMII_EN | +- QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) | +- QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY)); ++ QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) | ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); + /* QCA8337 requires to set rgmii rx delay */ + if (priv->switch_id == QCA8K_ID_QCA8337) + qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, +@@ -1073,6 +1147,8 @@ qca8k_phylink_validate(struct dsa_switch + if (state->interface != PHY_INTERFACE_MODE_NA && + state->interface != PHY_INTERFACE_MODE_RGMII && + state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && + state->interface != PHY_INTERFACE_MODE_SGMII) + goto unsupported; + break; +@@ -1090,6 +1166,8 @@ qca8k_phylink_validate(struct dsa_switch + if (state->interface != PHY_INTERFACE_MODE_NA && + state->interface != PHY_INTERFACE_MODE_RGMII && + state->interface != PHY_INTERFACE_MODE_RGMII_ID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && ++ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && + state->interface != PHY_INTERFACE_MODE_SGMII && + state->interface != PHY_INTERFACE_MODE_1000BASEX) + goto unsupported; +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -38,12 +38,11 @@ + #define QCA8K_REG_PORT5_PAD_CTRL 0x008 + #define QCA8K_REG_PORT6_PAD_CTRL 0x00c + #define QCA8K_PORT_PAD_RGMII_EN BIT(26) +-#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) \ +- ((0x8 + (x & 0x3)) << 22) +-#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) \ +- ((0x10 + (x & 0x3)) << 20) +-#define QCA8K_MAX_DELAY 3 ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22) ++#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20) ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25) + #define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) ++#define QCA8K_MAX_DELAY 3 + #define QCA8K_PORT_PAD_SGMII_EN BIT(7) + #define QCA8K_REG_PWS 0x010 + #define QCA8K_PWS_SERDES_AEN_DIS BIT(7) +@@ -254,6 +253,8 @@ struct qca8k_match_data { + struct qca8k_priv { + u8 switch_id; + u8 switch_revision; ++ u8 rgmii_tx_delay; ++ u8 rgmii_rx_delay; + struct regmap *regmap; + struct mii_bus *bus; + struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch b/target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch new file mode 100644 index 0000000000..4593da032b --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch @@ -0,0 +1,50 @@ +From 63c33bbfeb6842a956a0eb12901e28eb335bdb18 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:07 +0200 +Subject: [PATCH] net: dsa: qca8k: clear MASTER_EN after phy read/write + +Clear MDIO_MASTER_EN bit from MDIO_MASTER_CTRL after read/write +operation. The MDIO_MASTER_EN bit is not reset after read/write +operation and the next operation can be wrongly interpreted by the +switch as a mdio operation. This cause a production of wrong/garbage +data from the switch and underfined bheavior. (random port drop, +unplugged port flagged with link up, wrong port speed) +Also on driver remove the MASTER_CTRL can be left set and cause the +malfunction of any next driver using the mdio device. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -649,8 +649,14 @@ qca8k_mdio_write(struct qca8k_priv *priv + if (ret) + return ret; + +- return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_BUSY); ++ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_BUSY); ++ ++ /* even if the busy_wait timeouts try to clear the MASTER_EN */ ++ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_EN); ++ ++ return ret; + } + + static int +@@ -685,6 +691,10 @@ qca8k_mdio_read(struct qca8k_priv *priv, + + val &= QCA8K_MDIO_MASTER_DATA_MASK; + ++ /* even if the busy_wait timeouts try to clear the MASTER_EN */ ++ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_EN); ++ + return val; + } + diff --git a/target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch b/target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch new file mode 100644 index 0000000000..b6684d7210 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch @@ -0,0 +1,128 @@ +From 60df02b6ea4581d72eb7a3ab7204504a54059b72 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:08 +0200 +Subject: [PATCH] net: dsa: qca8k: dsa: qca8k: protect MASTER busy_wait with + mdio mutex + +MDIO_MASTER operation have a dedicated busy wait that is not protected +by the mdio mutex. This can cause situation where the MASTER operation +is done and a normal operation is executed between the MASTER read/write +and the MASTER busy_wait. Rework the qca8k_mdio_read/write function to +address this issue by binding the lock for the whole MASTER operation +and not only the mdio read/write common operation. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 68 +++++++++++++++++++++++++++++++++-------- + 1 file changed, 55 insertions(+), 13 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -628,8 +628,31 @@ qca8k_port_to_phy(int port) + } + + static int ++qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) ++{ ++ u16 r1, r2, page; ++ u32 val; ++ int ret; ++ ++ qca8k_split_addr(reg, &r1, &r2, &page); ++ ++ ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0, ++ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, ++ priv->bus, 0x10 | r2, r1); ++ ++ /* Check if qca8k_read has failed for a different reason ++ * before returnting -ETIMEDOUT ++ */ ++ if (ret < 0 && val < 0) ++ return val; ++ ++ return ret; ++} ++ ++static int + qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) + { ++ u16 r1, r2, page; + u32 phy, val; + int ret; + +@@ -645,12 +668,21 @@ qca8k_mdio_write(struct qca8k_priv *priv + QCA8K_MDIO_MASTER_REG_ADDR(regnum) | + QCA8K_MDIO_MASTER_DATA(data); + +- ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); ++ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); ++ ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = qca8k_set_page(priv->bus, page); + if (ret) +- return ret; ++ goto exit; ++ ++ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); + +- ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_BUSY); ++ ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_BUSY); ++ ++exit: ++ mutex_unlock(&priv->bus->mdio_lock); + + /* even if the busy_wait timeouts try to clear the MASTER_EN */ + qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, +@@ -662,6 +694,7 @@ qca8k_mdio_write(struct qca8k_priv *priv + static int + qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) + { ++ u16 r1, r2, page; + u32 phy, val; + int ret; + +@@ -676,21 +709,30 @@ qca8k_mdio_read(struct qca8k_priv *priv, + QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | + QCA8K_MDIO_MASTER_REG_ADDR(regnum); + +- ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); +- if (ret) +- return ret; ++ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); ++ ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_BUSY); ++ ret = qca8k_set_page(priv->bus, page); + if (ret) +- return ret; ++ goto exit; + +- val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL); +- if (val < 0) +- return val; ++ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); ++ ++ ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_BUSY); ++ if (ret) ++ goto exit; + ++ val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); + val &= QCA8K_MDIO_MASTER_DATA_MASK; + ++exit: ++ mutex_unlock(&priv->bus->mdio_lock); ++ ++ if (val >= 0) ++ val &= QCA8K_MDIO_MASTER_DATA_MASK; ++ + /* even if the busy_wait timeouts try to clear the MASTER_EN */ + qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_EN); diff --git a/target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch b/target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch new file mode 100644 index 0000000000..30eeed361e --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch @@ -0,0 +1,39 @@ +From 617960d72e93de0f3fa52407e2d39e8c43e73b0a Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:09 +0200 +Subject: [PATCH] net: dsa: qca8k: enlarge mdio delay and timeout + +The witch require some extra delay after setting page or the next +read/write can use still use the old page. Add a delay after the +set_page function to address this as it's done in QSDK legacy driver. +Some timeouts were notice with VLAN and phy function, enlarge the +mdio busy wait timeout to fix these problems. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 1 + + drivers/net/dsa/qca8k.h | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -143,6 +143,7 @@ qca8k_set_page(struct mii_bus *bus, u16 + } + + qca8k_current_page = page; ++ usleep_range(1000, 2000); + return 0; + } + +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -20,7 +20,7 @@ + #define PHY_ID_QCA8337 0x004dd036 + #define QCA8K_ID_QCA8337 0x13 + +-#define QCA8K_BUSY_WAIT_TIMEOUT 20 ++#define QCA8K_BUSY_WAIT_TIMEOUT 2000 + + #define QCA8K_NUM_FDB_RECORDS 2048 + diff --git a/target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch b/target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch new file mode 100644 index 0000000000..88d3c1ef43 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch @@ -0,0 +1,267 @@ +From 759bafb8a3226326ca357613bc90acf738f80c32 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:10 +0200 +Subject: [PATCH] net: dsa: qca8k: add support for internal phy and internal + mdio + +Add support to setup_mdio_bus for internal phy declaration. Introduce a +flag to use the legacy port phy mapping by default and use the direct +mapping if a mdio node is detected in the switch node. Register a +dedicated mdio internal mdio bus to address the different mapping +between port and phy if the mdio node is detected. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 112 +++++++++++++++++++++++++++++----------- + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 83 insertions(+), 30 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -629,7 +630,7 @@ qca8k_port_to_phy(int port) + } + + static int +-qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) ++qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) + { + u16 r1, r2, page; + u32 val; +@@ -639,7 +640,7 @@ qca8k_mdio_busy_wait(struct qca8k_priv * + + ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0, + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- priv->bus, 0x10 | r2, r1); ++ bus, 0x10 | r2, r1); + + /* Check if qca8k_read has failed for a different reason + * before returnting -ETIMEDOUT +@@ -651,19 +652,16 @@ qca8k_mdio_busy_wait(struct qca8k_priv * + } + + static int +-qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) ++qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) + { ++ struct qca8k_priv *priv = salve_bus->priv; + u16 r1, r2, page; +- u32 phy, val; ++ u32 val; + int ret; + + if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) + return -EINVAL; + +- /* callee is responsible for not passing bad ports, +- * but we still would like to make spills impossible. +- */ +- phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR; + val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | + QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | + QCA8K_MDIO_MASTER_REG_ADDR(regnum) | +@@ -679,33 +677,29 @@ qca8k_mdio_write(struct qca8k_priv *priv + + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); + +- ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, ++ ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + + exit: +- mutex_unlock(&priv->bus->mdio_lock); +- + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_EN); ++ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); ++ ++ mutex_unlock(&priv->bus->mdio_lock); + + return ret; + } + + static int +-qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) ++qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) + { ++ struct qca8k_priv *priv = salve_bus->priv; + u16 r1, r2, page; +- u32 phy, val; ++ u32 val; + int ret; + + if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) + return -EINVAL; + +- /* callee is responsible for not passing bad ports, +- * but we still would like to make spills impossible. +- */ +- phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR; + val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | + QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | + QCA8K_MDIO_MASTER_REG_ADDR(regnum); +@@ -720,24 +714,22 @@ qca8k_mdio_read(struct qca8k_priv *priv, + + qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); + +- ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, ++ ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + if (ret) + goto exit; + + val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); +- val &= QCA8K_MDIO_MASTER_DATA_MASK; + + exit: ++ /* even if the busy_wait timeouts try to clear the MASTER_EN */ ++ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); ++ + mutex_unlock(&priv->bus->mdio_lock); + + if (val >= 0) + val &= QCA8K_MDIO_MASTER_DATA_MASK; + +- /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_EN); +- + return val; + } + +@@ -746,7 +738,14 @@ qca8k_phy_write(struct dsa_switch *ds, i + { + struct qca8k_priv *priv = ds->priv; + +- return qca8k_mdio_write(priv, port, regnum, data); ++ /* Check if the legacy mapping should be used and the ++ * port is not correctly mapped to the right PHY in the ++ * devicetree ++ */ ++ if (priv->legacy_phy_port_mapping) ++ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; ++ ++ return qca8k_mdio_write(priv->bus, port, regnum, data); + } + + static int +@@ -755,7 +754,14 @@ qca8k_phy_read(struct dsa_switch *ds, in + struct qca8k_priv *priv = ds->priv; + int ret; + +- ret = qca8k_mdio_read(priv, port, regnum); ++ /* Check if the legacy mapping should be used and the ++ * port is not correctly mapped to the right PHY in the ++ * devicetree ++ */ ++ if (priv->legacy_phy_port_mapping) ++ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; ++ ++ ret = qca8k_mdio_read(priv->bus, port, regnum); + + if (ret < 0) + return 0xffff; +@@ -764,10 +770,37 @@ qca8k_phy_read(struct dsa_switch *ds, in + } + + static int ++qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio) ++{ ++ struct dsa_switch *ds = priv->ds; ++ struct mii_bus *bus; ++ ++ bus = devm_mdiobus_alloc(ds->dev); ++ ++ if (!bus) ++ return -ENOMEM; ++ ++ bus->priv = (void *)priv; ++ bus->name = "qca8k slave mii"; ++ bus->read = qca8k_mdio_read; ++ bus->write = qca8k_mdio_write; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d", ++ ds->index); ++ ++ bus->parent = ds->dev; ++ bus->phy_mask = ~ds->phys_mii_mask; ++ ++ ds->slave_mii_bus = bus; ++ ++ return devm_of_mdiobus_register(priv->dev, bus, mdio); ++} ++ ++static int + qca8k_setup_mdio_bus(struct qca8k_priv *priv) + { + u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg; +- struct device_node *ports, *port; ++ struct device_node *ports, *port, *mdio; ++ phy_interface_t mode; + int err; + + ports = of_get_child_by_name(priv->dev->of_node, "ports"); +@@ -788,7 +821,10 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + if (!dsa_is_user_port(priv->ds, reg)) + continue; + +- if (of_property_read_bool(port, "phy-handle")) ++ of_get_phy_mode(port, &mode); ++ ++ if (of_property_read_bool(port, "phy-handle") && ++ mode != PHY_INTERFACE_MODE_INTERNAL) + external_mdio_mask |= BIT(reg); + else + internal_mdio_mask |= BIT(reg); +@@ -825,8 +861,23 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + QCA8K_MDIO_MASTER_EN); + } + ++ /* Check if the devicetree declare the port:phy mapping */ ++ mdio = of_get_child_by_name(priv->dev->of_node, "mdio"); ++ if (of_device_is_available(mdio)) { ++ err = qca8k_mdio_register(priv, mdio); ++ if (err) ++ of_node_put(mdio); ++ ++ return err; ++ } ++ ++ /* If a mapping can't be found the legacy mapping is used, ++ * using the qca8k_port_to_phy function ++ */ ++ priv->legacy_phy_port_mapping = true; + priv->ops.phy_read = qca8k_phy_read; + priv->ops.phy_write = qca8k_phy_write; ++ + return 0; + } + +@@ -1212,7 +1263,8 @@ qca8k_phylink_validate(struct dsa_switch + case 5: + /* Internal PHY */ + if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_GMII) ++ state->interface != PHY_INTERFACE_MODE_GMII && ++ state->interface != PHY_INTERFACE_MODE_INTERNAL) + goto unsupported; + break; + case 6: /* 2nd CPU port / external PHY */ +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -255,6 +255,7 @@ struct qca8k_priv { + u8 switch_revision; + u8 rgmii_tx_delay; + u8 rgmii_rx_delay; ++ bool legacy_phy_port_mapping; + struct regmap *regmap; + struct mii_bus *bus; + struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch b/target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch new file mode 100644 index 0000000000..6db01b4b41 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch @@ -0,0 +1,93 @@ +From 0c994a28e7518f098c84a3049cb2915780db873a Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:11 +0200 +Subject: [PATCH] devicetree: bindings: dsa: qca8k: Document internal mdio + definition + +Document new way of declare mapping of internal PHY to port. +The new implementation directly declare the PHY connected to the port +by adding a node in the switch node. The driver detect this and register +an internal mdiobus using the mapping defined in the mdio node. + +Signed-off-by: Ansuel Smith +Reviewed-by: Rob Herring +Signed-off-by: David S. Miller +--- + .../devicetree/bindings/net/dsa/qca8k.txt | 39 +++++++++++++++++++ + 1 file changed, 39 insertions(+) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -21,6 +21,10 @@ described in dsa/dsa.txt. If the QCA8K s + mdio-bus each subnode describing a port needs to have a valid phandle + referencing the internal PHY it is connected to. This is because there's no + N:N mapping of port and PHY id. ++To declare the internal mdio-bus configuration, declare a mdio node in the ++switch node and declare the phandle for the port referencing the internal ++PHY is connected to. In this config a internal mdio-bus is registered and ++the mdio MASTER is used as communication. + + Don't use mixed external and internal mdio-bus configurations, as this is + not supported by the hardware. +@@ -150,26 +154,61 @@ for the internal master mdio-bus configu + port@1 { + reg = <1>; + label = "lan1"; ++ phy-mode = "internal"; ++ phy-handle = <&phy_port1>; + }; + + port@2 { + reg = <2>; + label = "lan2"; ++ phy-mode = "internal"; ++ phy-handle = <&phy_port2>; + }; + + port@3 { + reg = <3>; + label = "lan3"; ++ phy-mode = "internal"; ++ phy-handle = <&phy_port3>; + }; + + port@4 { + reg = <4>; + label = "lan4"; ++ phy-mode = "internal"; ++ phy-handle = <&phy_port4>; + }; + + port@5 { + reg = <5>; + label = "wan"; ++ phy-mode = "internal"; ++ phy-handle = <&phy_port5>; ++ }; ++ }; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy_port1: phy@0 { ++ reg = <0>; ++ }; ++ ++ phy_port2: phy@1 { ++ reg = <1>; ++ }; ++ ++ phy_port3: phy@2 { ++ reg = <2>; ++ }; ++ ++ phy_port4: phy@3 { ++ reg = <3>; ++ }; ++ ++ phy_port5: phy@4 { ++ reg = <4>; + }; + }; + }; diff --git a/target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch b/target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch new file mode 100644 index 0000000000..da8d5b3462 --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch @@ -0,0 +1,95 @@ +From b7ebac354d54f1657bb89b7a7ca149db50203e6a Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:12 +0200 +Subject: [PATCH] net: dsa: qca8k: improve internal mdio read/write bus access + +Improve the internal mdio read/write bus access by caching the value +without accessing it for every read/write. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -655,6 +655,7 @@ static int + qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) + { + struct qca8k_priv *priv = salve_bus->priv; ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; +@@ -669,22 +670,22 @@ qca8k_mdio_write(struct mii_bus *salve_b + + qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(priv->bus, page); ++ ret = qca8k_set_page(bus, page); + if (ret) + goto exit; + +- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + +- ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, ++ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); + +- mutex_unlock(&priv->bus->mdio_lock); ++ mutex_unlock(&bus->mdio_lock); + + return ret; + } +@@ -693,6 +694,7 @@ static int + qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) + { + struct qca8k_priv *priv = salve_bus->priv; ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; +@@ -706,26 +708,26 @@ qca8k_mdio_read(struct mii_bus *salve_bu + + qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(priv->bus, page); ++ ret = qca8k_set_page(bus, page); + if (ret) + goto exit; + +- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + +- ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, ++ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + if (ret) + goto exit; + +- val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); ++ val = qca8k_mii_read32(bus, 0x10 | r2, r1); + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); + +- mutex_unlock(&priv->bus->mdio_lock); ++ mutex_unlock(&bus->mdio_lock); + + if (val >= 0) + val &= QCA8K_MDIO_MASTER_DATA_MASK; diff --git a/target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch b/target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch new file mode 100644 index 0000000000..1179cf152d --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch @@ -0,0 +1,48 @@ +From a46aec02bc06ac2c33f326339e4ef88c735dc30d Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:13 +0200 +Subject: [PATCH] net: dsa: qca8k: pass switch_revision info to phy dev_flags + +Define get_phy_flags to pass switch_Revision needed to tweak the +internal PHY with debug values based on the revision. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1740,6 +1740,22 @@ qca8k_port_vlan_del(struct dsa_switch *d + return ret; + } + ++static u32 qca8k_get_phy_flags(struct dsa_switch *ds, int port) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ /* Communicate to the phy internal driver the switch revision. ++ * Based on the switch revision different values needs to be ++ * set to the dbg and mmd reg on the phy. ++ * The first 2 bit are used to communicate the switch revision ++ * to the phy driver. ++ */ ++ if (port > 0 && port < 6) ++ return priv->switch_revision; ++ ++ return 0; ++} ++ + static enum dsa_tag_protocol + qca8k_get_tag_protocol(struct dsa_switch *ds, int port, + enum dsa_tag_protocol mp) +@@ -1774,6 +1790,7 @@ static const struct dsa_switch_ops qca8k + .phylink_mac_config = qca8k_phylink_mac_config, + .phylink_mac_link_down = qca8k_phylink_mac_link_down, + .phylink_mac_link_up = qca8k_phylink_mac_link_up, ++ .get_phy_flags = qca8k_get_phy_flags, + }; + + static int qca8k_read_switch_id(struct qca8k_priv *priv) diff --git a/target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch b/target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch new file mode 100644 index 0000000000..20325f564d --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch @@ -0,0 +1,229 @@ +From 272833b9b3b3969be7a91839121d86662c8c4253 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 14 May 2021 23:00:15 +0200 +Subject: [PATCH] net: phy: add support for qca8k switch internal PHY in at803x + +Since the at803x share the same regs, it's assumed they are based on the +same implementation. Make it part of the at803x PHY driver to skip +having redudant code. +Add initial support for qca8k internal PHYs. The internal PHYs requires +special mmd and debug values to be set based on the switch revision +passwd using the dev_flags. Supports output of idle, receive and eee_wake +errors stats. +Some debug values sets can't be translated as the documentation lacks any +reference about them. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 5 +- + drivers/net/phy/at803x.c | 132 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 134 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -235,10 +235,11 @@ config NXP_TJA11XX_PHY + Currently supports the NXP TJA1100 and TJA1101 PHY. + + config AT803X_PHY +- tristate "Qualcomm Atheros AR803X PHYs" ++ tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" + depends on REGULATOR + help +- Currently supports the AR8030, AR8031, AR8033 and AR8035 model ++ Currently supports the AR8030, AR8031, AR8033, AR8035 and internal ++ QCA8337(Internal qca8k PHY) model + + config QSEMI_PHY + tristate "Quality Semiconductor PHYs" +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -92,10 +92,16 @@ + #define AT803X_DEBUG_REG_5 0x05 + #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) + ++#define AT803X_DEBUG_REG_3C 0x3C ++ ++#define AT803X_DEBUG_REG_3D 0x3D ++ + #define AT803X_DEBUG_REG_1F 0x1F + #define AT803X_DEBUG_PLL_ON BIT(2) + #define AT803X_DEBUG_RGMII_1V8 BIT(3) + ++#define MDIO_AZ_DEBUG 0x800D ++ + /* AT803x supports either the XTAL input pad, an internal PLL or the + * DSP as clock reference for the clock output pad. The XTAL reference + * is only used for 25 MHz output, all other frequencies need the PLL. +@@ -142,10 +148,34 @@ + #define AT803X_PAGE_FIBER 0 + #define AT803X_PAGE_COPPER 1 + ++#define QCA8327_PHY_ID 0x004dd034 ++#define QCA8337_PHY_ID 0x004dd036 ++#define QCA8K_PHY_ID_MASK 0xffffffff ++ ++#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + ++enum stat_access_type { ++ PHY, ++ MMD ++}; ++ ++struct at803x_hw_stat { ++ const char *string; ++ u8 reg; ++ u32 mask; ++ enum stat_access_type access_type; ++}; ++ ++static struct at803x_hw_stat at803x_hw_stats[] = { ++ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, ++ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, ++ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, ++}; ++ + struct at803x_priv { + int flags; + #define AT803X_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */ +@@ -154,6 +184,7 @@ struct at803x_priv { + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; + struct regulator *vddio; ++ u64 stats[ARRAY_SIZE(at803x_hw_stats)]; + }; + + struct at803x_context { +@@ -165,6 +196,17 @@ struct at803x_context { + u16 led_control; + }; + ++static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, data); ++} ++ + static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) + { + int ret; +@@ -327,6 +369,53 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + ++static int at803x_get_sset_count(struct phy_device *phydev) ++{ ++ return ARRAY_SIZE(at803x_hw_stats); ++} ++ ++static void at803x_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) { ++ strscpy(data + i * ETH_GSTRING_LEN, ++ at803x_hw_stats[i].string, ETH_GSTRING_LEN); ++ } ++} ++ ++static u64 at803x_get_stat(struct phy_device *phydev, int i) ++{ ++ struct at803x_hw_stat stat = at803x_hw_stats[i]; ++ struct at803x_priv *priv = phydev->priv; ++ int val; ++ u64 ret; ++ ++ if (stat.access_type == MMD) ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); ++ else ++ val = phy_read(phydev, stat.reg); ++ ++ if (val < 0) { ++ ret = U64_MAX; ++ } else { ++ val = val & stat.mask; ++ priv->stats[i] += val; ++ ret = priv->stats[i]; ++ } ++ ++ return ret; ++} ++ ++static void at803x_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) ++ data[i] = at803x_get_stat(phydev, i); ++} ++ + static int at803x_suspend(struct phy_device *phydev) + { + int value; +@@ -1102,6 +1191,34 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int qca83xx_config_init(struct phy_device *phydev) ++{ ++ u8 switch_revision; ++ ++ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; ++ ++ switch (switch_revision) { ++ case 1: ++ /* For 100M waveform */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_0, 0x02ea); ++ /* Turn on Gigabit clock */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x68a0); ++ break; ++ ++ case 2: ++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); ++ fallthrough; ++ case 4: ++ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x6860); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_5, 0x2c46); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); ++ break; ++ } ++ ++ return 0; ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -1198,7 +1315,20 @@ static struct phy_driver at803x_driver[] + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +-} }; ++}, { ++ /* QCA8337 */ ++ .phy_id = QCA8337_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "QCA PHY 8337", ++ /* PHY_GBIT_FEATURES */ ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = at803x_get_sset_count, ++ .get_strings = at803x_get_strings, ++ .get_stats = at803x_get_stats, ++}, }; + + module_phy_driver(at803x_driver); + diff --git a/target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch b/target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch new file mode 100644 index 0000000000..a68e3b1821 --- /dev/null +++ b/target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch @@ -0,0 +1,64 @@ +From 0d56e5c191b197e1d30a0a4c92628836dafced0f Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Tue, 18 May 2021 11:24:13 +0000 +Subject: [PATCH] net: dsa: qca8k: fix missing unlock on error in + qca8k_vlan_(add|del) + +Add the missing unlock before return from function qca8k_vlan_add() +and qca8k_vlan_del() in the error handling case. + +Fixes: 028f5f8ef44f ("net: dsa: qca8k: handle error with qca8k_read operation") +Reported-by: Hulk Robot +Signed-off-by: Wei Yongjun +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -506,8 +506,10 @@ qca8k_vlan_add(struct qca8k_priv *priv, + goto out; + + reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); +- if (reg < 0) +- return reg; ++ if (reg < 0) { ++ ret = reg; ++ goto out; ++ } + reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; + reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); + if (untagged) +@@ -519,7 +521,7 @@ qca8k_vlan_add(struct qca8k_priv *priv, + + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); + if (ret) +- return ret; ++ goto out; + ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); + + out: +@@ -541,8 +543,10 @@ qca8k_vlan_del(struct qca8k_priv *priv, + goto out; + + reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); +- if (reg < 0) +- return reg; ++ if (reg < 0) { ++ ret = reg; ++ goto out; ++ } + reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); + reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << + QCA8K_VTU_FUNC0_EG_MODE_S(port); +@@ -564,7 +568,7 @@ qca8k_vlan_del(struct qca8k_priv *priv, + } else { + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); + if (ret) +- return ret; ++ goto out; + ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); + } + diff --git a/target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch b/target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch new file mode 100644 index 0000000000..451b0e9446 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch @@ -0,0 +1,348 @@ +From 7c9896e37807862e276064dd9331860f5d27affc Mon Sep 17 00:00:00 2001 +From: Yang Yingliang +Date: Sat, 29 May 2021 11:04:38 +0800 +Subject: [PATCH] net: dsa: qca8k: check return value of read functions + correctly + +Current return type of qca8k_mii_read32() and qca8k_read() are +unsigned, it can't be negative, so the return value check is +unuseful. For check the return value correctly, change return +type of the read functions and add a output parameter to store +the read value. + +Signed-off-by: Yang Yingliang +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/qca8k.c | 130 +++++++++++++++++++--------------------- + 1 file changed, 60 insertions(+), 70 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -89,26 +89,26 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u + *page = regaddr & 0x3ff; + } + +-static u32 +-qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum) ++static int ++qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + { +- u32 val; + int ret; + + ret = bus->read(bus, phy_id, regnum); + if (ret >= 0) { +- val = ret; ++ *val = ret; + ret = bus->read(bus, phy_id, regnum + 1); +- val |= ret << 16; ++ *val |= ret << 16; + } + + if (ret < 0) { + dev_err_ratelimited(&bus->dev, + "failed to read qca8k 32bit register\n"); ++ *val = 0; + return ret; + } + +- return val; ++ return 0; + } + + static void +@@ -148,26 +148,26 @@ qca8k_set_page(struct mii_bus *bus, u16 + return 0; + } + +-static u32 +-qca8k_read(struct qca8k_priv *priv, u32 reg) ++static int ++qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) + { + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; +- u32 val; ++ int ret; + + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- val = qca8k_set_page(bus, page); +- if (val < 0) ++ ret = qca8k_set_page(bus, page); ++ if (ret < 0) + goto exit; + +- val = qca8k_mii_read32(bus, 0x10 | r2, r1); ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, val); + + exit: + mutex_unlock(&bus->mdio_lock); +- return val; ++ return ret; + } + + static int +@@ -208,11 +208,9 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r + if (ret < 0) + goto exit; + +- val = qca8k_mii_read32(bus, 0x10 | r2, r1); +- if (val < 0) { +- ret = val; ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); ++ if (ret < 0) + goto exit; +- } + + val &= ~mask; + val |= write_val; +@@ -240,15 +238,8 @@ static int + qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ctx; +- int ret; +- +- ret = qca8k_read(priv, reg); +- if (ret < 0) +- return ret; +- +- *val = ret; + +- return 0; ++ return qca8k_read(priv, reg, val); + } + + static int +@@ -296,18 +287,18 @@ static struct regmap_config qca8k_regmap + static int + qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + { ++ int ret, ret1; + u32 val; +- int ret; + +- ret = read_poll_timeout(qca8k_read, val, !(val & mask), ++ ret = read_poll_timeout(qca8k_read, ret1, !(val & mask), + 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- priv, reg); ++ priv, reg, &val); + + /* Check if qca8k_read has failed for a different reason + * before returning -ETIMEDOUT + */ +- if (ret < 0 && val < 0) +- return val; ++ if (ret < 0 && ret1 < 0) ++ return ret1; + + return ret; + } +@@ -316,13 +307,13 @@ static int + qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) + { + u32 reg[4], val; +- int i; ++ int i, ret; + + /* load the ARL table into an array */ + for (i = 0; i < 4; i++) { +- val = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4)); +- if (val < 0) +- return val; ++ ret = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4), &val); ++ if (ret < 0) ++ return ret; + + reg[i] = val; + } +@@ -396,9 +387,9 @@ qca8k_fdb_access(struct qca8k_priv *priv + + /* Check for table full violation when adding an entry */ + if (cmd == QCA8K_FDB_LOAD) { +- reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC); +- if (reg < 0) +- return reg; ++ ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, ®); ++ if (ret < 0) ++ return ret; + if (reg & QCA8K_ATU_FUNC_FULL) + return -1; + } +@@ -477,9 +468,9 @@ qca8k_vlan_access(struct qca8k_priv *pri + + /* Check for table full violation when adding an entry */ + if (cmd == QCA8K_VLAN_LOAD) { +- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1); +- if (reg < 0) +- return reg; ++ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, ®); ++ if (ret < 0) ++ return ret; + if (reg & QCA8K_VTU_FUNC1_FULL) + return -ENOMEM; + } +@@ -505,11 +496,9 @@ qca8k_vlan_add(struct qca8k_priv *priv, + if (ret < 0) + goto out; + +- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); +- if (reg < 0) { +- ret = reg; ++ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); ++ if (ret < 0) + goto out; +- } + reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; + reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); + if (untagged) +@@ -542,11 +531,9 @@ qca8k_vlan_del(struct qca8k_priv *priv, + if (ret < 0) + goto out; + +- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); +- if (reg < 0) { +- ret = reg; ++ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); ++ if (ret < 0) + goto out; +- } + reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); + reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << + QCA8K_VTU_FUNC0_EG_MODE_S(port); +@@ -638,19 +625,19 @@ qca8k_mdio_busy_wait(struct mii_bus *bus + { + u16 r1, r2, page; + u32 val; +- int ret; ++ int ret, ret1; + + qca8k_split_addr(reg, &r1, &r2, &page); + +- ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0, ++ ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- bus, 0x10 | r2, r1); ++ bus, 0x10 | r2, r1, &val); + + /* Check if qca8k_read has failed for a different reason + * before returnting -ETIMEDOUT + */ +- if (ret < 0 && val < 0) +- return val; ++ if (ret < 0 && ret1 < 0) ++ return ret1; + + return ret; + } +@@ -725,7 +712,7 @@ qca8k_mdio_read(struct mii_bus *salve_bu + if (ret) + goto exit; + +- val = qca8k_mii_read32(bus, 0x10 | r2, r1); ++ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +@@ -733,10 +720,10 @@ exit: + + mutex_unlock(&bus->mdio_lock); + +- if (val >= 0) +- val &= QCA8K_MDIO_MASTER_DATA_MASK; ++ if (ret >= 0) ++ ret = val & QCA8K_MDIO_MASTER_DATA_MASK; + +- return val; ++ return ret; + } + + static int +@@ -1211,7 +1198,7 @@ qca8k_phylink_mac_config(struct dsa_swit + qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); + + /* Enable/disable SerDes auto-negotiation as necessary */ +- val = qca8k_read(priv, QCA8K_REG_PWS); ++ qca8k_read(priv, QCA8K_REG_PWS, &val); + if (phylink_autoneg_inband(mode)) + val &= ~QCA8K_PWS_SERDES_AEN_DIS; + else +@@ -1219,7 +1206,7 @@ qca8k_phylink_mac_config(struct dsa_swit + qca8k_write(priv, QCA8K_REG_PWS, val); + + /* Configure the SGMII parameters */ +- val = qca8k_read(priv, QCA8K_REG_SGMII_CTRL); ++ qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); + + val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | + QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD; +@@ -1314,10 +1301,11 @@ qca8k_phylink_mac_link_state(struct dsa_ + { + struct qca8k_priv *priv = ds->priv; + u32 reg; ++ int ret; + +- reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port)); +- if (reg < 0) +- return reg; ++ ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), ®); ++ if (ret < 0) ++ return ret; + + state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); + state->an_complete = state->link; +@@ -1419,19 +1407,20 @@ qca8k_get_ethtool_stats(struct dsa_switc + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + const struct qca8k_mib_desc *mib; + u32 reg, i, val; +- u64 hi; ++ u64 hi = 0; ++ int ret; + + for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { + mib = &ar8327_mib[i]; + reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; + +- val = qca8k_read(priv, reg); +- if (val < 0) ++ ret = qca8k_read(priv, reg, &val); ++ if (ret < 0) + continue; + + if (mib->size == 2) { +- hi = qca8k_read(priv, reg + 4); +- if (hi < 0) ++ ret = qca8k_read(priv, reg + 4, (u32 *)&hi); ++ if (ret < 0) + continue; + } + +@@ -1459,7 +1448,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds, + int ret; + + mutex_lock(&priv->reg_mutex); +- reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL); ++ ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®); + if (reg < 0) { + ret = reg; + goto exit; +@@ -1802,14 +1791,15 @@ static int qca8k_read_switch_id(struct q + const struct qca8k_match_data *data; + u32 val; + u8 id; ++ int ret; + + /* get the switches ID from the compatible */ + data = of_device_get_match_data(priv->dev); + if (!data) + return -ENODEV; + +- val = qca8k_read(priv, QCA8K_REG_MASK_CTRL); +- if (val < 0) ++ ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val); ++ if (ret < 0) + return -ENODEV; + + id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); diff --git a/target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch b/target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch new file mode 100644 index 0000000000..d20da5b85e --- /dev/null +++ b/target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch @@ -0,0 +1,47 @@ +From 9fe99de01440d9ede74d447ac76e9c445d8daae9 Mon Sep 17 00:00:00 2001 +From: Yang Yingliang +Date: Sat, 29 May 2021 11:04:39 +0800 +Subject: [PATCH] net: dsa: qca8k: add missing check return value in + qca8k_phylink_mac_config() + +Now we can check qca8k_read() return value correctly, so if +it fails, we need return directly. + +Signed-off-by: Yang Yingliang +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/qca8k.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1128,6 +1128,7 @@ qca8k_phylink_mac_config(struct dsa_swit + { + struct qca8k_priv *priv = ds->priv; + u32 reg, val; ++ int ret; + + switch (port) { + case 0: /* 1st CPU port */ +@@ -1198,7 +1199,9 @@ qca8k_phylink_mac_config(struct dsa_swit + qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); + + /* Enable/disable SerDes auto-negotiation as necessary */ +- qca8k_read(priv, QCA8K_REG_PWS, &val); ++ ret = qca8k_read(priv, QCA8K_REG_PWS, &val); ++ if (ret) ++ return; + if (phylink_autoneg_inband(mode)) + val &= ~QCA8K_PWS_SERDES_AEN_DIS; + else +@@ -1206,7 +1209,9 @@ qca8k_phylink_mac_config(struct dsa_swit + qca8k_write(priv, QCA8K_REG_PWS, val); + + /* Configure the SGMII parameters */ +- qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); ++ ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); ++ if (ret) ++ return; + + val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | + QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD; diff --git a/target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch b/target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch new file mode 100644 index 0000000000..aed97d0549 --- /dev/null +++ b/target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch @@ -0,0 +1,47 @@ +From aa3d020b22cb844ab7bdbb9e5d861a64666e2b74 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 9 Jun 2021 12:52:12 +0300 +Subject: [PATCH] net: dsa: qca8k: fix an endian bug in + qca8k_get_ethtool_stats() + +The "hi" variable is a u64 but the qca8k_read() writes to the top 32 +bits of it. That will work on little endian systems but it's a bit +subtle. It's cleaner to make declare "hi" as a u32. We will still need +to cast it when we shift it later on in the function but that's fine. + +Fixes: 7c9896e37807 ("net: dsa: qca8k: check return value of read functions correctly") +Signed-off-by: Dan Carpenter +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1412,7 +1412,7 @@ qca8k_get_ethtool_stats(struct dsa_switc + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + const struct qca8k_mib_desc *mib; + u32 reg, i, val; +- u64 hi = 0; ++ u32 hi = 0; + int ret; + + for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { +@@ -1424,14 +1424,14 @@ qca8k_get_ethtool_stats(struct dsa_switc + continue; + + if (mib->size == 2) { +- ret = qca8k_read(priv, reg + 4, (u32 *)&hi); ++ ret = qca8k_read(priv, reg + 4, &hi); + if (ret < 0) + continue; + } + + data[i] = val; + if (mib->size == 2) +- data[i] |= hi << 32; ++ data[i] |= (u64)hi << 32; + } + } + diff --git a/target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch b/target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch new file mode 100644 index 0000000000..c58f79cd8b --- /dev/null +++ b/target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch @@ -0,0 +1,31 @@ +From 3d0167f2a627528032821cdeb78b4eab0510460f Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 9 Jun 2021 12:53:03 +0300 +Subject: [PATCH] net: dsa: qca8k: check the correct variable in + qca8k_set_mac_eee() + +This code check "reg" but "ret" was intended so the error handling will +never trigger. + +Fixes: 7c9896e37807 ("net: dsa: qca8k: check return value of read functions correctly") +Signed-off-by: Dan Carpenter +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1454,10 +1454,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds, + + mutex_lock(&priv->reg_mutex); + ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®); +- if (reg < 0) { +- ret = reg; ++ if (ret < 0) + goto exit; +- } + + if (eee->eee_enabled) + reg |= lpi_en; diff --git a/target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch b/target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch new file mode 100644 index 0000000000..1e293d3a0b --- /dev/null +++ b/target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch @@ -0,0 +1,80 @@ +From ce062a0adbfe933b1932235fdfd874c4c91d1bb0 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sat, 11 Sep 2021 17:50:09 +0200 +Subject: net: dsa: qca8k: fix kernel panic with legacy mdio mapping + +When the mdio legacy mapping is used the mii_bus priv registered by DSA +refer to the dsa switch struct instead of the qca8k_priv struct and +causes a kernel panic. Create dedicated function when the internal +dedicated mdio driver is used to properly handle the 2 different +implementation. + +Fixes: 759bafb8a322 ("net: dsa: qca8k: add support for internal phy and internal mdio") +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 30 ++++++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -643,10 +643,8 @@ qca8k_mdio_busy_wait(struct mii_bus *bus + } + + static int +-qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) ++qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) + { +- struct qca8k_priv *priv = salve_bus->priv; +- struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; +@@ -682,10 +680,8 @@ exit: + } + + static int +-qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) ++qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) + { +- struct qca8k_priv *priv = salve_bus->priv; +- struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; +@@ -727,6 +723,24 @@ exit: + } + + static int ++qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data) ++{ ++ struct qca8k_priv *priv = slave_bus->priv; ++ struct mii_bus *bus = priv->bus; ++ ++ return qca8k_mdio_write(bus, phy, regnum, data); ++} ++ ++static int ++qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) ++{ ++ struct qca8k_priv *priv = slave_bus->priv; ++ struct mii_bus *bus = priv->bus; ++ ++ return qca8k_mdio_read(bus, phy, regnum); ++} ++ ++static int + qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) + { + struct qca8k_priv *priv = ds->priv; +@@ -775,8 +789,8 @@ qca8k_mdio_register(struct qca8k_priv *p + + bus->priv = (void *)priv; + bus->name = "qca8k slave mii"; +- bus->read = qca8k_mdio_read; +- bus->write = qca8k_mdio_write; ++ bus->read = qca8k_internal_mdio_read; ++ bus->write = qca8k_internal_mdio_write; + snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d", + ds->index); + diff --git a/target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch b/target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch new file mode 100644 index 0000000000..91cf55b18a --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch @@ -0,0 +1,65 @@ +From ee47ed08d75e8f16b3cf882061ee19c2ea19dd6c Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Wed, 10 Mar 2021 10:52:26 -0800 +Subject: [PATCH] net: dsa: b53: Add debug prints in b53_vlan_enable() + +Having dynamic debug prints in b53_vlan_enable() has been helpful to +uncover a recent but update the function to indicate the port being +configured (or -1 for initial setup) and include the global VLAN enabled +and VLAN filtering enable status. + +Signed-off-by: Florian Fainelli +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_common.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -349,7 +349,7 @@ static void b53_set_forwarding(struct b5 + b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); + } + +-static void b53_enable_vlan(struct b53_device *dev, bool enable, ++static void b53_enable_vlan(struct b53_device *dev, int port, bool enable, + bool enable_filtering) + { + u8 mgmt, vc0, vc1, vc4 = 0, vc5; +@@ -431,6 +431,9 @@ static void b53_enable_vlan(struct b53_d + b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); + + dev->vlan_enabled = enable; ++ ++ dev_dbg(dev->dev, "Port %d VLAN enabled: %d, filtering: %d\n", ++ port, enable, enable_filtering); + } + + static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100) +@@ -708,7 +711,7 @@ int b53_configure_vlan(struct dsa_switch + b53_do_vlan_op(dev, VTA_CMD_CLEAR); + } + +- b53_enable_vlan(dev, dev->vlan_enabled, ds->vlan_filtering); ++ b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering); + + b53_for_each_port(dev, i) + b53_write16(dev, B53_VLAN_PAGE, +@@ -1390,7 +1393,7 @@ int b53_vlan_filtering(struct dsa_switch + if (switchdev_trans_ph_prepare(trans)) + return 0; + +- b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); ++ b53_enable_vlan(dev, port, dev->vlan_enabled, vlan_filtering); + + return 0; + } +@@ -1415,7 +1418,7 @@ int b53_vlan_prepare(struct dsa_switch * + if (vlan->vid_end >= dev->num_vlans) + return -ERANGE; + +- b53_enable_vlan(dev, true, ds->vlan_filtering); ++ b53_enable_vlan(dev, port, true, ds->vlan_filtering); + + return 0; + } diff --git a/target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch b/target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch new file mode 100644 index 0000000000..56579b2d36 --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch @@ -0,0 +1,41 @@ +From 6d16eadab6db0c1d61e59fee7ed1ecc2d10269be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Mon, 15 Mar 2021 15:14:23 +0100 +Subject: [PATCH] net: dsa: b53: spi: allow device tree probing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add missing of_match_table to allow device tree probing. + +Signed-off-by: Álvaro Fernández Rojas +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_spi.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/net/dsa/b53/b53_spi.c ++++ b/drivers/net/dsa/b53/b53_spi.c +@@ -324,9 +324,22 @@ static int b53_spi_remove(struct spi_dev + return 0; + } + ++static const struct of_device_id b53_spi_of_match[] = { ++ { .compatible = "brcm,bcm5325" }, ++ { .compatible = "brcm,bcm5365" }, ++ { .compatible = "brcm,bcm5395" }, ++ { .compatible = "brcm,bcm5397" }, ++ { .compatible = "brcm,bcm5398" }, ++ { .compatible = "brcm,bcm53115" }, ++ { .compatible = "brcm,bcm53125" }, ++ { .compatible = "brcm,bcm53128" }, ++ { /* sentinel */ } ++}; ++ + static struct spi_driver b53_spi_driver = { + .driver = { + .name = "b53-switch", ++ .of_match_table = b53_spi_of_match, + }, + .probe = b53_spi_probe, + .remove = b53_spi_remove, diff --git a/target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch b/target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch new file mode 100644 index 0000000000..99eced1b6a --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch @@ -0,0 +1,31 @@ +From ad426d7d966b525b73ed5a1842dd830312bbba71 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 17 Mar 2021 09:42:01 +0100 +Subject: [PATCH] net: dsa: b53: relax is63xx() condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM63xx switches are present on bcm63xx and bmips devices. + +Signed-off-by: Álvaro Fernández Rojas +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_priv.h | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -186,11 +186,7 @@ static inline int is531x5(struct b53_dev + + static inline int is63xx(struct b53_device *dev) + { +-#ifdef CONFIG_BCM63XX + return dev->chip_id == BCM63XX_DEVICE_ID; +-#else +- return 0; +-#endif + } + + static inline int is5301x(struct b53_device *dev) diff --git a/target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch b/target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch new file mode 100644 index 0000000000..3b7d8f37cd --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch @@ -0,0 +1,180 @@ +From 964dbf186eaa84d409c359ddf09c827a3fbe8228 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 17 Mar 2021 11:29:26 +0100 +Subject: [PATCH] net: dsa: tag_brcm: add support for legacy tags +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for legacy Broadcom tags, which are similar to DSA_TAG_PROTO_BRCM. +These tags are used on BCM5325, BCM5365 and BCM63xx switches. + +Signed-off-by: Álvaro Fernández Rojas +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 2 + + net/dsa/Kconfig | 7 +++ + net/dsa/tag_brcm.c | 107 +++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 113 insertions(+), 3 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -45,10 +45,12 @@ struct phylink_link_state; + #define DSA_TAG_PROTO_OCELOT_VALUE 15 + #define DSA_TAG_PROTO_AR9331_VALUE 16 + #define DSA_TAG_PROTO_RTL4_A_VALUE 17 ++#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, + DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, ++ DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE, + DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, + DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, + DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -47,6 +47,13 @@ config NET_DSA_TAG_BRCM + Say Y if you want to enable support for tagging frames for the + Broadcom switches which place the tag after the MAC source address. + ++config NET_DSA_TAG_BRCM_LEGACY ++ tristate "Tag driver for Broadcom legacy switches using in-frame headers" ++ select NET_DSA_TAG_BRCM_COMMON ++ help ++ Say Y if you want to enable support for tagging frames for the ++ Broadcom legacy switches which place the tag after the MAC source ++ address. + + config NET_DSA_TAG_BRCM_PREPEND + tristate "Tag driver for Broadcom switches using prepended headers" +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -11,9 +11,26 @@ + + #include "dsa_priv.h" + +-/* This tag length is 4 bytes, older ones were 6 bytes, we do not +- * handle them +- */ ++/* Legacy Broadcom tag (6 bytes) */ ++#define BRCM_LEG_TAG_LEN 6 ++ ++/* Type fields */ ++/* 1st byte in the tag */ ++#define BRCM_LEG_TYPE_HI 0x88 ++/* 2nd byte in the tag */ ++#define BRCM_LEG_TYPE_LO 0x74 ++ ++/* Tag fields */ ++/* 3rd byte in the tag */ ++#define BRCM_LEG_UNICAST (0 << 5) ++#define BRCM_LEG_MULTICAST (1 << 5) ++#define BRCM_LEG_EGRESS (2 << 5) ++#define BRCM_LEG_INGRESS (3 << 5) ++ ++/* 6th byte in the tag */ ++#define BRCM_LEG_PORT_ID (0xf) ++ ++/* Newer Broadcom tag (4 bytes) */ + #define BRCM_TAG_LEN 4 + + /* Tag is constructed and desconstructed using byte by byte access +@@ -194,6 +211,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops); + MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM); + #endif + ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) ++static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct dsa_port *dp = dsa_slave_to_port(dev); ++ u8 *brcm_tag; ++ ++ /* The Ethernet switch we are interfaced with needs packets to be at ++ * least 64 bytes (including FCS) otherwise they will be discarded when ++ * they enter the switch port logic. When Broadcom tags are enabled, we ++ * need to make sure that packets are at least 70 bytes ++ * (including FCS and tag) because the length verification is done after ++ * the Broadcom tag is stripped off the ingress packet. ++ * ++ * Let dsa_slave_xmit() free the SKB ++ */ ++ if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false)) ++ return NULL; ++ ++ skb_push(skb, BRCM_LEG_TAG_LEN); ++ ++ memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN); ++ ++ brcm_tag = skb->data + 2 * ETH_ALEN; ++ ++ /* Broadcom tag type */ ++ brcm_tag[0] = BRCM_LEG_TYPE_HI; ++ brcm_tag[1] = BRCM_LEG_TYPE_LO; ++ ++ /* Broadcom tag value */ ++ brcm_tag[2] = BRCM_LEG_EGRESS; ++ brcm_tag[3] = 0; ++ brcm_tag[4] = 0; ++ brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID; ++ ++ return skb; ++} ++ ++static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, ++ struct net_device *dev, ++ struct packet_type *pt) ++{ ++ int source_port; ++ u8 *brcm_tag; ++ ++ if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID))) ++ return NULL; ++ ++ brcm_tag = skb->data - 2; ++ ++ source_port = brcm_tag[5] & BRCM_LEG_PORT_ID; ++ ++ skb->dev = dsa_master_find_slave(dev, 0, source_port); ++ if (!skb->dev) ++ return NULL; ++ ++ /* Remove Broadcom tag and update checksum */ ++ skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN); ++ ++ skb->offload_fwd_mark = 1; ++ ++ /* Move the Ethernet DA and SA */ ++ memmove(skb->data - ETH_HLEN, ++ skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN, ++ 2 * ETH_ALEN); ++ ++ return skb; ++} ++ ++static const struct dsa_device_ops brcm_legacy_netdev_ops = { ++ .name = "brcm-legacy", ++ .proto = DSA_TAG_PROTO_BRCM_LEGACY, ++ .xmit = brcm_leg_tag_xmit, ++ .rcv = brcm_leg_tag_rcv, ++ .overhead = BRCM_LEG_TAG_LEN, ++}; ++ ++DSA_TAG_DRIVER(brcm_legacy_netdev_ops); ++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY); ++#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */ ++ + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) + static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, + struct net_device *dev) +@@ -226,6 +324,9 @@ static struct dsa_tag_driver *dsa_tag_dr + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) + &DSA_TAG_DRIVER_NAME(brcm_netdev_ops), + #endif ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) ++ &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops), ++#endif + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) + &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), + #endif diff --git a/target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch b/target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch new file mode 100644 index 0000000000..838e78a057 --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch @@ -0,0 +1,53 @@ +From 46c5176c586c81306bf9e7024c13b95da775490f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 17 Mar 2021 11:29:27 +0100 +Subject: [PATCH] net: dsa: b53: support legacy tags +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These tags are used on BCM5325, BCM5365 and BCM63xx switches. + +Signed-off-by: Álvaro Fernández Rojas +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/Kconfig | 1 + + drivers/net/dsa/b53/b53_common.c | 12 +++++++----- + 2 files changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/net/dsa/b53/Kconfig ++++ b/drivers/net/dsa/b53/Kconfig +@@ -3,6 +3,7 @@ menuconfig B53 + tristate "Broadcom BCM53xx managed switch support" + depends on NET_DSA + select NET_DSA_TAG_BRCM ++ select NET_DSA_TAG_BRCM_LEGACY + select NET_DSA_TAG_BRCM_PREPEND + help + This driver adds support for Broadcom managed switch chips. It supports +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2024,15 +2024,17 @@ enum dsa_tag_protocol b53_get_tag_protoc + { + struct b53_device *dev = ds->priv; + +- /* Older models (5325, 5365) support a different tag format that we do +- * not support in net/dsa/tag_brcm.c yet. +- */ +- if (is5325(dev) || is5365(dev) || +- !b53_can_enable_brcm_tags(ds, port, mprot)) { ++ if (!b53_can_enable_brcm_tags(ds, port, mprot)) { + dev->tag_protocol = DSA_TAG_PROTO_NONE; + goto out; + } + ++ /* Older models require a different 6 byte tag */ ++ if (is5325(dev) || is5365(dev) || is63xx(dev)) { ++ dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY; ++ goto out; ++ } ++ + /* Broadcom BCM58xx chips have a flow accelerator on Port 8 + * which requires us to use the prepended Broadcom tag type + */ diff --git a/target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch b/target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch new file mode 100644 index 0000000000..c1014b20bc --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch @@ -0,0 +1,92 @@ +From a5538a777b73b35750ed1ffff8c1ef539e861624 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 17 Mar 2021 10:23:17 +0100 +Subject: [PATCH] net: dsa: b53: mmap: Add device tree support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add device tree support to b53_mmap.c while keeping platform devices support. + +Signed-off-by: Álvaro Fernández Rojas +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_mmap.c | 55 ++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -16,6 +16,7 @@ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#include + #include + #include + #include +@@ -228,11 +229,65 @@ static const struct b53_io_ops b53_mmap_ + .write64 = b53_mmap_write64, + }; + ++static int b53_mmap_probe_of(struct platform_device *pdev, ++ struct b53_platform_data **ppdata) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *of_ports, *of_port; ++ struct device *dev = &pdev->dev; ++ struct b53_platform_data *pdata; ++ void __iomem *mem; ++ ++ mem = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mem)) ++ return PTR_ERR(mem); ++ ++ pdata = devm_kzalloc(dev, sizeof(struct b53_platform_data), ++ GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ ++ pdata->regs = mem; ++ pdata->chip_id = BCM63XX_DEVICE_ID; ++ pdata->big_endian = of_property_read_bool(np, "big-endian"); ++ ++ of_ports = of_get_child_by_name(np, "ports"); ++ if (!of_ports) { ++ dev_err(dev, "no ports child node found\n"); ++ return -EINVAL; ++ } ++ ++ for_each_available_child_of_node(of_ports, of_port) { ++ u32 reg; ++ ++ if (of_property_read_u32(of_port, "reg", ®)) ++ continue; ++ ++ if (reg < B53_CPU_PORT) ++ pdata->enabled_ports |= BIT(reg); ++ } ++ ++ of_node_put(of_ports); ++ *ppdata = pdata; ++ ++ return 0; ++} ++ + static int b53_mmap_probe(struct platform_device *pdev) + { ++ struct device_node *np = pdev->dev.of_node; + struct b53_platform_data *pdata = pdev->dev.platform_data; + struct b53_mmap_priv *priv; + struct b53_device *dev; ++ int ret; ++ ++ if (!pdata && np) { ++ ret = b53_mmap_probe_of(pdev, &pdata); ++ if (ret) { ++ dev_err(&pdev->dev, "OF probe error\n"); ++ return ret; ++ } ++ } + + if (!pdata) + return -EINVAL; diff --git a/target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch b/target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch new file mode 100644 index 0000000000..ea36755732 --- /dev/null +++ b/target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch @@ -0,0 +1,27 @@ +From 866f1577ba69bde2b9f36c300f603596c7d84a62 Mon Sep 17 00:00:00 2001 +From: Qinglang Miao +Date: Thu, 25 Mar 2021 17:19:54 +0800 +Subject: [PATCH] net: dsa: b53: spi: add missing MODULE_DEVICE_TABLE + +This patch adds missing MODULE_DEVICE_TABLE definition which generates +correct modalias for automatic loading of this driver when it is built +as an external module. + +Reported-by: Hulk Robot +Signed-off-by: Qinglang Miao +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_spi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/dsa/b53/b53_spi.c ++++ b/drivers/net/dsa/b53/b53_spi.c +@@ -335,6 +335,7 @@ static const struct of_device_id b53_spi + { .compatible = "brcm,bcm53128" }, + { /* sentinel */ } + }; ++MODULE_DEVICE_TABLE(of, b53_spi_of_match); + + static struct spi_driver b53_spi_driver = { + .driver = { diff --git a/target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch b/target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch new file mode 100644 index 0000000000..2a8def39b8 --- /dev/null +++ b/target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch @@ -0,0 +1,86 @@ +From 2c32a3d3c233b855943677609fe388f82b1f0975 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Tue, 8 Jun 2021 14:22:04 -0700 +Subject: [PATCH] net: dsa: b53: Do not force CPU to be always tagged + +Commit ca8931948344 ("net: dsa: b53: Keep CPU port as tagged in all +VLANs") forced the CPU port to be always tagged in any VLAN membership. +This was necessary back then because we did not support Broadcom tags +for all configurations so the only way to differentiate tagged and +untagged traffic while DSA_TAG_PROTO_NONE was used was to force the CPU +port into being always tagged. + +With most configurations enabling Broadcom tags, especially after +8fab459e69ab ("net: dsa: b53: Enable Broadcom tags for 531x5/539x +families") we do not need to apply this unconditional force tagging of +the CPU port in all VLANs. + +A helper function is introduced to faciliate the encapsulation of the +specific condition requiring the CPU port to be tagged in all VLANs and +the dsa_switch_ops::untag_bridge_pvid boolean is moved to when +dsa_switch_ops::setup is called when we have already determined the +tagging protocol we will be using. + +Reported-by: Matthew Hagan +Signed-off-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Tested-by: Matthew Hagan +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_common.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1049,6 +1049,11 @@ static int b53_setup(struct dsa_switch * + unsigned int port; + int ret; + ++ /* Request bridge PVID untagged when DSA_TAG_PROTO_NONE is set ++ * which forces the CPU port to be tagged in all VLANs. ++ */ ++ ds->untag_bridge_pvid = dev->tag_protocol == DSA_TAG_PROTO_NONE; ++ + ret = b53_reset_switch(dev); + if (ret) { + dev_err(ds->dev, "failed to reset switch\n"); +@@ -1423,6 +1428,13 @@ int b53_vlan_prepare(struct dsa_switch * + return 0; + } + EXPORT_SYMBOL(b53_vlan_prepare); ++ ++static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) ++{ ++ struct b53_device *dev = ds->priv; ++ ++ return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); ++} + + void b53_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +@@ -1442,7 +1454,7 @@ void b53_vlan_add(struct dsa_switch *ds, + untagged = true; + + vl->members |= BIT(port); +- if (untagged && !dsa_is_cpu_port(ds, port)) ++ if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port)) + vl->untag |= BIT(port); + else + vl->untag &= ~BIT(port); +@@ -1480,7 +1492,7 @@ int b53_vlan_del(struct dsa_switch *ds, + if (pvid == vid) + pvid = b53_default_pvid(dev); + +- if (untagged && !dsa_is_cpu_port(ds, port)) ++ if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port)) + vl->untag &= ~(BIT(port)); + + b53_set_vlan_entry(dev, vid, vl); +@@ -2644,7 +2656,6 @@ struct b53_device *b53_switch_alloc(stru + dev->ops = ops; + ds->ops = &b53_switch_ops; + ds->configure_vlan_while_not_filtering = true; +- ds->untag_bridge_pvid = true; + dev->vlan_enabled = ds->configure_vlan_while_not_filtering; + /* Let DSA handle the case were multiple bridges span the same switch + * device and different VLAN awareness settings are requested, which diff --git a/target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch b/target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch new file mode 100644 index 0000000000..ee3a71ffa5 --- /dev/null +++ b/target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch @@ -0,0 +1,30 @@ +From 11b57faf951cd3a570e3d9e463fc7c41023bc8c6 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Tue, 15 Jun 2021 10:05:16 +0100 +Subject: [PATCH] net: dsa: b53: remove redundant null check on dev + +The pointer dev can never be null, the null check is redundant +and can be removed. Cleans up a static analysis warning that +pointer priv is dereferencing dev before dev is being null +checked. + +Addresses-Coverity: ("Dereference before null check") +Signed-off-by: Colin Ian King +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_srab.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/dsa/b53/b53_srab.c ++++ b/drivers/net/dsa/b53/b53_srab.c +@@ -632,8 +632,7 @@ static int b53_srab_remove(struct platfo + struct b53_srab_priv *priv = dev->priv; + + b53_srab_intr_set(priv, false); +- if (dev) +- b53_switch_remove(dev); ++ b53_switch_remove(dev); + + return 0; + } diff --git a/target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch b/target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch new file mode 100644 index 0000000000..df891d68ab --- /dev/null +++ b/target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch @@ -0,0 +1,71 @@ +From 64a81b24487f0d2fba0f033029eec2abc7d82cee Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Mon, 21 Jun 2021 15:10:55 -0700 +Subject: [PATCH] net: dsa: b53: Create default VLAN entry explicitly + +In case CONFIG_VLAN_8021Q is not set, there will be no call down to the +b53 driver to ensure that the default PVID VLAN entry will be configured +with the appropriate untagged attribute towards the CPU port. We were +implicitly relying on dsa_slave_vlan_rx_add_vid() to do that for us, +instead make it explicit. + +Reported-by: Vladimir Oltean +Signed-off-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/b53/b53_common.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -693,6 +693,13 @@ static u16 b53_default_pvid(struct b53_d + return 0; + } + ++static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) ++{ ++ struct b53_device *dev = ds->priv; ++ ++ return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); ++} ++ + int b53_configure_vlan(struct dsa_switch *ds) + { + struct b53_device *dev = ds->priv; +@@ -713,9 +720,20 @@ int b53_configure_vlan(struct dsa_switch + + b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering); + +- b53_for_each_port(dev, i) ++ /* Create an untagged VLAN entry for the default PVID in case ++ * CONFIG_VLAN_8021Q is disabled and there are no calls to ++ * dsa_slave_vlan_rx_add_vid() to create the default VLAN ++ * entry. Do this only when the tagging protocol is not ++ * DSA_TAG_PROTO_NONE ++ */ ++ b53_for_each_port(dev, i) { ++ v = &dev->vlans[def_vid]; ++ v->members |= BIT(i); ++ if (!b53_vlan_port_needs_forced_tagged(ds, i)) ++ v->untag = v->members; + b53_write16(dev, B53_VLAN_PAGE, + B53_VLAN_PORT_DEF_TAG(i), def_vid); ++ } + + /* Upon initial call we have not set-up any VLANs, but upon + * system resume, we need to restore all VLAN entries. +@@ -1429,13 +1447,6 @@ int b53_vlan_prepare(struct dsa_switch * + } + EXPORT_SYMBOL(b53_vlan_prepare); + +-static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) +-{ +- struct b53_device *dev = ds->priv; +- +- return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); +-} +- + void b53_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) + { diff --git a/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch b/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch new file mode 100644 index 0000000000..16aa0711ad --- /dev/null +++ b/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch @@ -0,0 +1,48 @@ +From 0ccf8511182436183c031e8a2f740ae91a02c625 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 14 Sep 2021 14:33:45 +0200 +Subject: net: phy: at803x: add support for qca 8327 internal phy + +Add support for qca8327 internal phy needed for correct init of the +switch port. It does use the same qca8337 function and reg just with a +different id. + +Signed-off-by: Ansuel Smith +Tested-by: Rosen Penev +Tested-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1328,6 +1328,19 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, ++}, { ++ /* QCA8327 */ ++ .phy_id = QCA8327_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "QCA PHY 8327", ++ /* PHY_GBIT_FEATURES */ ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = at803x_get_sset_count, ++ .get_strings = at803x_get_strings, ++ .get_stats = at803x_get_stats, + }, }; + + module_phy_driver(at803x_driver); +@@ -1338,6 +1351,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_PHY_ID) }, + { } + }; + diff --git a/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch b/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch new file mode 100644 index 0000000000..d80b5db714 --- /dev/null +++ b/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch @@ -0,0 +1,131 @@ +From 983d96a9116a328668601555d96736261d33170c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 Sep 2021 14:03:51 +0200 +Subject: [PATCH] net: dsa: b53: Include all ports in "enabled_ports" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make "enabled_ports" bitfield contain all available switch ports +including a CPU port. This way there is no need for fixup during +initialization. + +For BCM53010, BCM53018 and BCM53019 include also other available ports. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2288,7 +2288,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM5325_DEVICE_ID, + .dev_name = "BCM5325", + .vlans = 16, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x3f, + .arl_bins = 2, + .arl_buckets = 1024, + .imp_port = 5, +@@ -2299,7 +2299,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM5365_DEVICE_ID, + .dev_name = "BCM5365", + .vlans = 256, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x3f, + .arl_bins = 2, + .arl_buckets = 1024, + .imp_port = 5, +@@ -2310,7 +2310,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM5389_DEVICE_ID, + .dev_name = "BCM5389", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x11f, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2324,7 +2324,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM5395_DEVICE_ID, + .dev_name = "BCM5395", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x11f, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2338,7 +2338,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM5397_DEVICE_ID, + .dev_name = "BCM5397", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x11f, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2352,7 +2352,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM5398_DEVICE_ID, + .dev_name = "BCM5398", + .vlans = 4096, +- .enabled_ports = 0x7f, ++ .enabled_ports = 0x17f, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2366,7 +2366,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM53115_DEVICE_ID, + .dev_name = "BCM53115", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x11f, + .arl_bins = 4, + .arl_buckets = 1024, + .vta_regs = B53_VTA_REGS, +@@ -2380,7 +2380,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM53125_DEVICE_ID, + .dev_name = "BCM53125", + .vlans = 4096, +- .enabled_ports = 0xff, ++ .enabled_ports = 0x1ff, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2422,7 +2422,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM53010_DEVICE_ID, + .dev_name = "BCM53010", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x1bf, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2464,7 +2464,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM53018_DEVICE_ID, + .dev_name = "BCM53018", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x1bf, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2478,7 +2478,7 @@ static const struct b53_chip_data b53_sw + .chip_id = BCM53019_DEVICE_ID, + .dev_name = "BCM53019", + .vlans = 4096, +- .enabled_ports = 0x1f, ++ .enabled_ports = 0x1bf, + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +@@ -2605,7 +2605,6 @@ static int b53_switch_init(struct b53_de + dev->cpu_port = 5; + } + +- dev->enabled_ports |= BIT(dev->cpu_port); + dev->num_ports = fls(dev->enabled_ports); + + dev->ds->num_ports = min_t(unsigned int, dev->num_ports, DSA_MAX_PORTS); diff --git a/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch b/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch new file mode 100644 index 0000000000..4a4f8e940d --- /dev/null +++ b/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch @@ -0,0 +1,42 @@ +From b290c6384afabbca5ae6e2af72fb1b2bc37922be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 Sep 2021 14:03:52 +0200 +Subject: [PATCH] net: dsa: b53: Drop BCM5301x workaround for a wrong CPU/IMP + port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On BCM5301x port 8 requires a fixed link when used. + +Years ago when b53 was an OpenWrt downstream driver (with configuration +based on sometimes bugged NVRAM) there was a need for a fixup. In case +of forcing fixed link for (incorrectly specified) port 5 the code had to +actually setup port 8 link. + +For upstream b53 driver with setup based on DT there is no need for that +workaround. In DT we have and require correct ports setup. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1256,12 +1256,6 @@ static void b53_adjust_link(struct dsa_s + return; + } + } +- } else if (is5301x(dev)) { +- if (port != dev->cpu_port) { +- b53_force_port_config(dev, dev->cpu_port, 2000, +- DUPLEX_FULL, true, true); +- b53_force_link(dev, dev->cpu_port, 1); +- } + } + + /* Re-negotiate EEE if it was enabled already */ diff --git a/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch b/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch new file mode 100644 index 0000000000..3954ee4aac --- /dev/null +++ b/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch @@ -0,0 +1,32 @@ +From 3ff26b29230c54fea2353b63124c589b61953e14 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 Sep 2021 14:03:53 +0200 +Subject: [PATCH] net: dsa: b53: Improve flow control setup on BCM5301x +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to the Broadcom's reference driver flow control needs to be +enabled for any CPU switch port (5, 7 or 8 - depending on which one is +used). Current code makes it work only for the port 5. Use +dsa_is_cpu_port() which solved that problem. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1187,7 +1187,7 @@ static void b53_adjust_link(struct dsa_s + return; + + /* Enable flow control on BCM5301x's CPU port */ +- if (is5301x(dev) && port == dev->cpu_port) ++ if (is5301x(dev) && dsa_is_cpu_port(ds, port)) + tx_pause = rx_pause = true; + + if (phydev->pause) { diff --git a/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch b/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch new file mode 100644 index 0000000000..9e687b1488 --- /dev/null +++ b/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch @@ -0,0 +1,205 @@ +From 7d5af56418d7d01e43247a33b6fe6492ea871923 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 Sep 2021 14:03:54 +0200 +Subject: [PATCH] net: dsa: b53: Drop unused "cpu_port" field +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's set but never used anymore. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 28 ---------------------------- + drivers/net/dsa/b53/b53_priv.h | 1 - + 2 files changed, 29 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2286,7 +2286,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 2, + .arl_buckets = 1024, + .imp_port = 5, +- .cpu_port = B53_CPU_PORT_25, + .duplex_reg = B53_DUPLEX_STAT_FE, + }, + { +@@ -2297,7 +2296,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 2, + .arl_buckets = 1024, + .imp_port = 5, +- .cpu_port = B53_CPU_PORT_25, + .duplex_reg = B53_DUPLEX_STAT_FE, + }, + { +@@ -2308,7 +2306,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2322,7 +2319,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2336,7 +2332,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS_9798, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2350,7 +2345,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS_9798, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2365,7 +2359,6 @@ static const struct b53_chip_data b53_sw + .arl_buckets = 1024, + .vta_regs = B53_VTA_REGS, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, +@@ -2378,7 +2371,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2392,7 +2384,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2406,7 +2397,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS_63XX, + .duplex_reg = B53_DUPLEX_STAT_63XX, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, +@@ -2420,7 +2410,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2434,7 +2423,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2448,7 +2436,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2462,7 +2449,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2476,7 +2462,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2490,7 +2475,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2504,7 +2488,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2518,7 +2501,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 1024, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2532,7 +2514,6 @@ static const struct b53_chip_data b53_sw + .arl_bins = 4, + .arl_buckets = 256, + .imp_port = 8, +- .cpu_port = B53_CPU_PORT, + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, +@@ -2558,7 +2539,6 @@ static int b53_switch_init(struct b53_de + dev->vta_regs[2] = chip->vta_regs[2]; + dev->jumbo_pm_reg = chip->jumbo_pm_reg; + dev->imp_port = chip->imp_port; +- dev->cpu_port = chip->cpu_port; + dev->num_vlans = chip->vlans; + dev->num_arl_bins = chip->arl_bins; + dev->num_arl_buckets = chip->arl_buckets; +@@ -2590,13 +2570,6 @@ static int b53_switch_init(struct b53_de + break; + #endif + } +- } else if (dev->chip_id == BCM53115_DEVICE_ID) { +- u64 strap_value; +- +- b53_read48(dev, B53_STAT_PAGE, B53_STRAP_VALUE, &strap_value); +- /* use second IMP port if GMII is enabled */ +- if (strap_value & SV_GMII_CTRL_115) +- dev->cpu_port = 5; + } + + dev->num_ports = fls(dev->enabled_ports); +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -123,7 +123,6 @@ struct b53_device { + /* used ports mask */ + u16 enabled_ports; + unsigned int imp_port; +- unsigned int cpu_port; + + /* connect specific data */ + u8 current_page; diff --git a/target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch b/target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch new file mode 100644 index 0000000000..ab4fdf8509 --- /dev/null +++ b/target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch @@ -0,0 +1,138 @@ +From bea7907837c57a0aaac009931eb14efb056dafab Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 29 Jul 2021 17:56:00 +0300 +Subject: [PATCH] net: dsa: don't set skb->offload_fwd_mark when not offloading + the bridge + +DSA has gained the recent ability to deal gracefully with upper +interfaces it cannot offload, such as the bridge, bonding or team +drivers. When such uppers exist, the ports are still in standalone mode +as far as the hardware is concerned. + +But when we deliver packets to the software bridge in order for that to +do the forwarding, there is an unpleasant surprise in that the bridge +will refuse to forward them. This is because we unconditionally set +skb->offload_fwd_mark = true, meaning that the bridge thinks the frames +were already forwarded in hardware by us. + +Since dp->bridge_dev is populated only when there is hardware offload +for it, but not in the software fallback case, let's introduce a new +helper that can be called from the tagger data path which sets the +skb->offload_fwd_mark accordingly to zero when there is no hardware +offload for bridging. This lets the bridge forward packets back to other +interfaces of our switch, if needed. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Tobias Waldekranz +Signed-off-by: David S. Miller +--- + net/dsa/dsa_priv.h | 14 ++++++++++++++ + net/dsa/tag_brcm.c | 4 ++-- + net/dsa/tag_dsa.c | 15 +++++++++++---- + net/dsa/tag_ksz.c | 2 +- + net/dsa/tag_lan9303.c | 3 ++- + net/dsa/tag_mtk.c | 2 +- + net/dsa/tag_ocelot.c | 2 +- + net/dsa/tag_rtl4_a.c | 2 +- + net/dsa/tag_sja1105.c | 20 ++++++++++++++------ + 9 files changed, 47 insertions(+), 17 deletions(-) + +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -266,6 +266,20 @@ static inline struct sk_buff *dsa_untag_ + return skb; + } + ++/* If the ingress port offloads the bridge, we mark the frame as autonomously ++ * forwarded by hardware, so the software bridge doesn't forward in twice, back ++ * to us, because we already did. However, if we're in fallback mode and we do ++ * software bridging, we are not offloading it, therefore the dp->bridge_dev ++ * pointer is not populated, and flooding needs to be done by software (we are ++ * effectively operating in standalone ports mode). ++ */ ++static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb) ++{ ++ struct dsa_port *dp = dsa_slave_to_port(skb->dev); ++ ++ skb->offload_fwd_mark = !!(dp->bridge_dev); ++} ++ + /* switch.c */ + int dsa_switch_register_notifier(struct dsa_switch *ds); + void dsa_switch_unregister_notifier(struct dsa_switch *ds); +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -166,7 +166,7 @@ static struct sk_buff *brcm_tag_rcv_ll(s + /* Remove Broadcom tag and update checksum */ + skb_pull_rcsum(skb, BRCM_TAG_LEN); + +- skb->offload_fwd_mark = 1; ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } +@@ -270,7 +270,7 @@ static struct sk_buff *brcm_leg_tag_rcv( + /* Remove Broadcom tag and update checksum */ + skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN); + +- skb->offload_fwd_mark = 1; ++ dsa_default_offload_fwd_mark(skb); + + /* Move the Ethernet DA and SA */ + memmove(skb->data - ETH_HLEN, +--- a/net/dsa/tag_ksz.c ++++ b/net/dsa/tag_ksz.c +@@ -24,7 +24,7 @@ static struct sk_buff *ksz_common_rcv(st + + pskb_trim_rcsum(skb, skb->len - len); + +- skb->offload_fwd_mark = true; ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } +--- a/net/dsa/tag_lan9303.c ++++ b/net/dsa/tag_lan9303.c +@@ -115,7 +115,8 @@ static struct sk_buff *lan9303_rcv(struc + skb_pull_rcsum(skb, 2 + 2); + memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN), + 2 * ETH_ALEN); +- skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU); ++ if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU)) ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -104,7 +104,7 @@ static struct sk_buff *mtk_tag_rcv(struc + + /* Only unicast or broadcast frames are offloaded */ + if (likely(!is_multicast_skb)) +- skb->offload_fwd_mark = 1; ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } +--- a/net/dsa/tag_ocelot.c ++++ b/net/dsa/tag_ocelot.c +@@ -225,7 +225,7 @@ static struct sk_buff *ocelot_rcv(struct + */ + return NULL; + +- skb->offload_fwd_mark = 1; ++ dsa_default_offload_fwd_mark(skb); + skb->priority = qos_class; + + /* Ocelot switches copy frames unmodified to the CPU. However, it is +--- a/net/dsa/tag_rtl4_a.c ++++ b/net/dsa/tag_rtl4_a.c +@@ -115,7 +115,7 @@ static struct sk_buff *rtl4a_tag_rcv(str + skb->data - ETH_HLEN - RTL4_A_HDR_LEN, + 2 * ETH_ALEN); + +- skb->offload_fwd_mark = 1; ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } diff --git a/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch b/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch new file mode 100644 index 0000000000..c82bf913a0 --- /dev/null +++ b/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch @@ -0,0 +1,65 @@ +From b4df02b562f4aa14ff6811f30e1b4d2159585c59 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 19 Sep 2021 18:28:15 +0200 +Subject: net: phy: at803x: add support for qca 8327 A variant internal phy + +For qca8327 internal phy there are 2 different switch variant with 2 +different phy id. Add this missing variant so the internal phy can be +correctly identified and fixed. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -148,7 +148,8 @@ + #define AT803X_PAGE_FIBER 0 + #define AT803X_PAGE_COPPER 1 + +-#define QCA8327_PHY_ID 0x004dd034 ++#define QCA8327_A_PHY_ID 0x004dd033 ++#define QCA8327_B_PHY_ID 0x004dd034 + #define QCA8337_PHY_ID 0x004dd036 + #define QCA8K_PHY_ID_MASK 0xffffffff + +@@ -1329,10 +1330,23 @@ static struct phy_driver at803x_driver[] + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, + }, { +- /* QCA8327 */ +- .phy_id = QCA8327_PHY_ID, ++ /* QCA8327-A from switch QCA8327-AL1A */ ++ .phy_id = QCA8327_A_PHY_ID, + .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "QCA PHY 8327", ++ .name = "QCA PHY 8327-A", ++ /* PHY_GBIT_FEATURES */ ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = at803x_get_sset_count, ++ .get_strings = at803x_get_strings, ++ .get_stats = at803x_get_stats, ++}, { ++ /* QCA8327-B from switch QCA8327-BL1A */ ++ .phy_id = QCA8327_B_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "QCA PHY 8327-B", + /* PHY_GBIT_FEATURES */ + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +@@ -1352,7 +1366,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, + { } + }; + diff --git a/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch b/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch new file mode 100644 index 0000000000..be24fd5cf7 --- /dev/null +++ b/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch @@ -0,0 +1,45 @@ +From 15b9df4ece17d084f14eb0ca1cf05f2ad497e425 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 19 Sep 2021 18:28:16 +0200 +Subject: net: phy: at803x: add resume/suspend function to qca83xx phy + +Add resume/suspend function to qca83xx internal phy. +We can't use the at803x generic function as the documentation lacks of +any support for WoL regs. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1329,6 +1329,8 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ + .phy_id = QCA8327_A_PHY_ID, +@@ -1342,6 +1344,8 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ + .phy_id = QCA8327_B_PHY_ID, +@@ -1355,6 +1359,8 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, }; + + module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch b/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch new file mode 100644 index 0000000000..23f574c76f --- /dev/null +++ b/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch @@ -0,0 +1,95 @@ +From d44fd8604a4ab92119adb35f05fd87612af722b5 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 19 Sep 2021 18:28:17 +0200 +Subject: net: phy: at803x: fix spacing and improve name for 83xx phy + +Fix spacing and improve name for 83xx phy following other phy in the +same driver. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 60 ++++++++++++++++++++++++------------------------ + 1 file changed, 30 insertions(+), 30 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1318,47 +1318,47 @@ static struct phy_driver at803x_driver[] + .config_aneg = at803x_config_aneg, + }, { + /* QCA8337 */ +- .phy_id = QCA8337_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "QCA PHY 8337", ++ .phy_id = QCA8337_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8337 internal PHY", + /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = at803x_get_sset_count, ++ .get_strings = at803x_get_strings, ++ .get_stats = at803x_get_stats, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ +- .phy_id = QCA8327_A_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "QCA PHY 8327-A", ++ .phy_id = QCA8327_A_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-A internal PHY", + /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = at803x_get_sset_count, ++ .get_strings = at803x_get_strings, ++ .get_stats = at803x_get_stats, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ +- .phy_id = QCA8327_B_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "QCA PHY 8327-B", ++ .phy_id = QCA8327_B_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-B internal PHY", + /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = at803x_get_sset_count, ++ .get_strings = at803x_get_strings, ++ .get_stats = at803x_get_stats, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, }; diff --git a/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch b/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch new file mode 100644 index 0000000000..5dfe27dd24 --- /dev/null +++ b/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch @@ -0,0 +1,131 @@ +From ba3c01ee02ed0d821c9f241f179bbc9457542b8f Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 10 Oct 2021 00:46:15 +0200 +Subject: net: phy: at803x: fix resume for QCA8327 phy + +From Documentation phy resume triggers phy reset and restart +auto-negotiation. Add a dedicated function to wait reset to finish as +it was notice a regression where port sometime are not reliable after a +suspend/resume session. The reset wait logic is copied from phy_poll_reset. +Add dedicated suspend function to use genphy_suspend only with QCA8337 +phy and set only additional debug settings for QCA8327. With more test +it was reported that QCA8327 doesn't proprely support this mode and +using this cause the unreliability of the switch ports, especially the +malfunction of the port0. + +Fixes: 15b9df4ece17 ("net: phy: at803x: add resume/suspend function to qca83xx phy") +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 69 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 63 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -92,9 +92,14 @@ + #define AT803X_DEBUG_REG_5 0x05 + #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) + ++#define AT803X_DEBUG_REG_HIB_CTRL 0x0b ++#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) ++#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) ++ + #define AT803X_DEBUG_REG_3C 0x3C + + #define AT803X_DEBUG_REG_3D 0x3D ++#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) + + #define AT803X_DEBUG_REG_1F 0x1F + #define AT803X_DEBUG_PLL_ON BIT(2) +@@ -1220,6 +1225,58 @@ static int qca83xx_config_init(struct ph + return 0; + } + ++static int qca83xx_resume(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ /* Skip reset if not suspended */ ++ if (!phydev->suspended) ++ return 0; ++ ++ /* Reinit the port, reset values set by suspend */ ++ qca83xx_config_init(phydev); ++ ++ /* Reset the port on port resume */ ++ phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ ++ /* On resume from suspend the switch execute a reset and ++ * restart auto-negotiation. Wait for reset to complete. ++ */ ++ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), ++ 50000, 600000, true); ++ if (ret) ++ return ret; ++ ++ msleep(1); ++ ++ return 0; ++} ++ ++static int qca83xx_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* Only QCA8337 support actual suspend. ++ * QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ if (phydev->drv->phy_id == QCA8337_PHY_ID) { ++ genphy_suspend(phydev); ++ } else { ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ } ++ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_3D, ++ AT803X_DEBUG_GATE_CLK_IN1000, 0); ++ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | ++ AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); ++ ++ return 0; ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -1329,8 +1386,8 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = qca83xx_suspend, ++ .resume = qca83xx_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ + .phy_id = QCA8327_A_PHY_ID, +@@ -1344,8 +1401,8 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = qca83xx_suspend, ++ .resume = qca83xx_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ + .phy_id = QCA8327_B_PHY_ID, +@@ -1359,8 +1416,8 @@ static struct phy_driver at803x_driver[] + .get_sset_count = at803x_get_sset_count, + .get_strings = at803x_get_strings, + .get_stats = at803x_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = qca83xx_suspend, ++ .resume = qca83xx_resume, + }, }; + + module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch b/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch new file mode 100644 index 0000000000..aeb43e2f67 --- /dev/null +++ b/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch @@ -0,0 +1,91 @@ +From 1ca8311949aec5c9447645731ef1c6bc5bd71350 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 10 Oct 2021 00:46:16 +0200 +Subject: net: phy: at803x: add DAC amplitude fix for 8327 phy + +QCA8327 internal phy require DAC amplitude adjustement set to +6% with +100m speed. Also add additional define to report a change of the same +reg in QCA8337. (different scope it does set 1000m voltage) +Add link_change_notify function to set the proper amplitude adjustement +on PHY_RUNNING state and disable on any other state. + +Fixes: b4df02b562f4 ("net: phy: at803x: add support for qca 8327 A variant internal phy") +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -87,6 +87,8 @@ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + + #define AT803X_DEBUG_REG_0 0x00 ++#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) ++#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) + #define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) + + #define AT803X_DEBUG_REG_5 0x05 +@@ -1222,9 +1224,37 @@ static int qca83xx_config_init(struct ph + break; + } + ++ /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. ++ * Disable on init and enable only with 100m speed following ++ * qca original source code. ++ */ ++ if (phydev->drv->phy_id == QCA8327_A_PHY_ID || ++ phydev->drv->phy_id == QCA8327_B_PHY_ID) ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ + return 0; + } + ++static void qca83xx_link_change_notify(struct phy_device *phydev) ++{ ++ /* QCA8337 doesn't require DAC Amplitude adjustement */ ++ if (phydev->drv->phy_id == QCA8337_PHY_ID) ++ return; ++ ++ /* Set DAC Amplitude adjustment to +6% for 100m on link running */ ++ if (phydev->state == PHY_RUNNING) { ++ if (phydev->speed == SPEED_100) ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ QCA8327_DEBUG_MANU_CTRL_EN, ++ QCA8327_DEBUG_MANU_CTRL_EN); ++ } else { ++ /* Reset DAC Amplitude adjustment */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ } ++} ++ + static int qca83xx_resume(struct phy_device *phydev) + { + int ret, val; +@@ -1379,6 +1409,7 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8337 internal PHY", + /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, +@@ -1394,6 +1425,7 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8327-A internal PHY", + /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, +@@ -1409,6 +1441,7 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8327-B internal PHY", + /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, diff --git a/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch b/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch new file mode 100644 index 0000000000..2352fa0e44 --- /dev/null +++ b/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch @@ -0,0 +1,27 @@ +From 9d1c29b4028557a496be9c5eb2b4b86063700636 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 10 Oct 2021 00:46:17 +0200 +Subject: net: phy: at803x: enable prefer master for 83xx internal phy + +From original QCA source code the port was set to prefer master as port +type in 1000BASE-T mode. Apply the same settings also here. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1233,6 +1233,9 @@ static int qca83xx_config_init(struct ph + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, + QCA8327_DEBUG_MANU_CTRL_EN, 0); + ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ + return 0; + } + diff --git a/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch b/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch new file mode 100644 index 0000000000..9c28a893f1 --- /dev/null +++ b/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch @@ -0,0 +1,127 @@ +From 67999555ff42e91de7654488d9a7735bd9e84555 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 10 Oct 2021 00:46:18 +0200 +Subject: net: phy: at803x: better describe debug regs + +Give a name to known debug regs from Documentation instead of using +unknown hex values. + +Signed-off-by: Ansuel Smith +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -86,12 +86,12 @@ + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + +-#define AT803X_DEBUG_REG_0 0x00 ++#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 + #define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) + #define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) + #define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) + +-#define AT803X_DEBUG_REG_5 0x05 ++#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 + #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) + + #define AT803X_DEBUG_REG_HIB_CTRL 0x0b +@@ -100,7 +100,7 @@ + + #define AT803X_DEBUG_REG_3C 0x3C + +-#define AT803X_DEBUG_REG_3D 0x3D ++#define AT803X_DEBUG_REG_GREEN 0x3D + #define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) + + #define AT803X_DEBUG_REG_1F 0x1F +@@ -274,25 +274,25 @@ static int at803x_read_page(struct phy_d + + static int at803x_enable_rx_delay(struct phy_device *phydev) + { +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0, + AT803X_DEBUG_RX_CLK_DLY_EN); + } + + static int at803x_enable_tx_delay(struct phy_device *phydev) + { +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0, + AT803X_DEBUG_TX_CLK_DLY_EN); + } + + static int at803x_disable_rx_delay(struct phy_device *phydev) + { +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, + AT803X_DEBUG_RX_CLK_DLY_EN, 0); + } + + static int at803x_disable_tx_delay(struct phy_device *phydev) + { +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, + AT803X_DEBUG_TX_CLK_DLY_EN, 0); + } + +@@ -1208,9 +1208,9 @@ static int qca83xx_config_init(struct ph + switch (switch_revision) { + case 1: + /* For 100M waveform */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_0, 0x02ea); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); + /* Turn on Gigabit clock */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x68a0); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); + break; + + case 2: +@@ -1218,8 +1218,8 @@ static int qca83xx_config_init(struct ph + fallthrough; + case 4: + phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x6860); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_5, 0x2c46); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); + at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); + break; + } +@@ -1230,7 +1230,7 @@ static int qca83xx_config_init(struct ph + */ + if (phydev->drv->phy_id == QCA8327_A_PHY_ID || + phydev->drv->phy_id == QCA8327_B_PHY_ID) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, + QCA8327_DEBUG_MANU_CTRL_EN, 0); + + /* Following original QCA sourcecode set port to prefer master */ +@@ -1248,12 +1248,12 @@ static void qca83xx_link_change_notify(s + /* Set DAC Amplitude adjustment to +6% for 100m on link running */ + if (phydev->state == PHY_RUNNING) { + if (phydev->speed == SPEED_100) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, + QCA8327_DEBUG_MANU_CTRL_EN, + QCA8327_DEBUG_MANU_CTRL_EN); + } else { + /* Reset DAC Amplitude adjustment */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, + QCA8327_DEBUG_MANU_CTRL_EN, 0); + } + } +@@ -1300,7 +1300,7 @@ static int qca83xx_suspend(struct phy_de + phy_modify(phydev, MII_BMCR, mask, 0); + } + +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_3D, ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, + AT803X_DEBUG_GATE_CLK_IN1000, 0); + + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, diff --git a/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch b/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch new file mode 100644 index 0000000000..c8d424de38 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch @@ -0,0 +1,80 @@ +From d8b6f5bae6d3b648a67b6958cb98e4e97256d652 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:06 +0200 +Subject: dsa: qca8k: add mac_power_sel support + +Add missing mac power sel support needed for ipq8064/5 SoC that require +1.8v for the internal regulator port instead of the default 1.5v. +If other device needs this, consider adding a dedicated binding to +support this. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 31 +++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 5 +++++ + 2 files changed, 36 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -951,6 +951,33 @@ qca8k_setup_of_rgmii_delay(struct qca8k_ + } + + static int ++qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv) ++{ ++ u32 mask = 0; ++ int ret = 0; ++ ++ /* SoC specific settings for ipq8064. ++ * If more device require this consider adding ++ * a dedicated binding. ++ */ ++ if (of_machine_is_compatible("qcom,ipq8064")) ++ mask |= QCA8K_MAC_PWR_RGMII0_1_8V; ++ ++ /* SoC specific settings for ipq8065 */ ++ if (of_machine_is_compatible("qcom,ipq8065")) ++ mask |= QCA8K_MAC_PWR_RGMII1_1_8V; ++ ++ if (mask) { ++ ret = qca8k_rmw(priv, QCA8K_REG_MAC_PWR_SEL, ++ QCA8K_MAC_PWR_RGMII0_1_8V | ++ QCA8K_MAC_PWR_RGMII1_1_8V, ++ mask); ++ } ++ ++ return ret; ++} ++ ++static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +@@ -979,6 +1006,10 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ ret = qca8k_setup_mac_pwr_sel(priv); ++ if (ret) ++ return ret; ++ + /* Enable CPU Port */ + ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -100,6 +100,11 @@ + #define QCA8K_SGMII_MODE_CTRL_PHY (1 << 22) + #define QCA8K_SGMII_MODE_CTRL_MAC (2 << 22) + ++/* MAC_PWR_SEL registers */ ++#define QCA8K_REG_MAC_PWR_SEL 0x0e4 ++#define QCA8K_MAC_PWR_RGMII1_1_8V BIT(18) ++#define QCA8K_MAC_PWR_RGMII0_1_8V BIT(19) ++ + /* EEE control registers */ + #define QCA8K_REG_EEE_CTRL 0x100 + #define QCA8K_REG_EEE_CTRL_LPI_EN(_i) ((_i + 1) * 2) diff --git a/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch b/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch new file mode 100644 index 0000000000..bd768ec27d --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch @@ -0,0 +1,30 @@ +From fdbf35df9c091db9c46e57e9938e3f7a4f603a7c Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:07 +0200 +Subject: dt-bindings: net: dsa: qca8k: Add SGMII clock phase properties + +Add names and descriptions of additional PORT0_PAD_CTRL properties. +qca,sgmii-(rx|tx)clk-falling-edge are for setting the respective clock +phase to failling edge. + +Co-developed-by: Matthew Hagan +Signed-off-by: Matthew Hagan +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/dsa/qca8k.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -37,6 +37,10 @@ A CPU port node has the following option + managed entity. See + Documentation/devicetree/bindings/net/fixed-link.txt + for details. ++- qca,sgmii-rxclk-falling-edge: Set the receive clock phase to falling edge. ++ Mostly used in qca8327 with CPU port 0 set to ++ sgmii. ++- qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge. + + For QCA8K the 'fixed-link' sub-node supports only the following properties: + diff --git a/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch b/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch new file mode 100644 index 0000000000..e464452d82 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch @@ -0,0 +1,127 @@ +From 6c43809bf1bee76c434e365a26546a92a5fbec14 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:08 +0200 +Subject: net: dsa: qca8k: add support for sgmii falling edge + +Add support for this in the qca8k driver. Also add support for SGMII +rx/tx clock falling edge. This is only present for pad0, pad5 and +pad6 have these bit reserved from Documentation. Add a comment that this +is hardcoded to PAD0 as qca8327/28/34/37 have an unique sgmii line and +setting falling in port0 applies to both configuration with sgmii used +for port0 or port6. + +Co-developed-by: Matthew Hagan +Signed-off-by: Matthew Hagan +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 4 ++++ + 2 files changed, 67 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -978,6 +978,42 @@ qca8k_setup_mac_pwr_sel(struct qca8k_pri + } + + static int ++qca8k_parse_port_config(struct qca8k_priv *priv) ++{ ++ struct device_node *port_dn; ++ phy_interface_t mode; ++ struct dsa_port *dp; ++ int port, ret; ++ ++ /* We have 2 CPU port. Check them */ ++ for (port = 0; port < QCA8K_NUM_PORTS; port++) { ++ /* Skip every other port */ ++ if (port != 0 && port != 6) ++ continue; ++ ++ dp = dsa_to_port(priv->ds, port); ++ port_dn = dp->dn; ++ ++ if (!of_device_is_available(port_dn)) ++ continue; ++ ++ ret = of_get_phy_mode(port_dn, &mode); ++ if (ret) ++ continue; ++ ++ if (mode == PHY_INTERFACE_MODE_SGMII) { ++ if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge")) ++ priv->sgmii_tx_clk_falling_edge = true; ++ ++ if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge")) ++ priv->sgmii_rx_clk_falling_edge = true; ++ } ++ } ++ ++ return 0; ++} ++ ++static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +@@ -990,6 +1026,11 @@ qca8k_setup(struct dsa_switch *ds) + return -EINVAL; + } + ++ /* Parse CPU port config to be later used in phy_link mac_config */ ++ ret = qca8k_parse_port_config(priv); ++ if (ret) ++ return ret; ++ + mutex_init(&priv->reg_mutex); + + /* Start by setting up the register mapping */ +@@ -1274,6 +1315,28 @@ qca8k_phylink_mac_config(struct dsa_swit + } + + qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val); ++ ++ /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and ++ * falling edge is set writing in the PORT0 PAD reg ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8327 || ++ priv->switch_id == QCA8K_ID_QCA8337) ++ reg = QCA8K_REG_PORT0_PAD_CTRL; ++ ++ val = 0; ++ ++ /* SGMII Clock phase configuration */ ++ if (priv->sgmii_rx_clk_falling_edge) ++ val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE; ++ ++ if (priv->sgmii_tx_clk_falling_edge) ++ val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE; ++ ++ if (val) ++ ret = qca8k_rmw(priv, reg, ++ QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE | ++ QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, ++ val); + break; + default: + dev_err(ds->dev, "xMII mode %s not supported for port %d\n", +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -35,6 +35,8 @@ + #define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) + #define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) + #define QCA8K_REG_PORT0_PAD_CTRL 0x004 ++#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19) ++#define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18) + #define QCA8K_REG_PORT5_PAD_CTRL 0x008 + #define QCA8K_REG_PORT6_PAD_CTRL 0x00c + #define QCA8K_PORT_PAD_RGMII_EN BIT(26) +@@ -260,6 +262,8 @@ struct qca8k_priv { + u8 switch_revision; + u8 rgmii_tx_delay; + u8 rgmii_rx_delay; ++ bool sgmii_rx_clk_falling_edge; ++ bool sgmii_tx_clk_falling_edge; + bool legacy_phy_port_mapping; + struct regmap *regmap; + struct mii_bus *bus; diff --git a/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch b/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch new file mode 100644 index 0000000000..606ac0af3d --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch @@ -0,0 +1,29 @@ +From 731d613338ec6de482053ffa3f71be2325b0f8eb Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:09 +0200 +Subject: dt-bindings: net: dsa: qca8k: Document support for CPU port 6 + +The switch now support CPU port to be set 6 instead of be hardcoded to +0. Document support for it and describe logic selection. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/dsa/qca8k.txt | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -29,7 +29,11 @@ the mdio MASTER is used as communication + Don't use mixed external and internal mdio-bus configurations, as this is + not supported by the hardware. + +-The CPU port of this switch is always port 0. ++This switch support 2 CPU port. Normally and advised configuration is with ++CPU port set to port 0. It is also possible to set the CPU port to port 6 ++if the device requires it. The driver will configure the switch to the defined ++port. With both CPU port declared the first CPU port is selected as primary ++and the secondary CPU ignored. + + A CPU port node has the following optional node: + diff --git a/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch b/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch new file mode 100644 index 0000000000..320db8fa9f --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch @@ -0,0 +1,153 @@ +From 3fcf734aa482487df83cf8f18608438fcf59127f Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:10 +0200 +Subject: net: dsa: qca8k: add support for cpu port 6 + +Currently CPU port is always hardcoded to port 0. This switch have 2 CPU +ports. The original intention of this driver seems to be use the +mac06_exchange bit to swap MAC0 with MAC6 in the strange configuration +where device have connected only the CPU port 6. To skip the +introduction of a new binding, rework the driver to address the +secondary CPU port as primary and drop any reference of hardcoded port. +With configuration of mac06 exchange, just skip the definition of port0 +and define the CPU port as a secondary. The driver will autoconfigure +the switch to use that as the primary CPU port. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 51 ++++++++++++++++++++++++++++++++++--------------- + drivers/net/dsa/qca8k.h | 2 -- + 2 files changed, 36 insertions(+), 17 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -977,6 +977,22 @@ qca8k_setup_mac_pwr_sel(struct qca8k_pri + return ret; + } + ++static int qca8k_find_cpu_port(struct dsa_switch *ds) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ /* Find the connected cpu port. Valid port are 0 or 6 */ ++ if (dsa_is_cpu_port(ds, 0)) ++ return 0; ++ ++ dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6"); ++ ++ if (dsa_is_cpu_port(ds, 6)) ++ return 6; ++ ++ return -EINVAL; ++} ++ + static int + qca8k_parse_port_config(struct qca8k_priv *priv) + { +@@ -1017,13 +1033,13 @@ static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +- int ret, i; ++ int cpu_port, ret, i; + u32 mask; + +- /* Make sure that port 0 is the cpu port */ +- if (!dsa_is_cpu_port(ds, 0)) { +- dev_err(priv->dev, "port 0 is not the CPU port"); +- return -EINVAL; ++ cpu_port = qca8k_find_cpu_port(ds); ++ if (cpu_port < 0) { ++ dev_err(priv->dev, "No cpu port configured in both cpu port0 and port6"); ++ return cpu_port; + } + + /* Parse CPU port config to be later used in phy_link mac_config */ +@@ -1065,7 +1081,7 @@ qca8k_setup(struct dsa_switch *ds) + dev_warn(priv->dev, "mib init failed"); + + /* Enable QCA header mode on the cpu port */ +- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT), ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(cpu_port), + QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | + QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); + if (ret) { +@@ -1087,10 +1103,10 @@ qca8k_setup(struct dsa_switch *ds) + + /* Forward all unknown frames to CPU port for Linux processing */ + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | +- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | ++ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); + if (ret) + return ret; + +@@ -1098,7 +1114,7 @@ qca8k_setup(struct dsa_switch *ds) + for (i = 0; i < QCA8K_NUM_PORTS; i++) { + /* CPU port gets connected to all user ports of the switch */ + if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), + QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); + if (ret) + return ret; +@@ -1110,7 +1126,7 @@ qca8k_setup(struct dsa_switch *ds) + + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), + QCA8K_PORT_LOOKUP_MEMBER, +- BIT(QCA8K_CPU_PORT)); ++ BIT(cpu_port)); + if (ret) + return ret; + +@@ -1616,9 +1632,12 @@ static int + qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +- int port_mask = BIT(QCA8K_CPU_PORT); ++ int port_mask, cpu_port; + int i, ret; + ++ cpu_port = dsa_to_port(ds, port)->cpu_dp->index; ++ port_mask = BIT(cpu_port); ++ + for (i = 1; i < QCA8K_NUM_PORTS; i++) { + if (dsa_to_port(ds, i)->bridge_dev != br) + continue; +@@ -1645,7 +1664,9 @@ static void + qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +- int i; ++ int cpu_port, i; ++ ++ cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + + for (i = 1; i < QCA8K_NUM_PORTS; i++) { + if (dsa_to_port(ds, i)->bridge_dev != br) +@@ -1662,7 +1683,7 @@ qca8k_port_bridge_leave(struct dsa_switc + * this port + */ + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT)); ++ QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); + } + + static int +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -24,8 +24,6 @@ + + #define QCA8K_NUM_FDB_RECORDS 2048 + +-#define QCA8K_CPU_PORT 0 +- + #define QCA8K_PORT_VID_DEF 1 + + /* Global control registers */ diff --git a/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch b/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch new file mode 100644 index 0000000000..de201764f9 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch @@ -0,0 +1,295 @@ +From 5654ec78dd7e64b1e04777b24007344329e6a63b Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:11 +0200 +Subject: net: dsa: qca8k: rework rgmii delay logic and scan for cpu port 6 + +Future proof commit. This switch have 2 CPU ports and one valid +configuration is first CPU port set to sgmii and second CPU port set to +rgmii-id. The current implementation detects delay only for CPU port +zero set to rgmii and doesn't count any delay set in a secondary CPU +port. Drop the current delay scan function and move it to the sgmii +parser function to generalize and implicitly add support for secondary +CPU port set to rgmii-id. Introduce new logic where delay is enabled +also with internal delay binding declared and rgmii set as PHY mode. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 165 ++++++++++++++++++++++++------------------------ + drivers/net/dsa/qca8k.h | 10 ++- + 2 files changed, 89 insertions(+), 86 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -889,68 +889,6 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + } + + static int +-qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv) +-{ +- struct device_node *port_dn; +- phy_interface_t mode; +- struct dsa_port *dp; +- u32 val; +- +- /* CPU port is already checked */ +- dp = dsa_to_port(priv->ds, 0); +- +- port_dn = dp->dn; +- +- /* Check if port 0 is set to the correct type */ +- of_get_phy_mode(port_dn, &mode); +- if (mode != PHY_INTERFACE_MODE_RGMII_ID && +- mode != PHY_INTERFACE_MODE_RGMII_RXID && +- mode != PHY_INTERFACE_MODE_RGMII_TXID) { +- return 0; +- } +- +- switch (mode) { +- case PHY_INTERFACE_MODE_RGMII_ID: +- case PHY_INTERFACE_MODE_RGMII_RXID: +- if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val)) +- val = 2; +- else +- /* Switch regs accept value in ns, convert ps to ns */ +- val = val / 1000; +- +- if (val > QCA8K_MAX_DELAY) { +- dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); +- val = 3; +- } +- +- priv->rgmii_rx_delay = val; +- /* Stop here if we need to check only for rx delay */ +- if (mode != PHY_INTERFACE_MODE_RGMII_ID) +- break; +- +- fallthrough; +- case PHY_INTERFACE_MODE_RGMII_TXID: +- if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val)) +- val = 1; +- else +- /* Switch regs accept value in ns, convert ps to ns */ +- val = val / 1000; +- +- if (val > QCA8K_MAX_DELAY) { +- dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); +- val = 3; +- } +- +- priv->rgmii_tx_delay = val; +- break; +- default: +- return 0; +- } +- +- return 0; +-} +- +-static int + qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv) + { + u32 mask = 0; +@@ -996,19 +934,21 @@ static int qca8k_find_cpu_port(struct ds + static int + qca8k_parse_port_config(struct qca8k_priv *priv) + { ++ int port, cpu_port_index = 0, ret; + struct device_node *port_dn; + phy_interface_t mode; + struct dsa_port *dp; +- int port, ret; ++ u32 delay; + + /* We have 2 CPU port. Check them */ +- for (port = 0; port < QCA8K_NUM_PORTS; port++) { ++ for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) { + /* Skip every other port */ + if (port != 0 && port != 6) + continue; + + dp = dsa_to_port(priv->ds, port); + port_dn = dp->dn; ++ cpu_port_index++; + + if (!of_device_is_available(port_dn)) + continue; +@@ -1017,12 +957,54 @@ qca8k_parse_port_config(struct qca8k_pri + if (ret) + continue; + +- if (mode == PHY_INTERFACE_MODE_SGMII) { ++ switch (mode) { ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ delay = 0; ++ ++ if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay)) ++ /* Switch regs accept value in ns, convert ps to ns */ ++ delay = delay / 1000; ++ else if (mode == PHY_INTERFACE_MODE_RGMII_ID || ++ mode == PHY_INTERFACE_MODE_RGMII_TXID) ++ delay = 1; ++ ++ if (delay > QCA8K_MAX_DELAY) { ++ dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); ++ delay = 3; ++ } ++ ++ priv->rgmii_tx_delay[cpu_port_index] = delay; ++ ++ delay = 0; ++ ++ if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay)) ++ /* Switch regs accept value in ns, convert ps to ns */ ++ delay = delay / 1000; ++ else if (mode == PHY_INTERFACE_MODE_RGMII_ID || ++ mode == PHY_INTERFACE_MODE_RGMII_RXID) ++ delay = 2; ++ ++ if (delay > QCA8K_MAX_DELAY) { ++ dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); ++ delay = 3; ++ } ++ ++ priv->rgmii_rx_delay[cpu_port_index] = delay; ++ ++ break; ++ case PHY_INTERFACE_MODE_SGMII: + if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge")) + priv->sgmii_tx_clk_falling_edge = true; + + if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge")) + priv->sgmii_rx_clk_falling_edge = true; ++ ++ break; ++ default: ++ continue; + } + } + +@@ -1059,10 +1041,6 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- ret = qca8k_setup_of_rgmii_delay(priv); +- if (ret) +- return ret; +- + ret = qca8k_setup_mac_pwr_sel(priv); + if (ret) + return ret; +@@ -1229,8 +1207,8 @@ qca8k_phylink_mac_config(struct dsa_swit + const struct phylink_link_state *state) + { + struct qca8k_priv *priv = ds->priv; +- u32 reg, val; +- int ret; ++ int cpu_port_index, ret; ++ u32 reg, val, delay; + + switch (port) { + case 0: /* 1st CPU port */ +@@ -1242,6 +1220,7 @@ qca8k_phylink_mac_config(struct dsa_swit + return; + + reg = QCA8K_REG_PORT0_PAD_CTRL; ++ cpu_port_index = QCA8K_CPU_PORT0; + break; + case 1: + case 2: +@@ -1260,6 +1239,7 @@ qca8k_phylink_mac_config(struct dsa_swit + return; + + reg = QCA8K_REG_PORT6_PAD_CTRL; ++ cpu_port_index = QCA8K_CPU_PORT6; + break; + default: + dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); +@@ -1274,23 +1254,40 @@ qca8k_phylink_mac_config(struct dsa_swit + + switch (state->interface) { + case PHY_INTERFACE_MODE_RGMII: +- /* RGMII mode means no delay so don't enable the delay */ +- qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN); +- break; + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: +- /* RGMII_ID needs internal delay. This is enabled through +- * PORT5_PAD_CTRL for all ports, rather than individual port +- * registers ++ val = QCA8K_PORT_PAD_RGMII_EN; ++ ++ /* Delay can be declared in 3 different way. ++ * Mode to rgmii and internal-delay standard binding defined ++ * rgmii-id or rgmii-tx/rx phy mode set. ++ * The parse logic set a delay different than 0 only when one ++ * of the 3 different way is used. In all other case delay is ++ * not enabled. With ID or TX/RXID delay is enabled and set ++ * to the default and recommended value. ++ */ ++ if (priv->rgmii_tx_delay[cpu_port_index]) { ++ delay = priv->rgmii_tx_delay[cpu_port_index]; ++ ++ val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) | ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN; ++ } ++ ++ if (priv->rgmii_rx_delay[cpu_port_index]) { ++ delay = priv->rgmii_rx_delay[cpu_port_index]; ++ ++ val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN; ++ } ++ ++ /* Set RGMII delay based on the selected values */ ++ qca8k_write(priv, reg, val); ++ ++ /* QCA8337 requires to set rgmii rx delay for all ports. ++ * This is enabled through PORT5_PAD_CTRL for all ports, ++ * rather than individual port registers. + */ +- qca8k_write(priv, reg, +- QCA8K_PORT_PAD_RGMII_EN | +- QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) | +- QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) | +- QCA8K_PORT_PAD_RGMII_TX_DELAY_EN | +- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); +- /* QCA8337 requires to set rgmii rx delay */ + if (priv->switch_id == QCA8K_ID_QCA8337) + qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, + QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -13,6 +13,7 @@ + #include + + #define QCA8K_NUM_PORTS 7 ++#define QCA8K_NUM_CPU_PORTS 2 + #define QCA8K_MAX_MTU 9000 + + #define PHY_ID_QCA8327 0x004dd034 +@@ -255,13 +256,18 @@ struct qca8k_match_data { + u8 id; + }; + ++enum { ++ QCA8K_CPU_PORT0, ++ QCA8K_CPU_PORT6, ++}; ++ + struct qca8k_priv { + u8 switch_id; + u8 switch_revision; +- u8 rgmii_tx_delay; +- u8 rgmii_rx_delay; + bool sgmii_rx_clk_falling_edge; + bool sgmii_tx_clk_falling_edge; ++ u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ ++ u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ + bool legacy_phy_port_mapping; + struct regmap *regmap; + struct mii_bus *bus; diff --git a/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch b/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch new file mode 100644 index 0000000000..8abd264e79 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch @@ -0,0 +1,33 @@ +From 13ad5ccc093ff448b99ac7e138e91e78796adb48 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:12 +0200 +Subject: dt-bindings: net: dsa: qca8k: Document qca,sgmii-enable-pll + +Document qca,sgmii-enable-pll binding used in the CPU nodes to +enable SGMII PLL on MAC config. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/dsa/qca8k.txt | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -45,6 +45,16 @@ A CPU port node has the following option + Mostly used in qca8327 with CPU port 0 set to + sgmii. + - qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge. ++- qca,sgmii-enable-pll : For SGMII CPU port, explicitly enable PLL, TX and RX ++ chain along with Signal Detection. ++ This should NOT be enabled for qca8327. If enabled with ++ qca8327 the sgmii port won't correctly init and an err ++ is printed. ++ This can be required for qca8337 switch with revision 2. ++ A warning is displayed when used with revision greater ++ 2. ++ With CPU port set to sgmii and qca8337 it is advised ++ to set this unless a communication problem is observed. + + For QCA8K the 'fixed-link' sub-node supports only the following properties: + diff --git a/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch b/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch new file mode 100644 index 0000000000..2b5a84a1b0 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch @@ -0,0 +1,65 @@ +From bbc4799e8bb6c397e3b3fec13de68e179f5db9ff Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:13 +0200 +Subject: net: dsa: qca8k: add explicit SGMII PLL enable + +Support enabling PLL on the SGMII CPU port. Some device require this +special configuration or no traffic is transmitted and the switch +doesn't work at all. A dedicated binding is added to the CPU node +port to apply the correct reg on mac config. +Fail to correctly configure sgmii with qca8327 switch and warn if pll is +used on qca8337 with a revision greater than 1. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 19 +++++++++++++++++-- + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 18 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1002,6 +1002,18 @@ qca8k_parse_port_config(struct qca8k_pri + if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge")) + priv->sgmii_rx_clk_falling_edge = true; + ++ if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) { ++ priv->sgmii_enable_pll = true; ++ ++ if (priv->switch_id == QCA8K_ID_QCA8327) { ++ dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling"); ++ priv->sgmii_enable_pll = false; ++ } ++ ++ if (priv->switch_revision < 2) ++ dev_warn(priv->dev, "SGMII PLL should NOT be enabled for qca8337 with revision 2 or more."); ++ } ++ + break; + default: + continue; +@@ -1312,8 +1324,11 @@ qca8k_phylink_mac_config(struct dsa_swit + if (ret) + return; + +- val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | +- QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD; ++ val |= QCA8K_SGMII_EN_SD; ++ ++ if (priv->sgmii_enable_pll) ++ val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | ++ QCA8K_SGMII_EN_TX; + + if (dsa_is_cpu_port(ds, port)) { + /* CPU port, we're talking to the CPU MAC, be a PHY */ +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -266,6 +266,7 @@ struct qca8k_priv { + u8 switch_revision; + bool sgmii_rx_clk_falling_edge; + bool sgmii_tx_clk_falling_edge; ++ bool sgmii_enable_pll; + u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ + u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ + bool legacy_phy_port_mapping; diff --git a/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch b/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch new file mode 100644 index 0000000000..38dc954e8c --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch @@ -0,0 +1,37 @@ +From 924087c5c3d41553700b0eb83ca2a53b91643dca Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:14 +0200 +Subject: dt-bindings: net: dsa: qca8k: Document qca,led-open-drain binding + +Document new binding qca,ignore-power-on-sel used to ignore +power on strapping and use sw regs instead. +Document qca,led-open.drain to set led to open drain mode, the +qca,ignore-power-on-sel is mandatory with this enabled or an error will +be reported. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/dsa/qca8k.txt | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -13,6 +13,17 @@ Required properties: + Optional properties: + + - reset-gpios: GPIO to be used to reset the whole device ++- qca,ignore-power-on-sel: Ignore power on pin strapping to configure led open ++ drain or eeprom presence. This is needed for broken ++ devices that have wrong configuration or when the oem ++ decided to not use pin strapping and fallback to sw ++ regs. ++- qca,led-open-drain: Set leds to open-drain mode. This requires the ++ qca,ignore-power-on-sel to be set or the driver will fail ++ to probe. This is needed if the oem doesn't use pin ++ strapping to set this mode and prefers to set it using sw ++ regs. The pin strapping related to led open drain mode is ++ the pin B68 for QCA832x and B49 for QCA833x + + Subnodes: + diff --git a/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch b/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch new file mode 100644 index 0000000000..aa5d92a4fd --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch @@ -0,0 +1,92 @@ +From 362bb238d8bf1470424214a8a5968d9c6cce68fa Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:15 +0200 +Subject: net: dsa: qca8k: add support for pws config reg + +Some qca8327 switch require to force the ignore of power on sel +strapping. Some switch require to set the led open drain mode in regs +instead of using strapping. While most of the device implements this +using the correct way using pin strapping, there are still some broken +device that require to be set using sw regs. +Introduce a new binding and support these special configuration. +As led open drain require to ignore pin strapping to work, the probe +fails with EINVAL error with incorrect configuration. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 39 +++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 6 ++++++ + 2 files changed, 45 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -932,6 +932,41 @@ static int qca8k_find_cpu_port(struct ds + } + + static int ++qca8k_setup_of_pws_reg(struct qca8k_priv *priv) ++{ ++ struct device_node *node = priv->dev->of_node; ++ u32 val = 0; ++ int ret; ++ ++ /* QCA8327 require to set to the correct mode. ++ * His bigger brother QCA8328 have the 172 pin layout. ++ * Should be applied by default but we set this just to make sure. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8327) { ++ ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN, ++ QCA8327_PWS_PACKAGE148_EN); ++ if (ret) ++ return ret; ++ } ++ ++ if (of_property_read_bool(node, "qca,ignore-power-on-sel")) ++ val |= QCA8K_PWS_POWER_ON_SEL; ++ ++ if (of_property_read_bool(node, "qca,led-open-drain")) { ++ if (!(val & QCA8K_PWS_POWER_ON_SEL)) { ++ dev_err(priv->dev, "qca,led-open-drain require qca,ignore-power-on-sel to be set."); ++ return -EINVAL; ++ } ++ ++ val |= QCA8K_PWS_LED_OPEN_EN_CSR; ++ } ++ ++ return qca8k_rmw(priv, QCA8K_REG_PWS, ++ QCA8K_PWS_LED_OPEN_EN_CSR | QCA8K_PWS_POWER_ON_SEL, ++ val); ++} ++ ++static int + qca8k_parse_port_config(struct qca8k_priv *priv) + { + int port, cpu_port_index = 0, ret; +@@ -1053,6 +1088,10 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ ret = qca8k_setup_of_pws_reg(priv); ++ if (ret) ++ return ret; ++ + ret = qca8k_setup_mac_pwr_sel(priv); + if (ret) + return ret; +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -46,6 +46,12 @@ + #define QCA8K_MAX_DELAY 3 + #define QCA8K_PORT_PAD_SGMII_EN BIT(7) + #define QCA8K_REG_PWS 0x010 ++#define QCA8K_PWS_POWER_ON_SEL BIT(31) ++/* This reg is only valid for QCA832x and toggle the package ++ * type from 176 pin (by default) to 148 pin used on QCA8327 ++ */ ++#define QCA8327_PWS_PACKAGE148_EN BIT(30) ++#define QCA8K_PWS_LED_OPEN_EN_CSR BIT(24) + #define QCA8K_PWS_SERDES_AEN_DIS BIT(7) + #define QCA8K_REG_MODULE_EN 0x030 + #define QCA8K_MODULE_EN_MIB BIT(0) diff --git a/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch b/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch new file mode 100644 index 0000000000..1bfb00c5b2 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch @@ -0,0 +1,32 @@ +From ed7988d77fbfb79366b68f9e7fa60a6080da23d4 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:16 +0200 +Subject: dt-bindings: net: dsa: qca8k: document support for qca8328 + +QCA8328 is the bigger brother of qca8327. Document the new compatible +binding and add some information to understand the various switch +compatible. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/dsa/qca8k.txt | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt +@@ -3,9 +3,10 @@ + Required properties: + + - compatible: should be one of: +- "qca,qca8327" +- "qca,qca8334" +- "qca,qca8337" ++ "qca,qca8328": referenced as AR8328(N)-AK1(A/B) QFN 176 pin package ++ "qca,qca8327": referenced as AR8327(N)-AL1A DR-QFN 148 pin package ++ "qca,qca8334": referenced as QCA8334-AL3C QFN 88 pin package ++ "qca,qca8337": referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package + + - #size-cells: must be 0 + - #address-cells: must be 1 diff --git a/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch b/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch new file mode 100644 index 0000000000..6e118f5a14 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch @@ -0,0 +1,78 @@ +From f477d1c8bdbef4f400718238e350f16f521d2a3e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:17 +0200 +Subject: net: dsa: qca8k: add support for QCA8328 + +QCA8328 switch is the bigger brother of the qca8327. Same regs different +chip. Change the function to set the correct pin layout and introduce a +new match_data to differentiate the 2 switch as they have the same ID +and their internal PHY have the same ID. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 19 ++++++++++++++++--- + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 17 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -935,6 +935,7 @@ static int + qca8k_setup_of_pws_reg(struct qca8k_priv *priv) + { + struct device_node *node = priv->dev->of_node; ++ const struct qca8k_match_data *data; + u32 val = 0; + int ret; + +@@ -943,8 +944,14 @@ qca8k_setup_of_pws_reg(struct qca8k_priv + * Should be applied by default but we set this just to make sure. + */ + if (priv->switch_id == QCA8K_ID_QCA8327) { ++ data = of_device_get_match_data(priv->dev); ++ ++ /* Set the correct package of 148 pin for QCA8327 */ ++ if (data->reduced_package) ++ val |= QCA8327_PWS_PACKAGE148_EN; ++ + ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN, +- QCA8327_PWS_PACKAGE148_EN); ++ val); + if (ret) + return ret; + } +@@ -2098,7 +2105,12 @@ static int qca8k_resume(struct device *d + static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, + qca8k_suspend, qca8k_resume); + +-static const struct qca8k_match_data qca832x = { ++static const struct qca8k_match_data qca8327 = { ++ .id = QCA8K_ID_QCA8327, ++ .reduced_package = true, ++}; ++ ++static const struct qca8k_match_data qca8328 = { + .id = QCA8K_ID_QCA8327, + }; + +@@ -2107,7 +2119,8 @@ static const struct qca8k_match_data qca + }; + + static const struct of_device_id qca8k_of_match[] = { +- { .compatible = "qca,qca8327", .data = &qca832x }, ++ { .compatible = "qca,qca8327", .data = &qca8327 }, ++ { .compatible = "qca,qca8328", .data = &qca8328 }, + { .compatible = "qca,qca8334", .data = &qca833x }, + { .compatible = "qca,qca8337", .data = &qca833x }, + { /* sentinel */ }, +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -260,6 +260,7 @@ struct ar8xxx_port_status { + + struct qca8k_match_data { + u8 id; ++ bool reduced_package; + }; + + enum { diff --git a/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch b/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch new file mode 100644 index 0000000000..27f94dca02 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch @@ -0,0 +1,159 @@ +From cef08115846e581f80ff99abf7bf218da1840616 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:18 +0200 +Subject: net: dsa: qca8k: set internal delay also for sgmii + +QCA original code report port instability and sa that SGMII also require +to set internal delay. Generalize the rgmii delay function and apply the +advised value if they are not defined in DT. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 88 +++++++++++++++++++++++++++++++++---------------- + drivers/net/dsa/qca8k.h | 2 ++ + 2 files changed, 62 insertions(+), 28 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1004,6 +1004,7 @@ qca8k_parse_port_config(struct qca8k_pri + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_SGMII: + delay = 0; + + if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay)) +@@ -1036,8 +1037,13 @@ qca8k_parse_port_config(struct qca8k_pri + + priv->rgmii_rx_delay[cpu_port_index] = delay; + +- break; +- case PHY_INTERFACE_MODE_SGMII: ++ /* Skip sgmii parsing for rgmii* mode */ ++ if (mode == PHY_INTERFACE_MODE_RGMII || ++ mode == PHY_INTERFACE_MODE_RGMII_ID || ++ mode == PHY_INTERFACE_MODE_RGMII_TXID || ++ mode == PHY_INTERFACE_MODE_RGMII_RXID) ++ break; ++ + if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge")) + priv->sgmii_tx_clk_falling_edge = true; + +@@ -1261,12 +1267,53 @@ qca8k_setup(struct dsa_switch *ds) + } + + static void ++qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_index, ++ u32 reg) ++{ ++ u32 delay, val = 0; ++ int ret; ++ ++ /* Delay can be declared in 3 different way. ++ * Mode to rgmii and internal-delay standard binding defined ++ * rgmii-id or rgmii-tx/rx phy mode set. ++ * The parse logic set a delay different than 0 only when one ++ * of the 3 different way is used. In all other case delay is ++ * not enabled. With ID or TX/RXID delay is enabled and set ++ * to the default and recommended value. ++ */ ++ if (priv->rgmii_tx_delay[cpu_port_index]) { ++ delay = priv->rgmii_tx_delay[cpu_port_index]; ++ ++ val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) | ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN; ++ } ++ ++ if (priv->rgmii_rx_delay[cpu_port_index]) { ++ delay = priv->rgmii_rx_delay[cpu_port_index]; ++ ++ val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN; ++ } ++ ++ /* Set RGMII delay based on the selected values */ ++ ret = qca8k_rmw(priv, reg, ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK | ++ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN | ++ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN, ++ val); ++ if (ret) ++ dev_err(priv->dev, "Failed to set internal delay for CPU port%d", ++ cpu_port_index == QCA8K_CPU_PORT0 ? 0 : 6); ++} ++ ++static void + qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) + { + struct qca8k_priv *priv = ds->priv; + int cpu_port_index, ret; +- u32 reg, val, delay; ++ u32 reg, val; + + switch (port) { + case 0: /* 1st CPU port */ +@@ -1315,32 +1362,10 @@ qca8k_phylink_mac_config(struct dsa_swit + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: +- val = QCA8K_PORT_PAD_RGMII_EN; +- +- /* Delay can be declared in 3 different way. +- * Mode to rgmii and internal-delay standard binding defined +- * rgmii-id or rgmii-tx/rx phy mode set. +- * The parse logic set a delay different than 0 only when one +- * of the 3 different way is used. In all other case delay is +- * not enabled. With ID or TX/RXID delay is enabled and set +- * to the default and recommended value. +- */ +- if (priv->rgmii_tx_delay[cpu_port_index]) { +- delay = priv->rgmii_tx_delay[cpu_port_index]; +- +- val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) | +- QCA8K_PORT_PAD_RGMII_TX_DELAY_EN; +- } +- +- if (priv->rgmii_rx_delay[cpu_port_index]) { +- delay = priv->rgmii_rx_delay[cpu_port_index]; +- +- val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) | +- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN; +- } ++ qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN); + +- /* Set RGMII delay based on the selected values */ +- qca8k_write(priv, reg, val); ++ /* Configure rgmii delay */ ++ qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); + + /* QCA8337 requires to set rgmii rx delay for all ports. + * This is enabled through PORT5_PAD_CTRL for all ports, +@@ -1411,6 +1436,13 @@ qca8k_phylink_mac_config(struct dsa_swit + QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE | + QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, + val); ++ ++ /* From original code is reported port instability as SGMII also ++ * require delay set. Apply advised values here or take them from DT. ++ */ ++ if (state->interface == PHY_INTERFACE_MODE_SGMII) ++ qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); ++ + break; + default: + dev_err(ds->dev, "xMII mode %s not supported for port %d\n", +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -39,7 +39,9 @@ + #define QCA8K_REG_PORT5_PAD_CTRL 0x008 + #define QCA8K_REG_PORT6_PAD_CTRL 0x00c + #define QCA8K_PORT_PAD_RGMII_EN BIT(26) ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK GENMASK(23, 22) + #define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22) ++#define QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK GENMASK(21, 20) + #define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20) + #define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25) + #define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) diff --git a/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch b/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch new file mode 100644 index 0000000000..b991798c87 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch @@ -0,0 +1,124 @@ +From fd0bb28c547f7c8affb1691128cece38f5b626a1 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:19 +0200 +Subject: net: dsa: qca8k: move port config to dedicated struct + +Move ports related config to dedicated struct to keep things organized. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 26 +++++++++++++------------- + drivers/net/dsa/qca8k.h | 10 +++++++--- + 2 files changed, 20 insertions(+), 16 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1019,7 +1019,7 @@ qca8k_parse_port_config(struct qca8k_pri + delay = 3; + } + +- priv->rgmii_tx_delay[cpu_port_index] = delay; ++ priv->ports_config.rgmii_tx_delay[cpu_port_index] = delay; + + delay = 0; + +@@ -1035,7 +1035,7 @@ qca8k_parse_port_config(struct qca8k_pri + delay = 3; + } + +- priv->rgmii_rx_delay[cpu_port_index] = delay; ++ priv->ports_config.rgmii_rx_delay[cpu_port_index] = delay; + + /* Skip sgmii parsing for rgmii* mode */ + if (mode == PHY_INTERFACE_MODE_RGMII || +@@ -1045,17 +1045,17 @@ qca8k_parse_port_config(struct qca8k_pri + break; + + if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge")) +- priv->sgmii_tx_clk_falling_edge = true; ++ priv->ports_config.sgmii_tx_clk_falling_edge = true; + + if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge")) +- priv->sgmii_rx_clk_falling_edge = true; ++ priv->ports_config.sgmii_rx_clk_falling_edge = true; + + if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) { +- priv->sgmii_enable_pll = true; ++ priv->ports_config.sgmii_enable_pll = true; + + if (priv->switch_id == QCA8K_ID_QCA8327) { + dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling"); +- priv->sgmii_enable_pll = false; ++ priv->ports_config.sgmii_enable_pll = false; + } + + if (priv->switch_revision < 2) +@@ -1281,15 +1281,15 @@ qca8k_mac_config_setup_internal_delay(st + * not enabled. With ID or TX/RXID delay is enabled and set + * to the default and recommended value. + */ +- if (priv->rgmii_tx_delay[cpu_port_index]) { +- delay = priv->rgmii_tx_delay[cpu_port_index]; ++ if (priv->ports_config.rgmii_tx_delay[cpu_port_index]) { ++ delay = priv->ports_config.rgmii_tx_delay[cpu_port_index]; + + val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) | + QCA8K_PORT_PAD_RGMII_TX_DELAY_EN; + } + +- if (priv->rgmii_rx_delay[cpu_port_index]) { +- delay = priv->rgmii_rx_delay[cpu_port_index]; ++ if (priv->ports_config.rgmii_rx_delay[cpu_port_index]) { ++ delay = priv->ports_config.rgmii_rx_delay[cpu_port_index]; + + val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) | + QCA8K_PORT_PAD_RGMII_RX_DELAY_EN; +@@ -1397,7 +1397,7 @@ qca8k_phylink_mac_config(struct dsa_swit + + val |= QCA8K_SGMII_EN_SD; + +- if (priv->sgmii_enable_pll) ++ if (priv->ports_config.sgmii_enable_pll) + val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | + QCA8K_SGMII_EN_TX; + +@@ -1425,10 +1425,10 @@ qca8k_phylink_mac_config(struct dsa_swit + val = 0; + + /* SGMII Clock phase configuration */ +- if (priv->sgmii_rx_clk_falling_edge) ++ if (priv->ports_config.sgmii_rx_clk_falling_edge) + val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE; + +- if (priv->sgmii_tx_clk_falling_edge) ++ if (priv->ports_config.sgmii_tx_clk_falling_edge) + val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE; + + if (val) +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -270,15 +270,19 @@ enum { + QCA8K_CPU_PORT6, + }; + +-struct qca8k_priv { +- u8 switch_id; +- u8 switch_revision; ++struct qca8k_ports_config { + bool sgmii_rx_clk_falling_edge; + bool sgmii_tx_clk_falling_edge; + bool sgmii_enable_pll; + u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ + u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ ++}; ++ ++struct qca8k_priv { ++ u8 switch_id; ++ u8 switch_revision; + bool legacy_phy_port_mapping; ++ struct qca8k_ports_config ports_config; + struct regmap *regmap; + struct mii_bus *bus; + struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch b/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch new file mode 100644 index 0000000000..f7cb514176 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch @@ -0,0 +1,26 @@ +From e52073a8e3086046a098b8a7cbeb282ff0cdb424 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Thu, 14 Oct 2021 00:39:20 +0200 +Subject: dt-bindings: net: ipq8064-mdio: fix warning with new qca8k switch + +Fix warning now that we have qca8k switch Documentation using yaml. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml ++++ b/Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml +@@ -51,6 +51,9 @@ examples: + switch@10 { + compatible = "qca,qca8337"; + reg = <0x10>; +- /* ... */ ++ ++ ports { ++ /* ... */ ++ }; + }; + }; diff --git a/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch b/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch new file mode 100644 index 0000000000..b9bce97dd3 --- /dev/null +++ b/target/linux/generic/backport-5.15/747-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch @@ -0,0 +1,631 @@ +From d291fbb8245d5ba04979fed85575860a5cea7196 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Thu, 14 Oct 2021 00:39:21 +0200 +Subject: dt-bindings: net: dsa: qca8k: convert to YAML schema + +Convert the qca8k bindings to YAML format. + +Signed-off-by: Matthew Hagan +Co-developed-by: Ansuel Smith +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + .../devicetree/bindings/net/dsa/qca8k.txt | 245 -------------- + .../devicetree/bindings/net/dsa/qca8k.yaml | 362 +++++++++++++++++++++ + 2 files changed, 362 insertions(+), 245 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt + create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.yaml + +--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt ++++ /dev/null +@@ -1,245 +0,0 @@ +-* Qualcomm Atheros QCA8xxx switch family +- +-Required properties: +- +-- compatible: should be one of: +- "qca,qca8328": referenced as AR8328(N)-AK1(A/B) QFN 176 pin package +- "qca,qca8327": referenced as AR8327(N)-AL1A DR-QFN 148 pin package +- "qca,qca8334": referenced as QCA8334-AL3C QFN 88 pin package +- "qca,qca8337": referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package +- +-- #size-cells: must be 0 +-- #address-cells: must be 1 +- +-Optional properties: +- +-- reset-gpios: GPIO to be used to reset the whole device +-- qca,ignore-power-on-sel: Ignore power on pin strapping to configure led open +- drain or eeprom presence. This is needed for broken +- devices that have wrong configuration or when the oem +- decided to not use pin strapping and fallback to sw +- regs. +-- qca,led-open-drain: Set leds to open-drain mode. This requires the +- qca,ignore-power-on-sel to be set or the driver will fail +- to probe. This is needed if the oem doesn't use pin +- strapping to set this mode and prefers to set it using sw +- regs. The pin strapping related to led open drain mode is +- the pin B68 for QCA832x and B49 for QCA833x +- +-Subnodes: +- +-The integrated switch subnode should be specified according to the binding +-described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external +-mdio-bus each subnode describing a port needs to have a valid phandle +-referencing the internal PHY it is connected to. This is because there's no +-N:N mapping of port and PHY id. +-To declare the internal mdio-bus configuration, declare a mdio node in the +-switch node and declare the phandle for the port referencing the internal +-PHY is connected to. In this config a internal mdio-bus is registered and +-the mdio MASTER is used as communication. +- +-Don't use mixed external and internal mdio-bus configurations, as this is +-not supported by the hardware. +- +-This switch support 2 CPU port. Normally and advised configuration is with +-CPU port set to port 0. It is also possible to set the CPU port to port 6 +-if the device requires it. The driver will configure the switch to the defined +-port. With both CPU port declared the first CPU port is selected as primary +-and the secondary CPU ignored. +- +-A CPU port node has the following optional node: +- +-- fixed-link : Fixed-link subnode describing a link to a non-MDIO +- managed entity. See +- Documentation/devicetree/bindings/net/fixed-link.txt +- for details. +-- qca,sgmii-rxclk-falling-edge: Set the receive clock phase to falling edge. +- Mostly used in qca8327 with CPU port 0 set to +- sgmii. +-- qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge. +-- qca,sgmii-enable-pll : For SGMII CPU port, explicitly enable PLL, TX and RX +- chain along with Signal Detection. +- This should NOT be enabled for qca8327. If enabled with +- qca8327 the sgmii port won't correctly init and an err +- is printed. +- This can be required for qca8337 switch with revision 2. +- A warning is displayed when used with revision greater +- 2. +- With CPU port set to sgmii and qca8337 it is advised +- to set this unless a communication problem is observed. +- +-For QCA8K the 'fixed-link' sub-node supports only the following properties: +- +-- 'speed' (integer, mandatory), to indicate the link speed. Accepted +- values are 10, 100 and 1000 +-- 'full-duplex' (boolean, optional), to indicate that full duplex is +- used. When absent, half duplex is assumed. +- +-Examples: +- +-for the external mdio-bus configuration: +- +- &mdio0 { +- phy_port1: phy@0 { +- reg = <0>; +- }; +- +- phy_port2: phy@1 { +- reg = <1>; +- }; +- +- phy_port3: phy@2 { +- reg = <2>; +- }; +- +- phy_port4: phy@3 { +- reg = <3>; +- }; +- +- phy_port5: phy@4 { +- reg = <4>; +- }; +- +- switch@10 { +- compatible = "qca,qca8337"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>; +- reg = <0x10>; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- port@0 { +- reg = <0>; +- label = "cpu"; +- ethernet = <&gmac1>; +- phy-mode = "rgmii"; +- fixed-link { +- speed = 1000; +- full-duplex; +- }; +- }; +- +- port@1 { +- reg = <1>; +- label = "lan1"; +- phy-handle = <&phy_port1>; +- }; +- +- port@2 { +- reg = <2>; +- label = "lan2"; +- phy-handle = <&phy_port2>; +- }; +- +- port@3 { +- reg = <3>; +- label = "lan3"; +- phy-handle = <&phy_port3>; +- }; +- +- port@4 { +- reg = <4>; +- label = "lan4"; +- phy-handle = <&phy_port4>; +- }; +- +- port@5 { +- reg = <5>; +- label = "wan"; +- phy-handle = <&phy_port5>; +- }; +- }; +- }; +- }; +- +-for the internal master mdio-bus configuration: +- +- &mdio0 { +- switch@10 { +- compatible = "qca,qca8337"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>; +- reg = <0x10>; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- reg = <0>; +- label = "cpu"; +- ethernet = <&gmac1>; +- phy-mode = "rgmii"; +- fixed-link { +- speed = 1000; +- full-duplex; +- }; +- }; +- +- port@1 { +- reg = <1>; +- label = "lan1"; +- phy-mode = "internal"; +- phy-handle = <&phy_port1>; +- }; +- +- port@2 { +- reg = <2>; +- label = "lan2"; +- phy-mode = "internal"; +- phy-handle = <&phy_port2>; +- }; +- +- port@3 { +- reg = <3>; +- label = "lan3"; +- phy-mode = "internal"; +- phy-handle = <&phy_port3>; +- }; +- +- port@4 { +- reg = <4>; +- label = "lan4"; +- phy-mode = "internal"; +- phy-handle = <&phy_port4>; +- }; +- +- port@5 { +- reg = <5>; +- label = "wan"; +- phy-mode = "internal"; +- phy-handle = <&phy_port5>; +- }; +- }; +- +- mdio { +- #address-cells = <1>; +- #size-cells = <0>; +- +- phy_port1: phy@0 { +- reg = <0>; +- }; +- +- phy_port2: phy@1 { +- reg = <1>; +- }; +- +- phy_port3: phy@2 { +- reg = <2>; +- }; +- +- phy_port4: phy@3 { +- reg = <3>; +- }; +- +- phy_port5: phy@4 { +- reg = <4>; +- }; +- }; +- }; +- }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.yaml +@@ -0,0 +1,362 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/dsa/qca8k.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Qualcomm Atheros QCA83xx switch family ++ ++maintainers: ++ - John Crispin ++ ++description: ++ If the QCA8K switch is connect to an SoC's external mdio-bus, each subnode ++ describing a port needs to have a valid phandle referencing the internal PHY ++ it is connected to. This is because there is no N:N mapping of port and PHY ++ ID. To declare the internal mdio-bus configuration, declare an MDIO node in ++ the switch node and declare the phandle for the port, referencing the internal ++ PHY it is connected to. In this config, an internal mdio-bus is registered and ++ the MDIO master is used for communication. Mixed external and internal ++ mdio-bus configurations are not supported by the hardware. ++ ++properties: ++ compatible: ++ oneOf: ++ - enum: ++ - qca,qca8327 ++ - qca,qca8328 ++ - qca,qca8334 ++ - qca,qca8337 ++ description: | ++ qca,qca8328: referenced as AR8328(N)-AK1(A/B) QFN 176 pin package ++ qca,qca8327: referenced as AR8327(N)-AL1A DR-QFN 148 pin package ++ qca,qca8334: referenced as QCA8334-AL3C QFN 88 pin package ++ qca,qca8337: referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package ++ ++ reg: ++ maxItems: 1 ++ ++ reset-gpios: ++ description: ++ GPIO to be used to reset the whole device ++ maxItems: 1 ++ ++ qca,ignore-power-on-sel: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ Ignore power-on pin strapping to configure LED open-drain or EEPROM ++ presence. This is needed for devices with incorrect configuration or when ++ the OEM has decided not to use pin strapping and falls back to SW regs. ++ ++ qca,led-open-drain: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ Set LEDs to open-drain mode. This requires the qca,ignore-power-on-sel to ++ be set, otherwise the driver will fail at probe. This is required if the ++ OEM does not use pin strapping to set this mode and prefers to set it ++ using SW regs. The pin strappings related to LED open-drain mode are ++ B68 on the QCA832x and B49 on the QCA833x. ++ ++ mdio: ++ type: object ++ description: Qca8k switch have an internal mdio to access switch port. ++ If this is not present, the legacy mapping is used and the ++ internal mdio access is used. ++ With the legacy mapping the reg corresponding to the internal ++ mdio is the switch reg with an offset of -1. ++ ++ properties: ++ '#address-cells': ++ const: 1 ++ '#size-cells': ++ const: 0 ++ ++ patternProperties: ++ "^(ethernet-)?phy@[0-4]$": ++ type: object ++ ++ allOf: ++ - $ref: "http://devicetree.org/schemas/net/mdio.yaml#" ++ ++ properties: ++ reg: ++ maxItems: 1 ++ ++ required: ++ - reg ++ ++patternProperties: ++ "^(ethernet-)?ports$": ++ type: object ++ properties: ++ '#address-cells': ++ const: 1 ++ '#size-cells': ++ const: 0 ++ ++ patternProperties: ++ "^(ethernet-)?port@[0-6]$": ++ type: object ++ description: Ethernet switch ports ++ ++ properties: ++ reg: ++ description: Port number ++ ++ label: ++ description: ++ Describes the label associated with this port, which will become ++ the netdev name ++ $ref: /schemas/types.yaml#/definitions/string ++ ++ link: ++ description: ++ Should be a list of phandles to other switch's DSA port. This ++ port is used as the outgoing port towards the phandle ports. The ++ full routing information must be given, not just the one hop ++ routes to neighbouring switches ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ ++ ethernet: ++ description: ++ Should be a phandle to a valid Ethernet device node. This host ++ device is what the switch port is connected to ++ $ref: /schemas/types.yaml#/definitions/phandle ++ ++ phy-handle: true ++ ++ phy-mode: true ++ ++ fixed-link: true ++ ++ mac-address: true ++ ++ sfp: true ++ ++ qca,sgmii-rxclk-falling-edge: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ Set the receive clock phase to falling edge. Mostly commonly used on ++ the QCA8327 with CPU port 0 set to SGMII. ++ ++ qca,sgmii-txclk-falling-edge: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ Set the transmit clock phase to falling edge. ++ ++ qca,sgmii-enable-pll: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ For SGMII CPU port, explicitly enable PLL, TX and RX chain along with ++ Signal Detection. On the QCA8327 this should not be enabled, otherwise ++ the SGMII port will not initialize. When used on the QCA8337, revision 3 ++ or greater, a warning will be displayed. When the CPU port is set to ++ SGMII on the QCA8337, it is advised to set this unless a communication ++ issue is observed. ++ ++ required: ++ - reg ++ ++ additionalProperties: false ++ ++oneOf: ++ - required: ++ - ports ++ - required: ++ - ethernet-ports ++ ++required: ++ - compatible ++ - reg ++ ++additionalProperties: true ++ ++examples: ++ - | ++ #include ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ external_phy_port1: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ ++ external_phy_port2: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ ++ external_phy_port3: ethernet-phy@2 { ++ reg = <2>; ++ }; ++ ++ external_phy_port4: ethernet-phy@3 { ++ reg = <3>; ++ }; ++ ++ external_phy_port5: ethernet-phy@4 { ++ reg = <4>; ++ }; ++ ++ switch@10 { ++ compatible = "qca,qca8337"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>; ++ reg = <0x10>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "cpu"; ++ ethernet = <&gmac1>; ++ phy-mode = "rgmii"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan1"; ++ phy-handle = <&external_phy_port1>; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan2"; ++ phy-handle = <&external_phy_port2>; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan3"; ++ phy-handle = <&external_phy_port3>; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "lan4"; ++ phy-handle = <&external_phy_port4>; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ label = "wan"; ++ phy-handle = <&external_phy_port5>; ++ }; ++ }; ++ }; ++ }; ++ - | ++ #include ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch@10 { ++ compatible = "qca,qca8337"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>; ++ reg = <0x10>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "cpu"; ++ ethernet = <&gmac1>; ++ phy-mode = "rgmii"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan1"; ++ phy-mode = "internal"; ++ phy-handle = <&internal_phy_port1>; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan2"; ++ phy-mode = "internal"; ++ phy-handle = <&internal_phy_port2>; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan3"; ++ phy-mode = "internal"; ++ phy-handle = <&internal_phy_port3>; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "lan4"; ++ phy-mode = "internal"; ++ phy-handle = <&internal_phy_port4>; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ label = "wan"; ++ phy-mode = "internal"; ++ phy-handle = <&internal_phy_port5>; ++ }; ++ ++ port@6 { ++ reg = <0>; ++ label = "cpu"; ++ ethernet = <&gmac1>; ++ phy-mode = "sgmii"; ++ ++ qca,sgmii-rxclk-falling-edge; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ internal_phy_port1: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ ++ internal_phy_port2: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ ++ internal_phy_port3: ethernet-phy@2 { ++ reg = <2>; ++ }; ++ ++ internal_phy_port4: ethernet-phy@3 { ++ reg = <3>; ++ }; ++ ++ internal_phy_port5: ethernet-phy@4 { ++ reg = <4>; ++ }; ++ }; ++ }; ++ }; diff --git a/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch b/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch new file mode 100644 index 0000000000..a510cfdc18 --- /dev/null +++ b/target/linux/generic/backport-5.15/748-v5.16-net-dsa-qca8k-fix-delay-applied-to-wrong-cpu-in-parse-p.patch @@ -0,0 +1,28 @@ +From 06dd34a628ae5b6a839b757e746de165d6789ca8 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Sun, 17 Oct 2021 16:56:46 +0200 +Subject: net: dsa: qca8k: fix delay applied to wrong cpu in parse_port_config + +Fix delay settings applied to wrong cpu in parse_port_config. The delay +values is set to the wrong index as the cpu_port_index is incremented +too early. Start the cpu_port_index to -1 so the correct value is +applied to address also the case with invalid phy mode and not available +port. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -976,7 +976,7 @@ qca8k_setup_of_pws_reg(struct qca8k_priv + static int + qca8k_parse_port_config(struct qca8k_priv *priv) + { +- int port, cpu_port_index = 0, ret; ++ int port, cpu_port_index = -1, ret; + struct device_node *port_dn; + phy_interface_t mode; + struct dsa_port *dp; diff --git a/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch b/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch new file mode 100644 index 0000000000..71fa3022d5 --- /dev/null +++ b/target/linux/generic/backport-5.15/749-v5.16-net-dsa-qca8k-tidy-for-loop-in-setup-and-add-cpu-port-c.patch @@ -0,0 +1,151 @@ +From 040e926f5813a5f4cc18dbff7c942d1e52f368f2 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 19 Oct 2021 02:08:50 +0200 +Subject: net: dsa: qca8k: tidy for loop in setup and add cpu port check + +Tidy and organize qca8k setup function from multiple for loop. +Change for loop in bridge leave/join to scan all port and skip cpu port. +No functional change intended. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 74 +++++++++++++++++++++++++++++-------------------- + 1 file changed, 44 insertions(+), 30 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1122,28 +1122,34 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + dev_warn(priv->dev, "mib init failed"); + +- /* Enable QCA header mode on the cpu port */ +- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(cpu_port), +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); +- if (ret) { +- dev_err(priv->dev, "failed enabling QCA header mode"); +- return ret; +- } +- +- /* Disable forwarding by default on all ports */ ++ /* Initial setup of all ports */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ /* Disable forwarding by default on all ports */ + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), + QCA8K_PORT_LOOKUP_MEMBER, 0); + if (ret) + return ret; +- } + +- /* Disable MAC by default on all ports */ +- for (i = 1; i < QCA8K_NUM_PORTS; i++) +- qca8k_port_set_status(priv, i, 0); ++ /* Enable QCA header mode on all cpu ports */ ++ if (dsa_is_cpu_port(ds, i)) { ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | ++ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode"); ++ return ret; ++ } ++ } ++ ++ /* Disable MAC by default on all user ports */ ++ if (dsa_is_user_port(ds, i)) ++ qca8k_port_set_status(priv, i, 0); ++ } + +- /* Forward all unknown frames to CPU port for Linux processing */ ++ /* Forward all unknown frames to CPU port for Linux processing ++ * Notice that in multi-cpu config only one port should be set ++ * for igmp, unknown, multicast and broadcast packet ++ */ + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, + BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | + BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | +@@ -1152,11 +1158,13 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- /* Setup connection between CPU port & user ports */ ++ /* Setup connection between CPU port & user ports ++ * Configure specific switch configuration for ports ++ */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { + /* CPU port gets connected to all user ports of the switch */ + if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), + QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); + if (ret) + return ret; +@@ -1193,16 +1201,14 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + } +- } + +- /* The port 5 of the qca8337 have some problem in flood condition. The +- * original legacy driver had some specific buffer and priority settings +- * for the different port suggested by the QCA switch team. Add this +- * missing settings to improve switch stability under load condition. +- * This problem is limited to qca8337 and other qca8k switch are not affected. +- */ +- if (priv->switch_id == QCA8K_ID_QCA8337) { +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ /* The port 5 of the qca8337 have some problem in flood condition. The ++ * original legacy driver had some specific buffer and priority settings ++ * for the different port suggested by the QCA switch team. Add this ++ * missing settings to improve switch stability under load condition. ++ * This problem is limited to qca8337 and other qca8k switch are not affected. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) { + switch (i) { + /* The 2 CPU port and port 5 requires some different + * priority than any other ports. +@@ -1238,6 +1244,12 @@ qca8k_setup(struct dsa_switch *ds) + QCA8K_PORT_HOL_CTRL1_WRED_EN, + mask); + } ++ ++ /* Set initial MTU for every port. ++ * We have only have a general MTU setting. So track ++ * every port and set the max across all port. ++ */ ++ priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; + } + + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ +@@ -1251,8 +1263,6 @@ qca8k_setup(struct dsa_switch *ds) + } + + /* Setup our port MTUs to match power on defaults */ +- for (i = 0; i < QCA8K_NUM_PORTS; i++) +- priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; + ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); + if (ret) + dev_warn(priv->dev, "failed setting MTU settings"); +@@ -1728,7 +1738,9 @@ qca8k_port_bridge_join(struct dsa_switch + cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + port_mask = BIT(cpu_port); + +- for (i = 1; i < QCA8K_NUM_PORTS; i++) { ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (dsa_is_cpu_port(ds, i)) ++ continue; + if (dsa_to_port(ds, i)->bridge_dev != br) + continue; + /* Add this port to the portvlan mask of the other ports +@@ -1758,7 +1770,9 @@ qca8k_port_bridge_leave(struct dsa_switc + + cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + +- for (i = 1; i < QCA8K_NUM_PORTS; i++) { ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (dsa_is_cpu_port(ds, i)) ++ continue; + if (dsa_to_port(ds, i)->bridge_dev != br) + continue; + /* Remove this port to the portvlan mask of the other ports diff --git a/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch b/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch new file mode 100644 index 0000000000..4a61703c52 --- /dev/null +++ b/target/linux/generic/backport-5.15/750-v5.16-net-dsa-qca8k-make-sure-pad0-mac06-exchange-is-disabled.patch @@ -0,0 +1,47 @@ +From 5f15d392dcb4aa250a63d6f2c5adfc26c0aedc78 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 2 Nov 2021 19:30:41 +0100 +Subject: net: dsa: qca8k: make sure PAD0 MAC06 exchange is disabled + +Some device set MAC06 exchange in the bootloader. This cause some +problem as we don't support this strange mode and we just set the port6 +as the primary CPU port. With MAC06 exchange, PAD0 reg configure port6 +instead of port0. Add an extra check and explicitly disable MAC06 exchange +to correctly configure the port PAD config. + +Signed-off-by: Ansuel Smith +Fixes: 3fcf734aa482 ("net: dsa: qca8k: add support for cpu port 6") +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 8 ++++++++ + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 9 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1109,6 +1109,14 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ /* Make sure MAC06 is disabled */ ++ ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL, ++ QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN); ++ if (ret) { ++ dev_err(priv->dev, "failed disabling MAC06 exchange"); ++ return ret; ++ } ++ + /* Enable CPU Port */ + ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -34,6 +34,7 @@ + #define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) + #define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) + #define QCA8K_REG_PORT0_PAD_CTRL 0x004 ++#define QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN BIT(31) + #define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19) + #define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18) + #define QCA8K_REG_PORT5_PAD_CTRL 0x008 diff --git a/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch b/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch new file mode 100644 index 0000000000..df9518d86c --- /dev/null +++ b/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch @@ -0,0 +1,48 @@ +From 3b00a07c2443745d62babfe08dbb2ad8e649526e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Fri, 19 Nov 2021 03:03:49 +0100 +Subject: [PATCH] net: dsa: qca8k: fix internal delay applied to the wrong PAD + config + +With SGMII phy the internal delay is always applied to the PAD0 config. +This is caused by the falling edge configuration that hardcode the reg +to PAD0 (as the falling edge bits are present only in PAD0 reg) +Move the delay configuration before the reg overwrite to correctly apply +the delay. + +Fixes: cef08115846e ("net: dsa: qca8k: set internal delay also for sgmii") +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1433,6 +1433,12 @@ qca8k_phylink_mac_config(struct dsa_swit + + qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val); + ++ /* From original code is reported port instability as SGMII also ++ * require delay set. Apply advised values here or take them from DT. ++ */ ++ if (state->interface == PHY_INTERFACE_MODE_SGMII) ++ qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); ++ + /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and + * falling edge is set writing in the PORT0 PAD reg + */ +@@ -1455,12 +1461,6 @@ qca8k_phylink_mac_config(struct dsa_swit + QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, + val); + +- /* From original code is reported port instability as SGMII also +- * require delay set. Apply advised values here or take them from DT. +- */ +- if (state->interface == PHY_INTERFACE_MODE_SGMII) +- qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg); +- + break; + default: + dev_err(ds->dev, "xMII mode %s not supported for port %d\n", diff --git a/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch b/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch new file mode 100644 index 0000000000..7348d93ec4 --- /dev/null +++ b/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch @@ -0,0 +1,46 @@ +From 65258b9d8cde45689bdc86ca39b50f01f983733b Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Nov 2021 03:03:50 +0100 +Subject: [PATCH] net: dsa: qca8k: fix MTU calculation + +qca8k has a global MTU, so its tracking the MTU per port to make sure +that the largest MTU gets applied. +Since it uses the frame size instead of MTU the driver MTU change function +will then add the size of Ethernet header and checksum on top of MTU. + +The driver currently populates the per port MTU size as Ethernet frame +length + checksum which equals 1518. + +The issue is that then MTU change function will go through all of the +ports, find the largest MTU and apply the Ethernet header + checksum on +top of it again, so for a desired MTU of 1500 you will end up with 1536. + +This is obviously incorrect, so to correct it populate the per port struct +MTU with just the MTU and not include the Ethernet header + checksum size +as those will be added by the MTU change function. + +Fixes: f58d2598cf70 ("net: dsa: qca8k: implement the port MTU callbacks") +Signed-off-by: Robert Marko +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1256,8 +1256,12 @@ qca8k_setup(struct dsa_switch *ds) + /* Set initial MTU for every port. + * We have only have a general MTU setting. So track + * every port and set the max across all port. ++ * Set per port MTU to 1500 as the MTU change function ++ * will add the overhead and if its set to 1518 then it ++ * will apply the overhead again and we will end up with ++ * MTU of 1536 instead of 1518 + */ +- priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; ++ priv->port_mtu[i] = ETH_DATA_LEN; + } + + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ diff --git a/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch b/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch new file mode 100644 index 0000000000..f477b1b929 --- /dev/null +++ b/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch @@ -0,0 +1,29 @@ +From b9133f3ef5a2659730cf47a74bd0a9259f1cf8ff Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:40 +0100 +Subject: net: dsa: qca8k: remove redundant check in parse_port_config + +The very next check for port 0 and 6 already makes sure we don't go out +of bounds with the ports_config delay table. +Remove the redundant check. + +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -983,7 +983,7 @@ qca8k_parse_port_config(struct qca8k_pri + u32 delay; + + /* We have 2 CPU port. Check them */ +- for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) { ++ for (port = 0; port < QCA8K_NUM_PORTS; port++) { + /* Skip every other port */ + if (port != 0 && port != 6) + continue; diff --git a/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch b/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch new file mode 100644 index 0000000000..c1489fd9a8 --- /dev/null +++ b/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch @@ -0,0 +1,508 @@ +From 90ae68bfc2ffcb54a4ba4f64edbeb84a80cbb57c Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:41 +0100 +Subject: net: dsa: qca8k: convert to GENMASK/FIELD_PREP/FIELD_GET + +Convert and try to standardize bit fields using +GENMASK/FIELD_PREP/FIELD_GET macros. Rework some logic to support the +standard macro and tidy things up. No functional change intended. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 98 +++++++++++++++---------------- + drivers/net/dsa/qca8k.h | 153 ++++++++++++++++++++++++++---------------------- + 2 files changed, 130 insertions(+), 121 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -319,18 +320,18 @@ qca8k_fdb_read(struct qca8k_priv *priv, + } + + /* vid - 83:72 */ +- fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M; ++ fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]); + /* aging - 67:64 */ +- fdb->aging = reg[2] & QCA8K_ATU_STATUS_M; ++ fdb->aging = FIELD_GET(QCA8K_ATU_STATUS_MASK, reg[2]); + /* portmask - 54:48 */ +- fdb->port_mask = (reg[1] >> QCA8K_ATU_PORT_S) & QCA8K_ATU_PORT_M; ++ fdb->port_mask = FIELD_GET(QCA8K_ATU_PORT_MASK, reg[1]); + /* mac - 47:0 */ +- fdb->mac[0] = (reg[1] >> QCA8K_ATU_ADDR0_S) & 0xff; +- fdb->mac[1] = reg[1] & 0xff; +- fdb->mac[2] = (reg[0] >> QCA8K_ATU_ADDR2_S) & 0xff; +- fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff; +- fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff; +- fdb->mac[5] = reg[0] & 0xff; ++ fdb->mac[0] = FIELD_GET(QCA8K_ATU_ADDR0_MASK, reg[1]); ++ fdb->mac[1] = FIELD_GET(QCA8K_ATU_ADDR1_MASK, reg[1]); ++ fdb->mac[2] = FIELD_GET(QCA8K_ATU_ADDR2_MASK, reg[0]); ++ fdb->mac[3] = FIELD_GET(QCA8K_ATU_ADDR3_MASK, reg[0]); ++ fdb->mac[4] = FIELD_GET(QCA8K_ATU_ADDR4_MASK, reg[0]); ++ fdb->mac[5] = FIELD_GET(QCA8K_ATU_ADDR5_MASK, reg[0]); + + return 0; + } +@@ -343,18 +344,18 @@ qca8k_fdb_write(struct qca8k_priv *priv, + int i; + + /* vid - 83:72 */ +- reg[2] = (vid & QCA8K_ATU_VID_M) << QCA8K_ATU_VID_S; ++ reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); + /* aging - 67:64 */ +- reg[2] |= aging & QCA8K_ATU_STATUS_M; ++ reg[2] |= FIELD_PREP(QCA8K_ATU_STATUS_MASK, aging); + /* portmask - 54:48 */ +- reg[1] = (port_mask & QCA8K_ATU_PORT_M) << QCA8K_ATU_PORT_S; ++ reg[1] = FIELD_PREP(QCA8K_ATU_PORT_MASK, port_mask); + /* mac - 47:0 */ +- reg[1] |= mac[0] << QCA8K_ATU_ADDR0_S; +- reg[1] |= mac[1]; +- reg[0] |= mac[2] << QCA8K_ATU_ADDR2_S; +- reg[0] |= mac[3] << QCA8K_ATU_ADDR3_S; +- reg[0] |= mac[4] << QCA8K_ATU_ADDR4_S; +- reg[0] |= mac[5]; ++ reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR0_MASK, mac[0]); ++ reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR1_MASK, mac[1]); ++ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR2_MASK, mac[2]); ++ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR3_MASK, mac[3]); ++ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR4_MASK, mac[4]); ++ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); + + /* load the array into the ARL table */ + for (i = 0; i < 3; i++) +@@ -372,7 +373,7 @@ qca8k_fdb_access(struct qca8k_priv *priv + reg |= cmd; + if (port >= 0) { + reg |= QCA8K_ATU_FUNC_PORT_EN; +- reg |= (port & QCA8K_ATU_FUNC_PORT_M) << QCA8K_ATU_FUNC_PORT_S; ++ reg |= FIELD_PREP(QCA8K_ATU_FUNC_PORT_MASK, port); + } + + /* Write the function register triggering the table access */ +@@ -454,7 +455,7 @@ qca8k_vlan_access(struct qca8k_priv *pri + /* Set the command and VLAN index */ + reg = QCA8K_VTU_FUNC1_BUSY; + reg |= cmd; +- reg |= vid << QCA8K_VTU_FUNC1_VID_S; ++ reg |= FIELD_PREP(QCA8K_VTU_FUNC1_VID_MASK, vid); + + /* Write the function register triggering the table access */ + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); +@@ -500,13 +501,11 @@ qca8k_vlan_add(struct qca8k_priv *priv, + if (ret < 0) + goto out; + reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; +- reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); ++ reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port); + if (untagged) +- reg |= QCA8K_VTU_FUNC0_EG_MODE_UNTAG << +- QCA8K_VTU_FUNC0_EG_MODE_S(port); ++ reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(port); + else +- reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG << +- QCA8K_VTU_FUNC0_EG_MODE_S(port); ++ reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(port); + + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); + if (ret) +@@ -534,15 +533,13 @@ qca8k_vlan_del(struct qca8k_priv *priv, + ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); + if (ret < 0) + goto out; +- reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); +- reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << +- QCA8K_VTU_FUNC0_EG_MODE_S(port); ++ reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port); ++ reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(port); + + /* Check if we're the last member to be removed */ + del = true; + for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- mask = QCA8K_VTU_FUNC0_EG_MODE_NOT; +- mask <<= QCA8K_VTU_FUNC0_EG_MODE_S(i); ++ mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i); + + if ((reg & mask) != mask) { + del = false; +@@ -1014,7 +1011,7 @@ qca8k_parse_port_config(struct qca8k_pri + mode == PHY_INTERFACE_MODE_RGMII_TXID) + delay = 1; + +- if (delay > QCA8K_MAX_DELAY) { ++ if (!FIELD_FIT(QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK, delay)) { + dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); + delay = 3; + } +@@ -1030,7 +1027,7 @@ qca8k_parse_port_config(struct qca8k_pri + mode == PHY_INTERFACE_MODE_RGMII_RXID) + delay = 2; + +- if (delay > QCA8K_MAX_DELAY) { ++ if (!FIELD_FIT(QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK, delay)) { + dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); + delay = 3; + } +@@ -1141,8 +1138,8 @@ qca8k_setup(struct dsa_switch *ds) + /* Enable QCA header mode on all cpu ports */ + if (dsa_is_cpu_port(ds, i)) { + ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | +- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); + if (ret) { + dev_err(priv->dev, "failed enabling QCA header mode"); + return ret; +@@ -1159,10 +1156,10 @@ qca8k_setup(struct dsa_switch *ds) + * for igmp, unknown, multicast and broadcast packet + */ + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | +- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, BIT(cpu_port)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, BIT(cpu_port)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, BIT(cpu_port)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, BIT(cpu_port))); + if (ret) + return ret; + +@@ -1180,8 +1177,6 @@ qca8k_setup(struct dsa_switch *ds) + + /* Individual user ports get connected to CPU port only */ + if (dsa_is_user_port(ds, i)) { +- int shift = 16 * (i % 2); +- + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), + QCA8K_PORT_LOOKUP_MEMBER, + BIT(cpu_port)); +@@ -1198,8 +1193,8 @@ qca8k_setup(struct dsa_switch *ds) + * default egress vid + */ + ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), +- 0xfff << shift, +- QCA8K_PORT_VID_DEF << shift); ++ QCA8K_EGREES_VLAN_PORT_MASK(i), ++ QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF)); + if (ret) + return ret; + +@@ -1246,7 +1241,7 @@ qca8k_setup(struct dsa_switch *ds) + QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | + QCA8K_PORT_HOL_CTRL1_WRED_EN; + qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), +- QCA8K_PORT_HOL_CTRL1_ING_BUF | ++ QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | + QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | + QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | + QCA8K_PORT_HOL_CTRL1_WRED_EN, +@@ -1269,8 +1264,8 @@ qca8k_setup(struct dsa_switch *ds) + mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | + QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); + qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, +- QCA8K_GLOBAL_FC_GOL_XON_THRES_S | +- QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S, ++ QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK | ++ QCA8K_GLOBAL_FC_GOL_XOFF_THRES_MASK, + mask); + } + +@@ -1918,11 +1913,11 @@ qca8k_port_vlan_filtering(struct dsa_swi + + if (vlan_filtering) { + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_VLAN_MODE, ++ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, + QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE); + } else { + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_VLAN_MODE, ++ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, + QCA8K_PORT_LOOKUP_VLAN_MODE_NONE); + } + +@@ -1953,11 +1948,9 @@ qca8k_port_vlan_add(struct dsa_switch *d + dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret); + + if (pvid) { +- int shift = 16 * (port % 2); +- + qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), +- 0xfff << shift, +- vlan->vid_end << shift); ++ QCA8K_EGREES_VLAN_PORT_MASK(port), ++ QCA8K_EGREES_VLAN_PORT(port, vlan->vid_end)); + qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), + QCA8K_PORT_VLAN_CVID(vlan->vid_end) | + QCA8K_PORT_VLAN_SVID(vlan->vid_end)); +@@ -2050,7 +2043,7 @@ static int qca8k_read_switch_id(struct q + if (ret < 0) + return -ENODEV; + +- id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); ++ id = QCA8K_MASK_CTRL_DEVICE_ID(val); + if (id != data->id) { + dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); + return -ENODEV; +@@ -2059,7 +2052,7 @@ static int qca8k_read_switch_id(struct q + priv->switch_id = id; + + /* Save revision to communicate to the internal PHY driver */ +- priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK); ++ priv->switch_revision = QCA8K_MASK_CTRL_REV_ID(val); + + return 0; + } +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -30,9 +30,9 @@ + /* Global control registers */ + #define QCA8K_REG_MASK_CTRL 0x000 + #define QCA8K_MASK_CTRL_REV_ID_MASK GENMASK(7, 0) +-#define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0) ++#define QCA8K_MASK_CTRL_REV_ID(x) FIELD_GET(QCA8K_MASK_CTRL_REV_ID_MASK, x) + #define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) +-#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) ++#define QCA8K_MASK_CTRL_DEVICE_ID(x) FIELD_GET(QCA8K_MASK_CTRL_DEVICE_ID_MASK, x) + #define QCA8K_REG_PORT0_PAD_CTRL 0x004 + #define QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN BIT(31) + #define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19) +@@ -41,12 +41,11 @@ + #define QCA8K_REG_PORT6_PAD_CTRL 0x00c + #define QCA8K_PORT_PAD_RGMII_EN BIT(26) + #define QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK GENMASK(23, 22) +-#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22) ++#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) FIELD_PREP(QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK, x) + #define QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK GENMASK(21, 20) +-#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20) ++#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) FIELD_PREP(QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK, x) + #define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25) + #define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) +-#define QCA8K_MAX_DELAY 3 + #define QCA8K_PORT_PAD_SGMII_EN BIT(7) + #define QCA8K_REG_PWS 0x010 + #define QCA8K_PWS_POWER_ON_SEL BIT(31) +@@ -68,10 +67,12 @@ + #define QCA8K_MDIO_MASTER_READ BIT(27) + #define QCA8K_MDIO_MASTER_WRITE 0 + #define QCA8K_MDIO_MASTER_SUP_PRE BIT(26) +-#define QCA8K_MDIO_MASTER_PHY_ADDR(x) ((x) << 21) +-#define QCA8K_MDIO_MASTER_REG_ADDR(x) ((x) << 16) +-#define QCA8K_MDIO_MASTER_DATA(x) (x) ++#define QCA8K_MDIO_MASTER_PHY_ADDR_MASK GENMASK(25, 21) ++#define QCA8K_MDIO_MASTER_PHY_ADDR(x) FIELD_PREP(QCA8K_MDIO_MASTER_PHY_ADDR_MASK, x) ++#define QCA8K_MDIO_MASTER_REG_ADDR_MASK GENMASK(20, 16) ++#define QCA8K_MDIO_MASTER_REG_ADDR(x) FIELD_PREP(QCA8K_MDIO_MASTER_REG_ADDR_MASK, x) + #define QCA8K_MDIO_MASTER_DATA_MASK GENMASK(15, 0) ++#define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x) + #define QCA8K_MDIO_MASTER_MAX_PORTS 5 + #define QCA8K_MDIO_MASTER_MAX_REG 32 + #define QCA8K_GOL_MAC_ADDR0 0x60 +@@ -93,9 +94,7 @@ + #define QCA8K_PORT_STATUS_FLOW_AUTO BIT(12) + #define QCA8K_REG_PORT_HDR_CTRL(_i) (0x9c + (_i * 4)) + #define QCA8K_PORT_HDR_CTRL_RX_MASK GENMASK(3, 2) +-#define QCA8K_PORT_HDR_CTRL_RX_S 2 + #define QCA8K_PORT_HDR_CTRL_TX_MASK GENMASK(1, 0) +-#define QCA8K_PORT_HDR_CTRL_TX_S 0 + #define QCA8K_PORT_HDR_CTRL_ALL 2 + #define QCA8K_PORT_HDR_CTRL_MGMT 1 + #define QCA8K_PORT_HDR_CTRL_NONE 0 +@@ -105,10 +104,11 @@ + #define QCA8K_SGMII_EN_TX BIT(3) + #define QCA8K_SGMII_EN_SD BIT(4) + #define QCA8K_SGMII_CLK125M_DELAY BIT(7) +-#define QCA8K_SGMII_MODE_CTRL_MASK (BIT(22) | BIT(23)) +-#define QCA8K_SGMII_MODE_CTRL_BASEX (0 << 22) +-#define QCA8K_SGMII_MODE_CTRL_PHY (1 << 22) +-#define QCA8K_SGMII_MODE_CTRL_MAC (2 << 22) ++#define QCA8K_SGMII_MODE_CTRL_MASK GENMASK(23, 22) ++#define QCA8K_SGMII_MODE_CTRL(x) FIELD_PREP(QCA8K_SGMII_MODE_CTRL_MASK, x) ++#define QCA8K_SGMII_MODE_CTRL_BASEX QCA8K_SGMII_MODE_CTRL(0x0) ++#define QCA8K_SGMII_MODE_CTRL_PHY QCA8K_SGMII_MODE_CTRL(0x1) ++#define QCA8K_SGMII_MODE_CTRL_MAC QCA8K_SGMII_MODE_CTRL(0x2) + + /* MAC_PWR_SEL registers */ + #define QCA8K_REG_MAC_PWR_SEL 0x0e4 +@@ -121,100 +121,115 @@ + + /* ACL registers */ + #define QCA8K_REG_PORT_VLAN_CTRL0(_i) (0x420 + (_i * 8)) +-#define QCA8K_PORT_VLAN_CVID(x) (x << 16) +-#define QCA8K_PORT_VLAN_SVID(x) x ++#define QCA8K_PORT_VLAN_CVID_MASK GENMASK(27, 16) ++#define QCA8K_PORT_VLAN_CVID(x) FIELD_PREP(QCA8K_PORT_VLAN_CVID_MASK, x) ++#define QCA8K_PORT_VLAN_SVID_MASK GENMASK(11, 0) ++#define QCA8K_PORT_VLAN_SVID(x) FIELD_PREP(QCA8K_PORT_VLAN_SVID_MASK, x) + #define QCA8K_REG_PORT_VLAN_CTRL1(_i) (0x424 + (_i * 8)) + #define QCA8K_REG_IPV4_PRI_BASE_ADDR 0x470 + #define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474 + + /* Lookup registers */ + #define QCA8K_REG_ATU_DATA0 0x600 +-#define QCA8K_ATU_ADDR2_S 24 +-#define QCA8K_ATU_ADDR3_S 16 +-#define QCA8K_ATU_ADDR4_S 8 ++#define QCA8K_ATU_ADDR2_MASK GENMASK(31, 24) ++#define QCA8K_ATU_ADDR3_MASK GENMASK(23, 16) ++#define QCA8K_ATU_ADDR4_MASK GENMASK(15, 8) ++#define QCA8K_ATU_ADDR5_MASK GENMASK(7, 0) + #define QCA8K_REG_ATU_DATA1 0x604 +-#define QCA8K_ATU_PORT_M 0x7f +-#define QCA8K_ATU_PORT_S 16 +-#define QCA8K_ATU_ADDR0_S 8 ++#define QCA8K_ATU_PORT_MASK GENMASK(22, 16) ++#define QCA8K_ATU_ADDR0_MASK GENMASK(15, 8) ++#define QCA8K_ATU_ADDR1_MASK GENMASK(7, 0) + #define QCA8K_REG_ATU_DATA2 0x608 +-#define QCA8K_ATU_VID_M 0xfff +-#define QCA8K_ATU_VID_S 8 +-#define QCA8K_ATU_STATUS_M 0xf ++#define QCA8K_ATU_VID_MASK GENMASK(19, 8) ++#define QCA8K_ATU_STATUS_MASK GENMASK(3, 0) + #define QCA8K_ATU_STATUS_STATIC 0xf + #define QCA8K_REG_ATU_FUNC 0x60c + #define QCA8K_ATU_FUNC_BUSY BIT(31) + #define QCA8K_ATU_FUNC_PORT_EN BIT(14) + #define QCA8K_ATU_FUNC_MULTI_EN BIT(13) + #define QCA8K_ATU_FUNC_FULL BIT(12) +-#define QCA8K_ATU_FUNC_PORT_M 0xf +-#define QCA8K_ATU_FUNC_PORT_S 8 ++#define QCA8K_ATU_FUNC_PORT_MASK GENMASK(11, 8) + #define QCA8K_REG_VTU_FUNC0 0x610 + #define QCA8K_VTU_FUNC0_VALID BIT(20) + #define QCA8K_VTU_FUNC0_IVL_EN BIT(19) +-#define QCA8K_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) +-#define QCA8K_VTU_FUNC0_EG_MODE_MASK 3 +-#define QCA8K_VTU_FUNC0_EG_MODE_UNMOD 0 +-#define QCA8K_VTU_FUNC0_EG_MODE_UNTAG 1 +-#define QCA8K_VTU_FUNC0_EG_MODE_TAG 2 +-#define QCA8K_VTU_FUNC0_EG_MODE_NOT 3 ++/* QCA8K_VTU_FUNC0_EG_MODE_MASK GENMASK(17, 4) ++ * It does contain VLAN_MODE for each port [5:4] for port0, ++ * [7:6] for port1 ... [17:16] for port6. Use virtual port ++ * define to handle this. ++ */ ++#define QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i) (4 + (_i) * 2) ++#define QCA8K_VTU_FUNC0_EG_MODE_MASK GENMASK(1, 0) ++#define QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(_i) (GENMASK(1, 0) << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i)) ++#define QCA8K_VTU_FUNC0_EG_MODE_UNMOD FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x0) ++#define QCA8K_VTU_FUNC0_EG_MODE_PORT_UNMOD(_i) (QCA8K_VTU_FUNC0_EG_MODE_UNMOD << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i)) ++#define QCA8K_VTU_FUNC0_EG_MODE_UNTAG FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x1) ++#define QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(_i) (QCA8K_VTU_FUNC0_EG_MODE_UNTAG << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i)) ++#define QCA8K_VTU_FUNC0_EG_MODE_TAG FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x2) ++#define QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(_i) (QCA8K_VTU_FUNC0_EG_MODE_TAG << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i)) ++#define QCA8K_VTU_FUNC0_EG_MODE_NOT FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x3) ++#define QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(_i) (QCA8K_VTU_FUNC0_EG_MODE_NOT << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i)) + #define QCA8K_REG_VTU_FUNC1 0x614 + #define QCA8K_VTU_FUNC1_BUSY BIT(31) +-#define QCA8K_VTU_FUNC1_VID_S 16 ++#define QCA8K_VTU_FUNC1_VID_MASK GENMASK(27, 16) + #define QCA8K_VTU_FUNC1_FULL BIT(4) + #define QCA8K_REG_GLOBAL_FW_CTRL0 0x620 + #define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) + #define QCA8K_REG_GLOBAL_FW_CTRL1 0x624 +-#define QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S 24 +-#define QCA8K_GLOBAL_FW_CTRL1_BC_DP_S 16 +-#define QCA8K_GLOBAL_FW_CTRL1_MC_DP_S 8 +-#define QCA8K_GLOBAL_FW_CTRL1_UC_DP_S 0 ++#define QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK GENMASK(30, 24) ++#define QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK GENMASK(22, 16) ++#define QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK GENMASK(14, 8) ++#define QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK GENMASK(6, 0) + #define QCA8K_PORT_LOOKUP_CTRL(_i) (0x660 + (_i) * 0xc) + #define QCA8K_PORT_LOOKUP_MEMBER GENMASK(6, 0) +-#define QCA8K_PORT_LOOKUP_VLAN_MODE GENMASK(9, 8) +-#define QCA8K_PORT_LOOKUP_VLAN_MODE_NONE (0 << 8) +-#define QCA8K_PORT_LOOKUP_VLAN_MODE_FALLBACK (1 << 8) +-#define QCA8K_PORT_LOOKUP_VLAN_MODE_CHECK (2 << 8) +-#define QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE (3 << 8) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_MASK GENMASK(9, 8) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE(x) FIELD_PREP(QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, x) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_NONE QCA8K_PORT_LOOKUP_VLAN_MODE(0x0) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_FALLBACK QCA8K_PORT_LOOKUP_VLAN_MODE(0x1) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_CHECK QCA8K_PORT_LOOKUP_VLAN_MODE(0x2) ++#define QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE QCA8K_PORT_LOOKUP_VLAN_MODE(0x3) + #define QCA8K_PORT_LOOKUP_STATE_MASK GENMASK(18, 16) +-#define QCA8K_PORT_LOOKUP_STATE_DISABLED (0 << 16) +-#define QCA8K_PORT_LOOKUP_STATE_BLOCKING (1 << 16) +-#define QCA8K_PORT_LOOKUP_STATE_LISTENING (2 << 16) +-#define QCA8K_PORT_LOOKUP_STATE_LEARNING (3 << 16) +-#define QCA8K_PORT_LOOKUP_STATE_FORWARD (4 << 16) +-#define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) ++#define QCA8K_PORT_LOOKUP_STATE(x) FIELD_PREP(QCA8K_PORT_LOOKUP_STATE_MASK, x) ++#define QCA8K_PORT_LOOKUP_STATE_DISABLED QCA8K_PORT_LOOKUP_STATE(0x0) ++#define QCA8K_PORT_LOOKUP_STATE_BLOCKING QCA8K_PORT_LOOKUP_STATE(0x1) ++#define QCA8K_PORT_LOOKUP_STATE_LISTENING QCA8K_PORT_LOOKUP_STATE(0x2) ++#define QCA8K_PORT_LOOKUP_STATE_LEARNING QCA8K_PORT_LOOKUP_STATE(0x3) ++#define QCA8K_PORT_LOOKUP_STATE_FORWARD QCA8K_PORT_LOOKUP_STATE(0x4) + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) + + #define QCA8K_REG_GLOBAL_FC_THRESH 0x800 +-#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16) +-#define QCA8K_GLOBAL_FC_GOL_XON_THRES_S GENMASK(24, 16) +-#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) ((x) << 0) +-#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S GENMASK(8, 0) ++#define QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK GENMASK(24, 16) ++#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) FIELD_PREP(QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK, x) ++#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_MASK GENMASK(8, 0) ++#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) FIELD_PREP(QCA8K_GLOBAL_FC_GOL_XOFF_THRES_MASK, x) + + #define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF GENMASK(7, 4) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) ((x) << 4) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF GENMASK(11, 8) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) ((x) << 8) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF GENMASK(15, 12) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) ((x) << 12) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF GENMASK(19, 16) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) ((x) << 16) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF GENMASK(23, 20) +-#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) ((x) << 20) +-#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF GENMASK(29, 24) +-#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) ((x) << 24) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF_MASK GENMASK(3, 0) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF_MASK, x) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF_MASK GENMASK(7, 4) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF_MASK, x) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF_MASK GENMASK(11, 8) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF_MASK, x) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF_MASK GENMASK(15, 12) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF_MASK, x) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF_MASK GENMASK(19, 16) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF_MASK, x) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF_MASK GENMASK(23, 20) ++#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF_MASK, x) ++#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF_MASK GENMASK(29, 24) ++#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF_MASK, x) + + #define QCA8K_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) +-#define QCA8K_PORT_HOL_CTRL1_ING_BUF GENMASK(3, 0) +-#define QCA8K_PORT_HOL_CTRL1_ING(x) ((x) << 0) ++#define QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK GENMASK(3, 0) ++#define QCA8K_PORT_HOL_CTRL1_ING(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK, x) + #define QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN BIT(6) + #define QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN BIT(7) + #define QCA8K_PORT_HOL_CTRL1_WRED_EN BIT(8) + #define QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) + + /* Pkt edit registers */ ++#define QCA8K_EGREES_VLAN_PORT_SHIFT(_i) (16 * ((_i) % 2)) ++#define QCA8K_EGREES_VLAN_PORT_MASK(_i) (GENMASK(11, 0) << QCA8K_EGREES_VLAN_PORT_SHIFT(_i)) ++#define QCA8K_EGREES_VLAN_PORT(_i, x) ((x) << QCA8K_EGREES_VLAN_PORT_SHIFT(_i)) + #define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2))) + + /* L3 registers */ diff --git a/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch b/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch new file mode 100644 index 0000000000..8c39b8ea29 --- /dev/null +++ b/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch @@ -0,0 +1,25 @@ +From 994c28b6f971fa5db8ae977daea37eee87d93d51 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:42 +0100 +Subject: net: dsa: qca8k: remove extra mutex_init in qca8k_setup + +Mutex is already init in sw_probe. Remove the extra init in qca8k_setup. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1086,8 +1086,6 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- mutex_init(&priv->reg_mutex); +- + /* Start by setting up the register mapping */ + priv->regmap = devm_regmap_init(ds->dev, NULL, priv, + &qca8k_regmap_config); diff --git a/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch b/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch new file mode 100644 index 0000000000..9fcc74a7ce --- /dev/null +++ b/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch @@ -0,0 +1,46 @@ +From 36b8af12f424e7a7f60a935c60a0fd4aa0822378 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:43 +0100 +Subject: net: dsa: qca8k: move regmap init in probe and set it mandatory + +In preparation for regmap conversion, move regmap init in the probe +function and make it mandatory as any read/write/rmw operation will be +converted to regmap API. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1086,12 +1086,6 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- /* Start by setting up the register mapping */ +- priv->regmap = devm_regmap_init(ds->dev, NULL, priv, +- &qca8k_regmap_config); +- if (IS_ERR(priv->regmap)) +- dev_warn(priv->dev, "regmap initialization failed"); +- + ret = qca8k_setup_mdio_bus(priv); + if (ret) + return ret; +@@ -2085,6 +2079,14 @@ qca8k_sw_probe(struct mdio_device *mdiod + gpiod_set_value_cansleep(priv->reset_gpio, 0); + } + ++ /* Start by setting up the register mapping */ ++ priv->regmap = devm_regmap_init(&mdiodev->dev, NULL, priv, ++ &qca8k_regmap_config); ++ if (IS_ERR(priv->regmap)) { ++ dev_err(priv->dev, "regmap initialization failed"); ++ return PTR_ERR(priv->regmap); ++ } ++ + /* Check the detected switch id */ + ret = qca8k_read_switch_id(priv); + if (ret) diff --git a/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch b/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch new file mode 100644 index 0000000000..4ca9c8ba41 --- /dev/null +++ b/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch @@ -0,0 +1,249 @@ +From 8b5f3f29a81a71934d004e21a1292c1148b05926 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:44 +0100 +Subject: net: dsa: qca8k: initial conversion to regmap helper + +Convert any qca8k set/clear/pool to regmap helper and add +missing config to regmap_config struct. +Read/write/rmw operation are reworked to use the regmap helper +internally to keep the delta of this patch low. These additional +function will then be dropped when the code split will be proposed. + +Ipq40xx SoC have the internal switch based on the qca8k regmap but use +mmio for read/write/rmw operation instead of mdio. +In preparation for the support of this internal switch, convert the +driver to regmap API to later split the driver to common and specific +code. The overhead introduced by the use of regamp API is marginal as the +internal mdio will bypass it by using its direct access and regmap will be +used only by configuration functions or fdb access. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 107 +++++++++++++++++++++--------------------------- + 1 file changed, 47 insertions(+), 60 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 + static int + qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) + { ++ return regmap_read(priv->regmap, reg, val); ++} ++ ++static int ++qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) ++{ ++ return regmap_write(priv->regmap, reg, val); ++} ++ ++static int ++qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) ++{ ++ return regmap_update_bits(priv->regmap, reg, mask, write_val); ++} ++ ++static int ++qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + int ret; +@@ -172,8 +192,9 @@ exit: + } + + static int +-qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) ++qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) + { ++ struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + int ret; +@@ -194,8 +215,9 @@ exit: + } + + static int +-qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) ++qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) + { ++ struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; +@@ -223,34 +245,6 @@ exit: + return ret; + } + +-static int +-qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val) +-{ +- return qca8k_rmw(priv, reg, 0, val); +-} +- +-static int +-qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val) +-{ +- return qca8k_rmw(priv, reg, val, 0); +-} +- +-static int +-qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +-{ +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; +- +- return qca8k_read(priv, reg, val); +-} +- +-static int +-qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) +-{ +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; +- +- return qca8k_write(priv, reg, val); +-} +- + static const struct regmap_range qca8k_readable_ranges[] = { + regmap_reg_range(0x0000, 0x00e4), /* Global control */ + regmap_reg_range(0x0100, 0x0168), /* EEE control */ +@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap + .max_register = 0x16ac, /* end MIB - Port6 range */ + .reg_read = qca8k_regmap_read, + .reg_write = qca8k_regmap_write, ++ .reg_update_bits = qca8k_regmap_update_bits, + .rd_table = &qca8k_readable_table, ++ .disable_locking = true, /* Locking is handled by qca8k read/write */ ++ .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ + }; + + static int + qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + { +- int ret, ret1; + u32 val; + +- ret = read_poll_timeout(qca8k_read, ret1, !(val & mask), +- 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, +- priv, reg, &val); +- +- /* Check if qca8k_read has failed for a different reason +- * before returning -ETIMEDOUT +- */ +- if (ret < 0 && ret1 < 0) +- return ret1; +- +- return ret; ++ return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0, ++ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC); + } + + static int +@@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv) + int ret; + + mutex_lock(&priv->reg_mutex); +- ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); ++ ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); + if (ret) + goto exit; + +@@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv) + if (ret) + goto exit; + +- ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); ++ ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); + if (ret) + goto exit; + +@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv + mask |= QCA8K_PORT_STATUS_LINK_AUTO; + + if (enable) +- qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask); ++ regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask); + else +- qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask); ++ regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask); + } + + static u32 +@@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv * + * a dt-overlay and driver reload changed the configuration + */ + +- return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, +- QCA8K_MDIO_MASTER_EN); ++ return regmap_clear_bits(priv->regmap, QCA8K_MDIO_MASTER_CTRL, ++ QCA8K_MDIO_MASTER_EN); + } + + /* Check if the devicetree declare the port:phy mapping */ +@@ -1099,16 +1086,16 @@ qca8k_setup(struct dsa_switch *ds) + return ret; + + /* Make sure MAC06 is disabled */ +- ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL, +- QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN); ++ ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL, ++ QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN); + if (ret) { + dev_err(priv->dev, "failed disabling MAC06 exchange"); + return ret; + } + + /* Enable CPU Port */ +- ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, +- QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); ++ ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, ++ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); + if (ret) { + dev_err(priv->dev, "failed enabling CPU port"); + return ret; +@@ -1176,8 +1163,8 @@ qca8k_setup(struct dsa_switch *ds) + return ret; + + /* Enable ARP Auto-learning by default */ +- ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); ++ ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_LEARN); + if (ret) + return ret; + +@@ -1745,9 +1732,9 @@ qca8k_port_bridge_join(struct dsa_switch + /* Add this port to the portvlan mask of the other ports + * in the bridge + */ +- ret = qca8k_reg_set(priv, +- QCA8K_PORT_LOOKUP_CTRL(i), +- BIT(port)); ++ ret = regmap_set_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); + if (ret) + return ret; + if (i != port) +@@ -1777,9 +1764,9 @@ qca8k_port_bridge_leave(struct dsa_switc + /* Remove this port to the portvlan mask of the other ports + * in the bridge + */ +- qca8k_reg_clear(priv, +- QCA8K_PORT_LOOKUP_CTRL(i), +- BIT(port)); ++ regmap_clear_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); + } + + /* Set the cpu port to be the only one in the portvlan mask of diff --git a/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch b/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch new file mode 100644 index 0000000000..78bdf7f77d --- /dev/null +++ b/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch @@ -0,0 +1,120 @@ +From c126f118b330ccf0db0dda4a4bd6c729865a205f Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:45 +0100 +Subject: net: dsa: qca8k: add additional MIB counter and make it dynamic + +We are currently missing 2 additionals MIB counter present in QCA833x +switch. +QC832x switch have 39 MIB counter and QCA833X have 41 MIB counter. +Add the additional MIB counter and rework the MIB function to print the +correct supported counter from the match_data struct. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 23 ++++++++++++++++++++--- + drivers/net/dsa/qca8k.h | 4 ++++ + 2 files changed, 24 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -70,6 +70,8 @@ static const struct qca8k_mib_desc ar832 + MIB_DESC(1, 0x9c, "TxExcDefer"), + MIB_DESC(1, 0xa0, "TxDefer"), + MIB_DESC(1, 0xa4, "TxLateCol"), ++ MIB_DESC(1, 0xa8, "RXUnicast"), ++ MIB_DESC(1, 0xac, "TXUnicast"), + }; + + /* The 32bit switch registers are accessed indirectly. To achieve this we need +@@ -1605,12 +1607,16 @@ qca8k_phylink_mac_link_up(struct dsa_swi + static void + qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) + { ++ const struct qca8k_match_data *match_data; ++ struct qca8k_priv *priv = ds->priv; + int i; + + if (stringset != ETH_SS_STATS) + return; + +- for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) ++ match_data = of_device_get_match_data(priv->dev); ++ ++ for (i = 0; i < match_data->mib_count; i++) + strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name, + ETH_GSTRING_LEN); + } +@@ -1620,12 +1626,15 @@ qca8k_get_ethtool_stats(struct dsa_switc + uint64_t *data) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ const struct qca8k_match_data *match_data; + const struct qca8k_mib_desc *mib; + u32 reg, i, val; + u32 hi = 0; + int ret; + +- for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { ++ match_data = of_device_get_match_data(priv->dev); ++ ++ for (i = 0; i < match_data->mib_count; i++) { + mib = &ar8327_mib[i]; + reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; + +@@ -1648,10 +1657,15 @@ qca8k_get_ethtool_stats(struct dsa_switc + static int + qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset) + { ++ const struct qca8k_match_data *match_data; ++ struct qca8k_priv *priv = ds->priv; ++ + if (sset != ETH_SS_STATS) + return 0; + +- return ARRAY_SIZE(ar8327_mib); ++ match_data = of_device_get_match_data(priv->dev); ++ ++ return match_data->mib_count; + } + + static int +@@ -2146,14 +2160,17 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, + static const struct qca8k_match_data qca8327 = { + .id = QCA8K_ID_QCA8327, + .reduced_package = true, ++ .mib_count = QCA8K_QCA832X_MIB_COUNT, + }; + + static const struct qca8k_match_data qca8328 = { + .id = QCA8K_ID_QCA8327, ++ .mib_count = QCA8K_QCA832X_MIB_COUNT, + }; + + static const struct qca8k_match_data qca833x = { + .id = QCA8K_ID_QCA8337, ++ .mib_count = QCA8K_QCA833X_MIB_COUNT, + }; + + static const struct of_device_id qca8k_of_match[] = { +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -21,6 +21,9 @@ + #define PHY_ID_QCA8337 0x004dd036 + #define QCA8K_ID_QCA8337 0x13 + ++#define QCA8K_QCA832X_MIB_COUNT 39 ++#define QCA8K_QCA833X_MIB_COUNT 41 ++ + #define QCA8K_BUSY_WAIT_TIMEOUT 2000 + + #define QCA8K_NUM_FDB_RECORDS 2048 +@@ -279,6 +282,7 @@ struct ar8xxx_port_status { + struct qca8k_match_data { + u8 id; + bool reduced_package; ++ u8 mib_count; + }; + + enum { diff --git a/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch b/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch new file mode 100644 index 0000000000..41efa89b5e --- /dev/null +++ b/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch @@ -0,0 +1,53 @@ +From 4592538bfb0d5d3c3c8a1d7071724d081412ac91 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:46 +0100 +Subject: net: dsa: qca8k: add support for port fast aging + +The switch supports fast aging by flushing any rule in the ARL +table for a specific port. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 11 +++++++++++ + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 12 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1790,6 +1790,16 @@ qca8k_port_bridge_leave(struct dsa_switc + QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); + } + ++static void ++qca8k_port_fast_age(struct dsa_switch *ds, int port) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ mutex_lock(&priv->reg_mutex); ++ qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port); ++ mutex_unlock(&priv->reg_mutex); ++} ++ + static int + qca8k_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phy) +@@ -2005,6 +2015,7 @@ static const struct dsa_switch_ops qca8k + .port_stp_state_set = qca8k_port_stp_state_set, + .port_bridge_join = qca8k_port_bridge_join, + .port_bridge_leave = qca8k_port_bridge_leave, ++ .port_fast_age = qca8k_port_fast_age, + .port_fdb_add = qca8k_port_fdb_add, + .port_fdb_del = qca8k_port_fdb_del, + .port_fdb_dump = qca8k_port_fdb_dump, +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -262,6 +262,7 @@ enum qca8k_fdb_cmd { + QCA8K_FDB_FLUSH = 1, + QCA8K_FDB_LOAD = 2, + QCA8K_FDB_PURGE = 3, ++ QCA8K_FDB_FLUSH_PORT = 5, + QCA8K_FDB_NEXT = 6, + QCA8K_FDB_SEARCH = 7, + }; diff --git a/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch b/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch new file mode 100644 index 0000000000..f32e6ae93a --- /dev/null +++ b/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch @@ -0,0 +1,78 @@ +From 6a3bdc5209f45d2af83aa92433ab6e5cf2297aa4 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:47 +0100 +Subject: net: dsa: qca8k: add set_ageing_time support + +qca8k support setting ageing time in step of 7s. Add support for it and +set the max value accepted of 7645m. +Documentation talks about support for 10000m but that values doesn't +make sense as the value doesn't match the max value in the reg. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 25 +++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 3 +++ + 2 files changed, 28 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1261,6 +1261,10 @@ qca8k_setup(struct dsa_switch *ds) + /* We don't have interrupts for link changes, so we need to poll */ + ds->pcs_poll = true; + ++ /* Set min a max ageing value supported */ ++ ds->ageing_time_min = 7000; ++ ds->ageing_time_max = 458745000; ++ + return 0; + } + +@@ -1801,6 +1805,26 @@ qca8k_port_fast_age(struct dsa_switch *d + } + + static int ++qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ unsigned int secs = msecs / 1000; ++ u32 val; ++ ++ /* AGE_TIME reg is set in 7s step */ ++ val = secs / 7; ++ ++ /* Handle case with 0 as val to NOT disable ++ * learning ++ */ ++ if (!val) ++ val = 1; ++ ++ return regmap_update_bits(priv->regmap, QCA8K_REG_ATU_CTRL, QCA8K_ATU_AGE_TIME_MASK, ++ QCA8K_ATU_AGE_TIME(val)); ++} ++ ++static int + qca8k_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phy) + { +@@ -2006,6 +2030,7 @@ static const struct dsa_switch_ops qca8k + .get_strings = qca8k_get_strings, + .get_ethtool_stats = qca8k_get_ethtool_stats, + .get_sset_count = qca8k_get_sset_count, ++ .set_ageing_time = qca8k_set_ageing_time, + .get_mac_eee = qca8k_get_mac_eee, + .set_mac_eee = qca8k_set_mac_eee, + .port_enable = qca8k_port_enable, +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -175,6 +175,9 @@ + #define QCA8K_VTU_FUNC1_BUSY BIT(31) + #define QCA8K_VTU_FUNC1_VID_MASK GENMASK(27, 16) + #define QCA8K_VTU_FUNC1_FULL BIT(4) ++#define QCA8K_REG_ATU_CTRL 0x618 ++#define QCA8K_ATU_AGE_TIME_MASK GENMASK(15, 0) ++#define QCA8K_ATU_AGE_TIME(x) FIELD_PREP(QCA8K_ATU_AGE_TIME_MASK, (x)) + #define QCA8K_REG_GLOBAL_FW_CTRL0 0x620 + #define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) + #define QCA8K_REG_GLOBAL_FW_CTRL1 0x624 diff --git a/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch b/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch new file mode 100644 index 0000000000..e0daa88c31 --- /dev/null +++ b/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch @@ -0,0 +1,142 @@ +From ba8f870dfa635113ce6e8095a5eb1835ecde2e9e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 22 Nov 2021 16:23:48 +0100 +Subject: net: dsa: qca8k: add support for mdb_add/del + +Add support for mdb add/del function. The ARL table is used to insert +the rule. The rule will be searched, deleted and reinserted with the +port mask updated. The function will check if the rule has to be updated +or insert directly with no deletion of the old rule. +If every port is removed from the port mask, the rule is removed. +The rule is set STATIC in the ARL table (aka it doesn't age) to not be +flushed by fast age function. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 99 insertions(+) + +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -436,6 +436,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv) + } + + static int ++qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, ++ const u8 *mac, u16 vid) ++{ ++ struct qca8k_fdb fdb = { 0 }; ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ ++ qca8k_fdb_write(priv, vid, 0, mac, 0); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1); ++ if (ret < 0) ++ goto exit; ++ ++ ret = qca8k_fdb_read(priv, &fdb); ++ if (ret < 0) ++ goto exit; ++ ++ /* Rule exist. Delete first */ ++ if (!fdb.aging) { ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1); ++ if (ret) ++ goto exit; ++ } ++ ++ /* Add port to fdb portmask */ ++ fdb.port_mask |= port_mask; ++ ++ qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1); ++ ++exit: ++ mutex_unlock(&priv->reg_mutex); ++ return ret; ++} ++ ++static int ++qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask, ++ const u8 *mac, u16 vid) ++{ ++ struct qca8k_fdb fdb = { 0 }; ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ ++ qca8k_fdb_write(priv, vid, 0, mac, 0); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1); ++ if (ret < 0) ++ goto exit; ++ ++ /* Rule doesn't exist. Why delete? */ ++ if (!fdb.aging) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1); ++ if (ret) ++ goto exit; ++ ++ /* Only port in the rule is this port. Don't re insert */ ++ if (fdb.port_mask == port_mask) ++ goto exit; ++ ++ /* Remove port from port mask */ ++ fdb.port_mask &= ~port_mask; ++ ++ qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging); ++ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1); ++ ++exit: ++ mutex_unlock(&priv->reg_mutex); ++ return ret; ++} ++ ++static int + qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) + { + u32 reg; +@@ -1929,6 +2004,28 @@ qca8k_port_fdb_dump(struct dsa_switch *d + return 0; + } + ++static void ++qca8k_port_mdb_add(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_mdb *mdb) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ const u8 *addr = mdb->addr; ++ u16 vid = mdb->vid; ++ ++ qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid); ++} ++ ++static int ++qca8k_port_mdb_del(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_mdb *mdb) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ const u8 *addr = mdb->addr; ++ u16 vid = mdb->vid; ++ ++ return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid); ++} ++ + static int + qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, + struct switchdev_trans *trans) +@@ -2044,6 +2141,8 @@ static const struct dsa_switch_ops qca8k + .port_fdb_add = qca8k_port_fdb_add, + .port_fdb_del = qca8k_port_fdb_del, + .port_fdb_dump = qca8k_port_fdb_dump, ++ .port_mdb_add = qca8k_port_mdb_add, ++ .port_mdb_del = qca8k_port_mdb_del, + .port_vlan_filtering = qca8k_port_vlan_filtering, + .port_vlan_prepare = qca8k_port_vlan_prepare, + .port_vlan_add = qca8k_port_vlan_add, diff --git a/target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch b/target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch new file mode 100644 index 0000000000..eb487cdfb5 --- /dev/null +++ b/target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch @@ -0,0 +1,112 @@ +From 9470174e7581e75a8ebd78964997314dfc2e706c Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Tue, 3 Nov 2020 13:06:18 +0800 +Subject: [PATCH] net: dsa: mt7530: support setting MTU + +MT7530/7531 has a global RX packet length register, which can be used +to set MTU. + +Supported packet length values are 1522 (1518 if untagged), 1536, +1552, and multiple of 1024 (from 2048 to 15360). + +Signed-off-by: DENG Qingfang +Link: https://lore.kernel.org/r/20201103050618.11419-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 12 ++++++++++ + 2 files changed, 61 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1015,6 +1015,53 @@ mt7530_port_disable(struct dsa_switch *d + mutex_unlock(&priv->reg_mutex); + } + ++static int ++mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct mii_bus *bus = priv->bus; ++ int length; ++ u32 val; ++ ++ /* When a new MTU is set, DSA always set the CPU port's MTU to the ++ * largest MTU of the slave ports. Because the switch only has a global ++ * RX length register, only allowing CPU port here is enough. ++ */ ++ if (!dsa_is_cpu_port(ds, port)) ++ return 0; ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ val = mt7530_mii_read(priv, MT7530_GMACCR); ++ val &= ~MAX_RX_PKT_LEN_MASK; ++ ++ /* RX length also includes Ethernet header, MTK tag, and FCS length */ ++ length = new_mtu + ETH_HLEN + MTK_HDR_LEN + ETH_FCS_LEN; ++ if (length <= 1522) { ++ val |= MAX_RX_PKT_LEN_1522; ++ } else if (length <= 1536) { ++ val |= MAX_RX_PKT_LEN_1536; ++ } else if (length <= 1552) { ++ val |= MAX_RX_PKT_LEN_1552; ++ } else { ++ val &= ~MAX_RX_JUMBO_MASK; ++ val |= MAX_RX_JUMBO(DIV_ROUND_UP(length, 1024)); ++ val |= MAX_RX_PKT_LEN_JUMBO; ++ } ++ ++ mt7530_mii_write(priv, MT7530_GMACCR, val); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ return 0; ++} ++ ++static int ++mt7530_port_max_mtu(struct dsa_switch *ds, int port) ++{ ++ return MT7530_MAX_MTU; ++} ++ + static void + mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state) + { +@@ -2652,6 +2699,8 @@ static const struct dsa_switch_ops mt753 + .get_sset_count = mt7530_get_sset_count, + .port_enable = mt7530_port_enable, + .port_disable = mt7530_port_disable, ++ .port_change_mtu = mt7530_port_change_mtu, ++ .port_max_mtu = mt7530_port_max_mtu, + .port_stp_state_set = mt7530_stp_state_set, + .port_bridge_join = mt7530_port_bridge_join, + .port_bridge_leave = mt7530_port_bridge_leave, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -11,6 +11,9 @@ + #define MT7530_NUM_FDB_RECORDS 2048 + #define MT7530_ALL_MEMBERS 0xff + ++#define MTK_HDR_LEN 4 ++#define MT7530_MAX_MTU (15 * 1024 - ETH_HLEN - ETH_FCS_LEN - MTK_HDR_LEN) ++ + enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, +@@ -301,6 +304,15 @@ enum mt7530_vlan_port_attr { + #define MT7531_DBG_CNT(x) (0x3018 + (x) * 0x100) + #define MT7531_DIS_CLR BIT(31) + ++#define MT7530_GMACCR 0x30e0 ++#define MAX_RX_JUMBO(x) ((x) << 2) ++#define MAX_RX_JUMBO_MASK GENMASK(5, 2) ++#define MAX_RX_PKT_LEN_MASK GENMASK(1, 0) ++#define MAX_RX_PKT_LEN_1522 0x0 ++#define MAX_RX_PKT_LEN_1536 0x1 ++#define MAX_RX_PKT_LEN_1552 0x2 ++#define MAX_RX_PKT_LEN_JUMBO 0x3 ++ + /* Register for MIB */ + #define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100) + #define MT7530_MIB_CCR 0x4fe0 diff --git a/target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch b/target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch new file mode 100644 index 0000000000..b0ad7b9f87 --- /dev/null +++ b/target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch @@ -0,0 +1,36 @@ +From 771c8901568dd8776a260aa93db41be88a60389e Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Fri, 11 Dec 2020 01:03:22 +0800 +Subject: [PATCH] net: dsa: mt7530: enable MTU normalization + +MT7530 has a global RX length register, so we are actually changing its +MRU. +Enable MTU normalization for this reason. + +Signed-off-by: DENG Qingfang +Acked-by: Landen Chao +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20201210170322.3433-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1703,6 +1703,7 @@ mt7530_setup(struct dsa_switch *ds) + */ + dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent; + ds->configure_vlan_while_not_filtering = true; ++ ds->mtu_enforcement_ingress = true; + + if (priv->id == ID_MT7530) { + regulator_set_voltage(priv->core_pwr, 1000000, 1000000); +@@ -1947,6 +1948,7 @@ mt7531_setup(struct dsa_switch *ds) + } + + ds->configure_vlan_while_not_filtering = true; ++ ds->mtu_enforcement_ingress = true; + + /* Flush the FDB table */ + ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); diff --git a/target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch b/target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch new file mode 100644 index 0000000000..44fa40eabe --- /dev/null +++ b/target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch @@ -0,0 +1,99 @@ +From ea6d5c924e391872d402acac38461a5f8261e57f Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Tue, 8 Dec 2020 15:00:28 +0800 +Subject: [PATCH] net: dsa: mt7530: support setting ageing time + +MT7530 has a global address age control register, so use it to set +ageing time. + +The applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds + +Signed-off-by: DENG Qingfang +Reviewed-by: Andrew Lunn +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 41 ++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 13 +++++++++++++ + 2 files changed, 54 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -870,6 +870,46 @@ mt7530_get_sset_count(struct dsa_switch + return ARRAY_SIZE(mt7530_mib); + } + ++static int ++mt7530_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ unsigned int secs = msecs / 1000; ++ unsigned int tmp_age_count; ++ unsigned int error = -1; ++ unsigned int age_count; ++ unsigned int age_unit; ++ ++ /* Applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds */ ++ if (secs < 1 || secs > (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1)) ++ return -ERANGE; ++ ++ /* iterate through all possible age_count to find the closest pair */ ++ for (tmp_age_count = 0; tmp_age_count <= AGE_CNT_MAX; ++tmp_age_count) { ++ unsigned int tmp_age_unit = secs / (tmp_age_count + 1) - 1; ++ ++ if (tmp_age_unit <= AGE_UNIT_MAX) { ++ unsigned int tmp_error = secs - ++ (tmp_age_count + 1) * (tmp_age_unit + 1); ++ ++ /* found a closer pair */ ++ if (error > tmp_error) { ++ error = tmp_error; ++ age_count = tmp_age_count; ++ age_unit = tmp_age_unit; ++ } ++ ++ /* found the exact match, so break the loop */ ++ if (!error) ++ break; ++ } ++ } ++ ++ mt7530_write(priv, MT7530_AAC, AGE_CNT(age_count) | AGE_UNIT(age_unit)); ++ ++ return 0; ++} ++ + static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) + { + struct mt7530_priv *priv = ds->priv; +@@ -2699,6 +2739,7 @@ static const struct dsa_switch_ops mt753 + .phy_write = mt753x_phy_write, + .get_ethtool_stats = mt7530_get_ethtool_stats, + .get_sset_count = mt7530_get_sset_count, ++ .set_ageing_time = mt7530_set_ageing_time, + .port_enable = mt7530_port_enable, + .port_disable = mt7530_port_disable, + .port_change_mtu = mt7530_port_change_mtu, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -161,6 +161,19 @@ enum mt7530_vlan_egress_attr { + MT7530_VLAN_EGRESS_STACK = 3, + }; + ++/* Register for address age control */ ++#define MT7530_AAC 0xa0 ++/* Disable ageing */ ++#define AGE_DIS BIT(20) ++/* Age count */ ++#define AGE_CNT_MASK GENMASK(19, 12) ++#define AGE_CNT_MAX 0xff ++#define AGE_CNT(x) (AGE_CNT_MASK & ((x) << 12)) ++/* Age unit */ ++#define AGE_UNIT_MASK GENMASK(11, 0) ++#define AGE_UNIT_MAX 0xfff ++#define AGE_UNIT(x) (AGE_UNIT_MASK & (x)) ++ + /* Register for port STP state control */ + #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) + #define FID_PST(x) ((x) & 0x3) diff --git a/target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch b/target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch new file mode 100644 index 0000000000..a0bb7fa888 --- /dev/null +++ b/target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch @@ -0,0 +1,65 @@ +From ba2203f36b981235556504fb7b62baee28512a40 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Tue, 24 Aug 2021 11:37:50 +0800 +Subject: [PATCH] net: dsa: mt7530: disable learning on standalone ports + +This is a partial backport of commit 5a30833b9a16f8d1aa15de06636f9317ca51f9df +("net: dsa: mt7530: support MDB and bridge flag operations") upstream. + +Make sure that the standalone ports start up with learning disabled. + +Signed-off-by: DENG Qingfang +--- + drivers/net/dsa/mt7530.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1163,6 +1163,8 @@ mt7530_port_bridge_join(struct dsa_switc + PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap)); + priv->ports[port].pm |= PCR_MATRIX(port_bitmap); + ++ mt7530_clear(priv, MT7530_PSC_P(port), SA_DIS); ++ + mutex_unlock(&priv->reg_mutex); + + return 0; +@@ -1260,6 +1262,8 @@ mt7530_port_bridge_leave(struct dsa_swit + PCR_MATRIX(BIT(MT7530_CPU_PORT))); + priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); + ++ mt7530_set(priv, MT7530_PSC_P(port), SA_DIS); ++ + mutex_unlock(&priv->reg_mutex); + } + +@@ -1817,9 +1821,13 @@ mt7530_setup(struct dsa_switch *ds) + ret = mt753x_cpu_port_enable(ds, i); + if (ret) + return ret; +- } else ++ } else { + mt7530_port_disable(ds, i); + ++ /* Disable learning by default on all user ports */ ++ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); ++ } ++ + /* Enable consistent egress tag */ + mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); +@@ -1979,9 +1987,13 @@ mt7531_setup(struct dsa_switch *ds) + ret = mt753x_cpu_port_enable(ds, i); + if (ret) + return ret; +- } else ++ } else { + mt7530_port_disable(ds, i); + ++ /* Disable learning by default on all user ports */ ++ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); ++ } ++ + /* Enable consistent egress tag */ + mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); diff --git a/target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch b/target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch new file mode 100644 index 0000000000..f376ff949a --- /dev/null +++ b/target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch @@ -0,0 +1,102 @@ +From 59c8adbc8e2c7f6b46385f36962eadaad3ea2daa Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Wed, 4 Aug 2021 00:04:01 +0800 +Subject: [PATCH] net: dsa: mt7530: enable assisted learning on CPU port + +Consider the following bridge configuration, where bond0 is not +offloaded: + + +-- br0 --+ + / / | \ + / / | \ + / | | bond0 + / | | / \ + swp0 swp1 swp2 swp3 swp4 + . . . + . . . + A B C + +Address learning is enabled on offloaded ports (swp0~2) and the CPU +port, so when client A sends a packet to C, the following will happen: + +1. The switch learns that client A can be reached at swp0. +2. The switch probably already knows that client C can be reached at the + CPU port, so it forwards the packet to the CPU. +3. The bridge core knows client C can be reached at bond0, so it + forwards the packet back to the switch. +4. The switch learns that client A can be reached at the CPU port. +5. The switch forwards the packet to either swp3 or swp4, according to + the packet's tag. + +That makes client A's MAC address flap between swp0 and the CPU port. If +client B sends a packet to A, it is possible that the packet is +forwarded to the CPU. With offload_fwd_mark = 1, the bridge core won't +forward it back to the switch, resulting in packet loss. + +As we have the assisted_learning_on_cpu_port in DSA core now, enable +that and disable hardware learning on the CPU port. + +Signed-off-by: DENG Qingfang +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1747,6 +1747,7 @@ mt7530_setup(struct dsa_switch *ds) + */ + dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent; + ds->configure_vlan_while_not_filtering = true; ++ ds->assisted_learning_on_cpu_port = true; + ds->mtu_enforcement_ingress = true; + + if (priv->id == ID_MT7530) { +@@ -1817,15 +1818,15 @@ mt7530_setup(struct dsa_switch *ds) + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, + PCR_MATRIX_CLR); + ++ /* Disable learning by default on all ports */ ++ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); ++ + if (dsa_is_cpu_port(ds, i)) { + ret = mt753x_cpu_port_enable(ds, i); + if (ret) + return ret; + } else { + mt7530_port_disable(ds, i); +- +- /* Disable learning by default on all user ports */ +- mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); + } + + /* Enable consistent egress tag */ +@@ -1981,6 +1982,9 @@ mt7531_setup(struct dsa_switch *ds) + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, + PCR_MATRIX_CLR); + ++ /* Disable learning by default on all ports */ ++ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); ++ + mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); + + if (dsa_is_cpu_port(ds, i)) { +@@ -1989,9 +1993,6 @@ mt7531_setup(struct dsa_switch *ds) + return ret; + } else { + mt7530_port_disable(ds, i); +- +- /* Disable learning by default on all user ports */ +- mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); + } + + /* Enable consistent egress tag */ +@@ -2000,6 +2001,7 @@ mt7531_setup(struct dsa_switch *ds) + } + + ds->configure_vlan_while_not_filtering = true; ++ ds->assisted_learning_on_cpu_port = true; + ds->mtu_enforcement_ingress = true; + + /* Flush the FDB table */ diff --git a/target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch b/target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch new file mode 100644 index 0000000000..f9fe0ef858 --- /dev/null +++ b/target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch @@ -0,0 +1,262 @@ +From e3a402764c5753698e7a9e45d4d21f093faa7852 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Wed, 4 Aug 2021 00:04:02 +0800 +Subject: [PATCH] net: dsa: mt7530: use independent VLAN learning on + VLAN-unaware bridges + +Consider the following bridge configuration, where bond0 is not +offloaded: + + +-- br0 --+ + / / | \ + / / | \ + / | | bond0 + / | | / \ + swp0 swp1 swp2 swp3 swp4 + . . . + . . . + A B C + +Ideally, when the switch receives a packet from swp3 or swp4, it should +forward the packet to the CPU, according to the port matrix and unknown +unicast flood settings. + +But packet loss will happen if the destination address is at one of the +offloaded ports (swp0~2). For example, when client C sends a packet to +A, the FDB lookup will indicate that it should be forwarded to swp0, but +the port matrix of swp3 and swp4 is configured to only allow the CPU to +be its destination, so it is dropped. + +However, this issue does not happen if the bridge is VLAN-aware. That is +because VLAN-aware bridges use independent VLAN learning, i.e. use VID +for FDB lookup, on offloaded ports. As swp3 and swp4 are not offloaded, +shared VLAN learning with default filter ID of 0 is used instead. So the +lookup for A with filter ID 0 never hits and the packet can be forwarded +to the CPU. + +In the current code, only two combinations were used to toggle user +ports' VLAN awareness: one is PCR.PORT_VLAN set to port matrix mode with +PVC.VLAN_ATTR set to transparent port, the other is PCR.PORT_VLAN set to +security mode with PVC.VLAN_ATTR set to user port. + +It turns out that only PVC.VLAN_ATTR contributes to VLAN awareness, and +port matrix mode just skips the VLAN table lookup. The reference manual +is somehow misleading when describing PORT_VLAN modes. It states that +PORT_MEM (VLAN port member) is used for destination if the VLAN table +lookup hits, but actually **PORT_MEM & PORT_MATRIX** (bitwise AND of +VLAN port member and port matrix) is used instead, which means we can +have two or more separate VLAN-aware bridges with the same PVID and +traffic won't leak between them. + +Therefore, to solve this, enable independent VLAN learning with PVID 0 +on VLAN-unaware bridges, by setting their PCR.PORT_VLAN to fallback +mode, while leaving standalone ports in port matrix mode. The CPU port +is always set to fallback mode to serve those bridges. + +During testing, it is found that FDB lookup with filter ID of 0 will +also hit entries with VID 0 even with independent VLAN learning. To +avoid that, install all VLANs with filter ID of 1. + +Signed-off-by: DENG Qingfang +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 72 +++++++++++++++++++++++++++++----------- + drivers/net/dsa/mt7530.h | 9 ++++- + 2 files changed, 60 insertions(+), 21 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1011,6 +1011,10 @@ mt753x_cpu_port_enable(struct dsa_switch + mt7530_write(priv, MT7530_PCR_P(port), + PCR_MATRIX(dsa_user_ports(priv->ds))); + ++ /* Set to fallback mode for independent VLAN learning */ ++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, ++ MT7530_PORT_FALLBACK_MODE); ++ + return 0; + } + +@@ -1165,6 +1169,10 @@ mt7530_port_bridge_join(struct dsa_switc + + mt7530_clear(priv, MT7530_PSC_P(port), SA_DIS); + ++ /* Set to fallback mode for independent VLAN learning */ ++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, ++ MT7530_PORT_FALLBACK_MODE); ++ + mutex_unlock(&priv->reg_mutex); + + return 0; +@@ -1177,16 +1185,21 @@ mt7530_port_set_vlan_unaware(struct dsa_ + bool all_user_ports_removed = true; + int i; + +- /* When a port is removed from the bridge, the port would be set up +- * back to the default as is at initial boot which is a VLAN-unaware +- * port. ++ /* This is called after .port_bridge_leave when leaving a VLAN-aware ++ * bridge. Don't set standalone ports to fallback mode. + */ +- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, +- MT7530_PORT_MATRIX_MODE); ++ if (dsa_to_port(ds, port)->bridge_dev) ++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, ++ MT7530_PORT_FALLBACK_MODE); ++ + mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK, + VLAN_ATTR(MT7530_VLAN_TRANSPARENT) | + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); + ++ /* Set PVID to 0 */ ++ mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, ++ G0_PORT_VID_DEF); ++ + for (i = 0; i < MT7530_NUM_PORTS; i++) { + if (dsa_is_user_port(ds, i) && + dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) { +@@ -1212,15 +1225,14 @@ mt7530_port_set_vlan_aware(struct dsa_sw + struct mt7530_priv *priv = ds->priv; + + /* Trapped into security mode allows packet forwarding through VLAN +- * table lookup. CPU port is set to fallback mode to let untagged +- * frames pass through. ++ * table lookup. + */ +- if (dsa_is_cpu_port(ds, port)) +- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, +- MT7530_PORT_FALLBACK_MODE); +- else ++ if (dsa_is_user_port(ds, port)) { + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, + MT7530_PORT_SECURITY_MODE); ++ mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, ++ G0_PORT_VID(priv->ports[port].pvid)); ++ } + + /* Set the port as a user port which is to be able to recognize VID + * from incoming packets before fetching entry within the VLAN table. +@@ -1264,6 +1276,13 @@ mt7530_port_bridge_leave(struct dsa_swit + + mt7530_set(priv, MT7530_PSC_P(port), SA_DIS); + ++ /* When a port is removed from the bridge, the port would be set up ++ * back to the default as is at initial boot which is a VLAN-unaware ++ * port. ++ */ ++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, ++ MT7530_PORT_MATRIX_MODE); ++ + mutex_unlock(&priv->reg_mutex); + } + +@@ -1406,7 +1425,8 @@ mt7530_hw_vlan_add(struct mt7530_priv *p + /* Validate the entry with independent learning, create egress tag per + * VLAN and joining the port as one of the port members. + */ +- val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID; ++ val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | FID(FID_BRIDGED) | ++ VLAN_VALID; + mt7530_write(priv, MT7530_VAWD1, val); + + /* Decide whether adding tag or not for those outgoing packets from the +@@ -1499,9 +1519,13 @@ mt7530_port_vlan_add(struct dsa_switch * + } + + if (pvid) { +- mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, +- G0_PORT_VID(vlan->vid_end)); + priv->ports[port].pvid = vlan->vid_end; ++ ++ /* Only configure PVID if VLAN filtering is enabled */ ++ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) ++ mt7530_rmw(priv, MT7530_PPBV1_P(port), ++ G0_PORT_VID_MASK, ++ G0_PORT_VID(vlan->vid_end)); + } + + mutex_unlock(&priv->reg_mutex); +@@ -1513,11 +1537,10 @@ mt7530_port_vlan_del(struct dsa_switch * + { + struct mt7530_hw_vlan_entry target_entry; + struct mt7530_priv *priv = ds->priv; +- u16 vid, pvid; ++ u16 vid; + + mutex_lock(&priv->reg_mutex); + +- pvid = priv->ports[port].pvid; + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + mt7530_hw_vlan_entry_init(&target_entry, port, 0); + mt7530_hw_vlan_update(priv, vid, &target_entry, +@@ -1526,12 +1549,13 @@ mt7530_port_vlan_del(struct dsa_switch * + /* PVID is being restored to the default whenever the PVID port + * is being removed from the VLAN. + */ +- if (pvid == vid) +- pvid = G0_PORT_VID_DEF; ++ if (priv->ports[port].pvid == vid) { ++ priv->ports[port].pvid = G0_PORT_VID_DEF; ++ mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, ++ G0_PORT_VID_DEF); ++ } + } + +- mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, pvid); +- priv->ports[port].pvid = pvid; + + mutex_unlock(&priv->reg_mutex); + +@@ -1827,6 +1851,10 @@ mt7530_setup(struct dsa_switch *ds) + return ret; + } else { + mt7530_port_disable(ds, i); ++ ++ /* Set default PVID to 0 on all user ports */ ++ mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK, ++ G0_PORT_VID_DEF); + } + + /* Enable consistent egress tag */ +@@ -1993,6 +2021,10 @@ mt7531_setup(struct dsa_switch *ds) + return ret; + } else { + mt7530_port_disable(ds, i); ++ ++ /* Set default PVID to 0 on all user ports */ ++ mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK, ++ G0_PORT_VID_DEF); + } + + /* Enable consistent egress tag */ +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -145,11 +145,18 @@ enum mt7530_vlan_cmd { + #define VTAG_EN BIT(28) + /* VLAN Member Control */ + #define PORT_MEM(x) (((x) & 0xff) << 16) ++/* Filter ID */ ++#define FID(x) (((x) & 0x7) << 1) + /* VLAN Entry Valid */ + #define VLAN_VALID BIT(0) + #define PORT_MEM_SHFT 16 + #define PORT_MEM_MASK 0xff + ++enum mt7530_fid { ++ FID_STANDALONE = 0, ++ FID_BRIDGED = 1, ++}; ++ + #define MT7530_VAWD2 0x98 + /* Egress Tag Control */ + #define ETAG_CTRL_P(p, x) (((x) & 0x3) << ((p) << 1)) +@@ -244,7 +251,7 @@ enum mt7530_vlan_port_attr { + #define MT7530_PPBV1_P(x) (0x2014 + ((x) * 0x100)) + #define G0_PORT_VID(x) (((x) & 0xfff) << 0) + #define G0_PORT_VID_MASK G0_PORT_VID(0xfff) +-#define G0_PORT_VID_DEF G0_PORT_VID(1) ++#define G0_PORT_VID_DEF G0_PORT_VID(0) + + /* Register for port MAC control register */ + #define MT7530_PMCR_P(x) (0x3000 + ((x) * 0x100)) diff --git a/target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch b/target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch new file mode 100644 index 0000000000..2c1958bd43 --- /dev/null +++ b/target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch @@ -0,0 +1,40 @@ +From c5ffcefcb40420528d04c63e7dfc88f2845c9831 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Wed, 4 Aug 2021 00:04:03 +0800 +Subject: [PATCH] net: dsa: mt7530: set STP state on filter ID 1 + +As filter ID 1 is the only one used for bridges, set STP state on it. + +Signed-off-by: DENG Qingfang +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 3 ++- + drivers/net/dsa/mt7530.h | 4 ++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1131,7 +1131,8 @@ mt7530_stp_state_set(struct dsa_switch * + break; + } + +- mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK, stp_state); ++ mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK(FID_BRIDGED), ++ FID_PST(FID_BRIDGED, stp_state)); + } + + static int +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -183,8 +183,8 @@ enum mt7530_vlan_egress_attr { + + /* Register for port STP state control */ + #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) +-#define FID_PST(x) ((x) & 0x3) +-#define FID_PST_MASK FID_PST(0x3) ++#define FID_PST(fid, state) (((state) & 0x3) << ((fid) * 2)) ++#define FID_PST_MASK(fid) FID_PST(fid, 0x3) + + enum mt7530_stp_state { + MT7530_STP_DISABLED = 0, diff --git a/target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch b/target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch new file mode 100644 index 0000000000..97824068f0 --- /dev/null +++ b/target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch @@ -0,0 +1,54 @@ +From 138c126a33f7564edb66b1da5b847e4a60740bfc Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Wed, 4 Aug 2021 00:04:04 +0800 +Subject: [PATCH] net: dsa: mt7530: always install FDB entries with IVL and FID + 1 + +This reverts commit 7e777021780e ("mt7530 mt7530_fdb_write only set ivl +bit vid larger than 1"). + +Before this series, the default value of all ports' PVID is 1, which is +copied into the FDB entry, even if the ports are VLAN unaware. So +`bridge fdb show` will show entries like `dev swp0 vlan 1 self` even on +a VLAN-unaware bridge. + +The blamed commit does not solve that issue completely, instead it may +cause a new issue that FDB is inaccessible in a VLAN-aware bridge with +PVID 1. + +This series sets PVID to 0 on VLAN-unaware ports, so `bridge fdb show` +will no longer print `vlan 1` on VLAN-unaware bridges, and that special +case in fdb_write is not required anymore. + +Set FDB entries' filter ID to 1 to match the VLAN table. + +Signed-off-by: DENG Qingfang +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 2 ++ + drivers/net/dsa/mt7530.h | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -361,6 +361,8 @@ mt7530_fdb_write(struct mt7530_priv *pri + int i; + + reg[1] |= vid & CVID_MASK; ++ reg[1] |= ATA2_IVL; ++ reg[1] |= ATA2_FID(FID_BRIDGED); + reg[2] |= (aging & AGE_TIMER_MASK) << AGE_TIMER; + reg[2] |= (port_mask & PORT_MAP_MASK) << PORT_MAP; + /* STATIC_ENT indicate that entry is static wouldn't +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -77,6 +77,8 @@ enum mt753x_bpdu_port_fw { + #define STATIC_EMP 0 + #define STATIC_ENT 3 + #define MT7530_ATA2 0x78 ++#define ATA2_IVL BIT(15) ++#define ATA2_FID(x) (((x) & 0x7) << 12) + + /* Register for address table write data */ + #define MT7530_ATWD 0x7c diff --git a/target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch b/target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch new file mode 100644 index 0000000000..5d91d5a657 --- /dev/null +++ b/target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch @@ -0,0 +1,171 @@ +From 1f11a07a33bc26997c18b633d63f088bf75d11f2 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Tue, 24 Aug 2021 11:37:50 +0800 +Subject: [PATCH] net: dsa: mt7530: support MDB operations + +This is a partial backport of commit 5a30833b9a16f8d1aa15de06636f9317ca51f9df +("net: dsa: mt7530: support MDB and bridge flag operations") upstream. + +Signed-off-by: DENG Qingfang +--- + drivers/net/dsa/mt7530.c | 78 ++++++++++++++++++++++++++++++++++++++-- + net/dsa/tag_mtk.c | 14 +------- + 2 files changed, 76 insertions(+), 16 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1000,9 +1000,6 @@ mt753x_cpu_port_enable(struct dsa_switch + mt7530_write(priv, MT7530_PVC_P(port), + PORT_SPEC_TAG); + +- /* Unknown multicast frame forwarding to the cpu port */ +- mt7530_rmw(priv, MT7530_MFC, UNM_FFP_MASK, UNM_FFP(BIT(port))); +- + /* Set CPU port number */ + if (priv->id == ID_MT7621) + mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); +@@ -1138,6 +1135,20 @@ mt7530_stp_state_set(struct dsa_switch * + } + + static int ++mt7530_port_egress_floods(struct dsa_switch *ds, int port, ++ bool unicast, bool multicast) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ mt7530_rmw(priv, MT7530_MFC, ++ UNU_FFP(BIT(port)) | UNM_FFP(BIT(port)), ++ (unicast ? UNU_FFP(BIT(port)) : 0) | ++ (multicast ? UNM_FFP(BIT(port)) : 0)); ++ ++ return 0; ++} ++ ++static int + mt7530_port_bridge_join(struct dsa_switch *ds, int port, + struct net_device *bridge) + { +@@ -1357,6 +1368,63 @@ err: + } + + static int ++mt7530_port_mdb_prepare(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_mdb *mdb) ++{ ++ return 0; ++} ++ ++static void ++mt7530_port_mdb_add(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_mdb *mdb) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ const u8 *addr = mdb->addr; ++ u16 vid = mdb->vid; ++ u8 port_mask = 0; ++ ++ mutex_lock(&priv->reg_mutex); ++ ++ mt7530_fdb_write(priv, vid, 0, addr, 0, STATIC_EMP); ++ if (!mt7530_fdb_cmd(priv, MT7530_FDB_READ, NULL)) ++ port_mask = (mt7530_read(priv, MT7530_ATRD) >> PORT_MAP) ++ & PORT_MAP_MASK; ++ ++ port_mask |= BIT(port); ++ mt7530_fdb_write(priv, vid, port_mask, addr, -1, STATIC_ENT); ++ mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, NULL); ++ ++ mutex_unlock(&priv->reg_mutex); ++} ++ ++static int ++mt7530_port_mdb_del(struct dsa_switch *ds, int port, ++ const struct switchdev_obj_port_mdb *mdb) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ const u8 *addr = mdb->addr; ++ u16 vid = mdb->vid; ++ u8 port_mask = 0; ++ int ret; ++ ++ mutex_lock(&priv->reg_mutex); ++ ++ mt7530_fdb_write(priv, vid, 0, addr, 0, STATIC_EMP); ++ if (!mt7530_fdb_cmd(priv, MT7530_FDB_READ, NULL)) ++ port_mask = (mt7530_read(priv, MT7530_ATRD) >> PORT_MAP) ++ & PORT_MAP_MASK; ++ ++ port_mask &= ~BIT(port); ++ mt7530_fdb_write(priv, vid, port_mask, addr, -1, ++ port_mask ? STATIC_ENT : STATIC_EMP); ++ ret = mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, NULL); ++ ++ mutex_unlock(&priv->reg_mutex); ++ ++ return ret; ++} ++ ++static int + mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid) + { + struct mt7530_dummy_poll p; +@@ -2794,11 +2862,15 @@ static const struct dsa_switch_ops mt753 + .port_change_mtu = mt7530_port_change_mtu, + .port_max_mtu = mt7530_port_max_mtu, + .port_stp_state_set = mt7530_stp_state_set, ++ .port_egress_floods = mt7530_port_egress_floods, + .port_bridge_join = mt7530_port_bridge_join, + .port_bridge_leave = mt7530_port_bridge_leave, + .port_fdb_add = mt7530_port_fdb_add, + .port_fdb_del = mt7530_port_fdb_del, + .port_fdb_dump = mt7530_port_fdb_dump, ++ .port_mdb_prepare = mt7530_port_mdb_prepare, ++ .port_mdb_add = mt7530_port_mdb_add, ++ .port_mdb_del = mt7530_port_mdb_del, + .port_vlan_filtering = mt7530_port_vlan_filtering, + .port_vlan_prepare = mt7530_port_vlan_prepare, + .port_vlan_add = mt7530_port_vlan_add, +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -24,9 +24,6 @@ static struct sk_buff *mtk_tag_xmit(stru + struct dsa_port *dp = dsa_slave_to_port(dev); + u8 xmit_tpid; + u8 *mtk_tag; +- unsigned char *dest = eth_hdr(skb)->h_dest; +- bool is_multicast_skb = is_multicast_ether_addr(dest) && +- !is_broadcast_ether_addr(dest); + + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is +@@ -55,10 +52,6 @@ static struct sk_buff *mtk_tag_xmit(stru + mtk_tag[0] = xmit_tpid; + mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; + +- /* Disable SA learning for multicast frames */ +- if (unlikely(is_multicast_skb)) +- mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS; +- + /* Tag control information is kept for 802.1Q */ + if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) { + mtk_tag[2] = 0; +@@ -74,9 +67,6 @@ static struct sk_buff *mtk_tag_rcv(struc + u16 hdr; + int port; + __be16 *phdr; +- unsigned char *dest = eth_hdr(skb)->h_dest; +- bool is_multicast_skb = is_multicast_ether_addr(dest) && +- !is_broadcast_ether_addr(dest); + + if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) + return NULL; +@@ -102,9 +92,7 @@ static struct sk_buff *mtk_tag_rcv(struc + if (!skb->dev) + return NULL; + +- /* Only unicast or broadcast frames are offloaded */ +- if (likely(!is_multicast_skb)) +- dsa_default_offload_fwd_mark(skb); ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } diff --git a/target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch b/target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch new file mode 100644 index 0000000000..67e3ca91ed --- /dev/null +++ b/target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch @@ -0,0 +1,159 @@ +From e40d2cca01893c1941f5959b14bb0cd0d4f4d099 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Wed, 19 May 2021 11:31:59 +0800 +Subject: [PATCH] net: phy: add MediaTek Gigabit Ethernet PHY driver + +Add support for MediaTek Gigabit Ethernet PHYs found in MT7530 and +MT7531 switches. +The initialization procedure is from the vendor driver, but due to lack +of documentation, the function of some register values remains unknown. + +Signed-off-by: DENG Qingfang +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 5 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mediatek-ge.c | 116 ++++++++++++++++++++++++++++++++++ + 3 files changed, 122 insertions(+) + create mode 100644 drivers/net/phy/mediatek-ge.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -201,6 +201,11 @@ config MARVELL_10G_PHY + help + Support for the Marvell Alaska MV88X3310 and compatible PHYs. + ++config MEDIATEK_GE_PHY ++ tristate "MediaTek PHYs" ++ help ++ Supports the MediaTek switch integrated PHYs. ++ + config MICREL_PHY + tristate "Micrel PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c + obj-$(CONFIG_LXT_PHY) += lxt.o + obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o + obj-$(CONFIG_MARVELL_PHY) += marvell.o ++obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o + obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o + obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o + obj-$(CONFIG_MICREL_PHY) += micrel.o +--- /dev/null ++++ b/drivers/net/phy/mediatek-ge.c +@@ -0,0 +1,113 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++#include ++#include ++#include ++ ++#define MTK_T10_TEST_CONTROL 0x145 ++#define MTK_PHY_TP_MASK GENMASK(4, 3) ++#define MTK_PHY_TP_AUTO 0 ++#define MTK_PHY_TP_MDI 2 ++#define MTK_PHY_TP_MDIX 3 ++ ++#define MTK_EXT_PAGE_ACCESS 0x1f ++#define MTK_PHY_PAGE_STANDARD 0x0000 ++#define MTK_PHY_PAGE_EXTENDED 0x0001 ++#define MTK_PHY_PAGE_EXTENDED_2 0x0002 ++#define MTK_PHY_PAGE_EXTENDED_3 0x0003 ++#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 ++#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 ++ ++static int mtk_gephy_read_page(struct phy_device *phydev) ++{ ++ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); ++} ++ ++static int mtk_gephy_write_page(struct phy_device *phydev, int page) ++{ ++ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); ++} ++ ++static void mtk_gephy_config_init(struct phy_device *phydev) ++{ ++ /* Disable EEE */ ++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); ++ ++ /* Enable HW auto downshift */ ++ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4)); ++ ++ /* Increase SlvDPSready time */ ++ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); ++ __phy_write(phydev, 0x10, 0xafae); ++ __phy_write(phydev, 0x12, 0x2f); ++ __phy_write(phydev, 0x10, 0x8fae); ++ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); ++ ++ /* Adjust 100_mse_threshold */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff); ++ ++ /* Disable mcc */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300); ++} ++ ++static int mt7530_phy_config_init(struct phy_device *phydev) ++{ ++ mtk_gephy_config_init(phydev); ++ ++ /* Increase post_update_timer */ ++ phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b); ++ ++ return 0; ++} ++ ++static int mt7531_phy_config_init(struct phy_device *phydev) ++{ ++ mtk_gephy_config_init(phydev); ++ ++ /* PHY link down power saving enable */ ++ phy_set_bits(phydev, 0x17, BIT(4)); ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300); ++ ++ /* Set TX Pair delay selection */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404); ++ ++ return 0; ++} ++ ++static struct phy_driver mtk_gephy_driver[] = { ++ { ++ PHY_ID_MATCH_EXACT(0x03a29412), ++ .name = "MediaTek MT7530 PHY", ++ .config_init = mt7530_phy_config_init, ++ /* Interrupts are handled by the switch, not the PHY ++ * itself. ++ */ ++ .config_intr = genphy_no_config_intr, ++ .ack_interrupt = genphy_no_ack_interrupt, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = mtk_gephy_read_page, ++ .write_page = mtk_gephy_write_page, ++ }, ++ { ++ PHY_ID_MATCH_EXACT(0x03a29441), ++ .name = "MediaTek MT7531 PHY", ++ .config_init = mt7531_phy_config_init, ++ /* Interrupts are handled by the switch, not the PHY ++ * itself. ++ */ ++ .config_intr = genphy_no_config_intr, ++ .ack_interrupt = genphy_no_ack_interrupt, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = mtk_gephy_read_page, ++ .write_page = mtk_gephy_write_page, ++ }, ++}; ++ ++module_phy_driver(mtk_gephy_driver); ++ ++static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { ++ { PHY_ID_MATCH_VENDOR(0x03a29400) }, ++ { } ++}; diff --git a/target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch b/target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch new file mode 100644 index 0000000000..9890015301 --- /dev/null +++ b/target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch @@ -0,0 +1,425 @@ +From ba751e28d44255744a30190faad0ca09b455c44d Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Wed, 19 May 2021 11:32:00 +0800 +Subject: [PATCH] net: dsa: mt7530: add interrupt support + +Add support for MT7530 interrupt controller to handle internal PHYs. +In order to assign an IRQ number to each PHY, the registration of MDIO bus +is also done in this driver. + +Signed-off-by: DENG Qingfang +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 264 +++++++++++++++++++++++++++++++++++---- + drivers/net/dsa/mt7530.h | 20 ++- + 2 files changed, 256 insertions(+), 28 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -602,18 +603,14 @@ mt7530_mib_reset(struct dsa_switch *ds) + mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE); + } + +-static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum) ++static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum) + { +- struct mt7530_priv *priv = ds->priv; +- + return mdiobus_read_nested(priv->bus, port, regnum); + } + +-static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum, ++static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum, + u16 val) + { +- struct mt7530_priv *priv = ds->priv; +- + return mdiobus_write_nested(priv->bus, port, regnum, val); + } + +@@ -791,9 +788,8 @@ out: + } + + static int +-mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) ++mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum) + { +- struct mt7530_priv *priv = ds->priv; + int devad; + int ret; + +@@ -809,10 +805,9 @@ mt7531_ind_phy_read(struct dsa_switch *d + } + + static int +-mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, ++mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum, + u16 data) + { +- struct mt7530_priv *priv = ds->priv; + int devad; + int ret; + +@@ -828,6 +823,22 @@ mt7531_ind_phy_write(struct dsa_switch * + return ret; + } + ++static int ++mt753x_phy_read(struct mii_bus *bus, int port, int regnum) ++{ ++ struct mt7530_priv *priv = bus->priv; ++ ++ return priv->info->phy_read(priv, port, regnum); ++} ++ ++static int ++mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val) ++{ ++ struct mt7530_priv *priv = bus->priv; ++ ++ return priv->info->phy_write(priv, port, regnum, val); ++} ++ + static void + mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data) +@@ -1824,6 +1835,210 @@ mt7530_setup_gpio(struct mt7530_priv *pr + return devm_gpiochip_add_data(dev, gc, priv); + } + ++static irqreturn_t ++mt7530_irq_thread_fn(int irq, void *dev_id) ++{ ++ struct mt7530_priv *priv = dev_id; ++ bool handled = false; ++ u32 val; ++ int p; ++ ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ val = mt7530_mii_read(priv, MT7530_SYS_INT_STS); ++ mt7530_mii_write(priv, MT7530_SYS_INT_STS, val); ++ mutex_unlock(&priv->bus->mdio_lock); ++ ++ for (p = 0; p < MT7530_NUM_PHYS; p++) { ++ if (BIT(p) & val) { ++ unsigned int irq; ++ ++ irq = irq_find_mapping(priv->irq_domain, p); ++ handle_nested_irq(irq); ++ handled = true; ++ } ++ } ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static void ++mt7530_irq_mask(struct irq_data *d) ++{ ++ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ priv->irq_enable &= ~BIT(d->hwirq); ++} ++ ++static void ++mt7530_irq_unmask(struct irq_data *d) ++{ ++ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ priv->irq_enable |= BIT(d->hwirq); ++} ++ ++static void ++mt7530_irq_bus_lock(struct irq_data *d) ++{ ++ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++} ++ ++static void ++mt7530_irq_bus_sync_unlock(struct irq_data *d) ++{ ++ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); ++ mutex_unlock(&priv->bus->mdio_lock); ++} ++ ++static struct irq_chip mt7530_irq_chip = { ++ .name = KBUILD_MODNAME, ++ .irq_mask = mt7530_irq_mask, ++ .irq_unmask = mt7530_irq_unmask, ++ .irq_bus_lock = mt7530_irq_bus_lock, ++ .irq_bus_sync_unlock = mt7530_irq_bus_sync_unlock, ++}; ++ ++static int ++mt7530_irq_map(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_data(irq, domain->host_data); ++ irq_set_chip_and_handler(irq, &mt7530_irq_chip, handle_simple_irq); ++ irq_set_nested_thread(irq, true); ++ irq_set_noprobe(irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops mt7530_irq_domain_ops = { ++ .map = mt7530_irq_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++static void ++mt7530_setup_mdio_irq(struct mt7530_priv *priv) ++{ ++ struct dsa_switch *ds = priv->ds; ++ int p; ++ ++ for (p = 0; p < MT7530_NUM_PHYS; p++) { ++ if (BIT(p) & ds->phys_mii_mask) { ++ unsigned int irq; ++ ++ irq = irq_create_mapping(priv->irq_domain, p); ++ ds->slave_mii_bus->irq[p] = irq; ++ } ++ } ++} ++ ++static int ++mt7530_setup_irq(struct mt7530_priv *priv) ++{ ++ struct device *dev = priv->dev; ++ struct device_node *np = dev->of_node; ++ int ret; ++ ++ if (!of_property_read_bool(np, "interrupt-controller")) { ++ dev_info(dev, "no interrupt support\n"); ++ return 0; ++ } ++ ++ priv->irq = of_irq_get(np, 0); ++ if (priv->irq <= 0) { ++ dev_err(dev, "failed to get parent IRQ: %d\n", priv->irq); ++ return priv->irq ? : -EINVAL; ++ } ++ ++ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, ++ &mt7530_irq_domain_ops, priv); ++ if (!priv->irq_domain) { ++ dev_err(dev, "failed to create IRQ domain\n"); ++ return -ENOMEM; ++ } ++ ++ /* This register must be set for MT7530 to properly fire interrupts */ ++ if (priv->id != ID_MT7531) ++ mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL); ++ ++ ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn, ++ IRQF_ONESHOT, KBUILD_MODNAME, priv); ++ if (ret) { ++ irq_domain_remove(priv->irq_domain); ++ dev_err(dev, "failed to request IRQ: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ++mt7530_free_mdio_irq(struct mt7530_priv *priv) ++{ ++ int p; ++ ++ for (p = 0; p < MT7530_NUM_PHYS; p++) { ++ if (BIT(p) & priv->ds->phys_mii_mask) { ++ unsigned int irq; ++ ++ irq = irq_find_mapping(priv->irq_domain, p); ++ irq_dispose_mapping(irq); ++ } ++ } ++} ++ ++static void ++mt7530_free_irq_common(struct mt7530_priv *priv) ++{ ++ free_irq(priv->irq, priv); ++ irq_domain_remove(priv->irq_domain); ++} ++ ++static void ++mt7530_free_irq(struct mt7530_priv *priv) ++{ ++ mt7530_free_mdio_irq(priv); ++ mt7530_free_irq_common(priv); ++} ++ ++static int ++mt7530_setup_mdio(struct mt7530_priv *priv) ++{ ++ struct dsa_switch *ds = priv->ds; ++ struct device *dev = priv->dev; ++ struct mii_bus *bus; ++ static int idx; ++ int ret; ++ ++ bus = devm_mdiobus_alloc(dev); ++ if (!bus) ++ return -ENOMEM; ++ ++ ds->slave_mii_bus = bus; ++ bus->priv = priv; ++ bus->name = KBUILD_MODNAME "-mii"; ++ snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++); ++ bus->read = mt753x_phy_read; ++ bus->write = mt753x_phy_write; ++ bus->parent = dev; ++ bus->phy_mask = ~ds->phys_mii_mask; ++ ++ if (priv->irq) ++ mt7530_setup_mdio_irq(priv); ++ ++ ret = devm_mdiobus_register(dev, bus); ++ if (ret) { ++ dev_err(dev, "failed to register MDIO bus: %d\n", ret); ++ if (priv->irq) ++ mt7530_free_mdio_irq(priv); ++ } ++ ++ return ret; ++} ++ + static int + mt7530_setup(struct dsa_switch *ds) + { +@@ -2798,24 +3013,20 @@ static int + mt753x_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; ++ int ret = priv->info->sw_setup(ds); + +- return priv->info->sw_setup(ds); +-} +- +-static int +-mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) +-{ +- struct mt7530_priv *priv = ds->priv; ++ if (ret) ++ return ret; + +- return priv->info->phy_read(ds, port, regnum); +-} ++ ret = mt7530_setup_irq(priv); ++ if (ret) ++ return ret; + +-static int +-mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) +-{ +- struct mt7530_priv *priv = ds->priv; ++ ret = mt7530_setup_mdio(priv); ++ if (ret && priv->irq) ++ mt7530_free_irq_common(priv); + +- return priv->info->phy_write(ds, port, regnum, val); ++ return ret; + } + + static int mt753x_get_mac_eee(struct dsa_switch *ds, int port, +@@ -2852,8 +3063,6 @@ static const struct dsa_switch_ops mt753 + .get_tag_protocol = mtk_get_tag_protocol, + .setup = mt753x_setup, + .get_strings = mt7530_get_strings, +- .phy_read = mt753x_phy_read, +- .phy_write = mt753x_phy_write, + .get_ethtool_stats = mt7530_get_ethtool_stats, + .get_sset_count = mt7530_get_sset_count, + .set_ageing_time = mt7530_set_ageing_time, +@@ -3036,6 +3245,9 @@ mt7530_remove(struct mdio_device *mdiode + dev_err(priv->dev, "Failed to disable io pwr: %d\n", + ret); + ++ if (priv->irq) ++ mt7530_free_irq(priv); ++ + dsa_unregister_switch(priv->ds); + mutex_destroy(&priv->reg_mutex); + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -7,6 +7,7 @@ + #define __MT7530_H + + #define MT7530_NUM_PORTS 7 ++#define MT7530_NUM_PHYS 5 + #define MT7530_CPU_PORT 6 + #define MT7530_NUM_FDB_RECORDS 2048 + #define MT7530_ALL_MEMBERS 0xff +@@ -401,6 +402,12 @@ enum mt7531_sgmii_force_duplex { + #define SYS_CTRL_SW_RST BIT(1) + #define SYS_CTRL_REG_RST BIT(0) + ++/* Register for system interrupt */ ++#define MT7530_SYS_INT_EN 0x7008 ++ ++/* Register for system interrupt status */ ++#define MT7530_SYS_INT_STS 0x700c ++ + /* Register for PHY Indirect Access Control */ + #define MT7531_PHY_IAC 0x701C + #define MT7531_PHY_ACS_ST BIT(31) +@@ -722,6 +729,8 @@ static const char *p5_intf_modes(unsigne + } + } + ++struct mt7530_priv; ++ + /* struct mt753x_info - This is the main data structure for holding the specific + * part for each supported device + * @sw_setup: Holding the handler to a device initialization +@@ -746,8 +755,8 @@ struct mt753x_info { + enum mt753x_id id; + + int (*sw_setup)(struct dsa_switch *ds); +- int (*phy_read)(struct dsa_switch *ds, int port, int regnum); +- int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); ++ int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); ++ int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); + int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); + int (*cpu_port_config)(struct dsa_switch *ds, int port); + bool (*phy_mode_supported)(struct dsa_switch *ds, int port, +@@ -781,6 +790,10 @@ struct mt753x_info { + * registers + * @p6_interface Holding the current port 6 interface + * @p5_intf_sel: Holding the current port 5 interface select ++ * ++ * @irq: IRQ number of the switch ++ * @irq_domain: IRQ domain of the switch irq_chip ++ * @irq_enable: IRQ enable bits, synced to SYS_INT_EN + */ + struct mt7530_priv { + struct device *dev; +@@ -802,6 +815,9 @@ struct mt7530_priv { + struct mt7530_port ports[MT7530_NUM_PORTS]; + /* protect among processes for registers access*/ + struct mutex reg_mutex; ++ int irq; ++ struct irq_domain *irq_domain; ++ u32 irq_enable; + }; + + struct mt7530_hw_vlan_entry { diff --git a/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch b/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch new file mode 100644 index 0000000000..eb60134a1e --- /dev/null +++ b/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch @@ -0,0 +1,83 @@ +From 7164a8cde4b42f76474088ccaf53f1e463d4e2f6 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Mon, 24 Jan 2022 22:09:43 +0100 +Subject: [PATCH 5.10 1/2] net: dsa: Move VLAN filtering syncing out of + dsa_switch_bridge_leave +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 381a730182f1d174e1950cd4e63e885b1c302051 upstream. + +Most of dsa_switch_bridge_leave was, in fact, dealing with the syncing +of VLAN filtering for switches on which that is a global +setting. Separate the two phases to prepare for the cross-chip related +bugfix in the following commit. + +Signed-off-by: Tobias Waldekranz +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Marek Behún +--- + net/dsa/switch.c | 39 ++++++++++++++++++++++++++------------- + 1 file changed, 26 insertions(+), 13 deletions(-) + +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -104,23 +104,12 @@ static int dsa_switch_bridge_join(struct + return 0; + } + +-static int dsa_switch_bridge_leave(struct dsa_switch *ds, +- struct dsa_notifier_bridge_info *info) ++static int dsa_switch_sync_vlan_filtering(struct dsa_switch *ds, ++ struct dsa_notifier_bridge_info *info) + { + bool unset_vlan_filtering = br_vlan_enabled(info->br); +- struct dsa_switch_tree *dst = ds->dst; + int err, i; + +- if (dst->index == info->tree_index && ds->index == info->sw_index && +- ds->ops->port_bridge_leave) +- ds->ops->port_bridge_leave(ds, info->port, info->br); +- +- if ((dst->index != info->tree_index || ds->index != info->sw_index) && +- ds->ops->crosschip_bridge_leave) +- ds->ops->crosschip_bridge_leave(ds, info->tree_index, +- info->sw_index, info->port, +- info->br); +- + /* If the bridge was vlan_filtering, the bridge core doesn't trigger an + * event for changing vlan_filtering setting upon slave ports leaving + * it. That is a good thing, because that lets us handle it and also +@@ -153,6 +142,30 @@ static int dsa_switch_bridge_leave(struc + if (err && err != EOPNOTSUPP) + return err; + } ++ ++ return 0; ++} ++ ++static int dsa_switch_bridge_leave(struct dsa_switch *ds, ++ struct dsa_notifier_bridge_info *info) ++{ ++ struct dsa_switch_tree *dst = ds->dst; ++ int err; ++ ++ if (dst->index == info->tree_index && ds->index == info->sw_index && ++ ds->ops->port_bridge_leave) ++ ds->ops->port_bridge_leave(ds, info->port, info->br); ++ ++ if ((dst->index != info->tree_index || ds->index != info->sw_index) && ++ ds->ops->crosschip_bridge_leave) ++ ds->ops->crosschip_bridge_leave(ds, info->tree_index, ++ info->sw_index, info->port, ++ info->br); ++ ++ err = dsa_switch_sync_vlan_filtering(ds, info); ++ if (err) ++ return err; ++ + return 0; + } + diff --git a/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch b/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch new file mode 100644 index 0000000000..0b36ef7cec --- /dev/null +++ b/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch @@ -0,0 +1,58 @@ +From 6948a6654ffc878fc0258b363da77e7fd775b2d9 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Mon, 24 Jan 2022 22:09:44 +0100 +Subject: [PATCH 5.10 2/2] net: dsa: Avoid cross-chip syncing of VLAN filtering +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 108dc8741c203e9d6ce4e973367f1bac20c7192b upstream. + +Changes to VLAN filtering are not applicable to cross-chip +notifications. + +On a system like this: + +.-----. .-----. .-----. +| sw1 +---+ sw2 +---+ sw3 | +'-1-2-' '-1-2-' '-1-2-' + +Before this change, upon sw1p1 leaving a bridge, a call to +dsa_port_vlan_filtering would also be made to sw2p1 and sw3p1. + +In this scenario: + +.---------. .-----. .-----. +| sw1 +---+ sw2 +---+ sw3 | +'-1-2-3-4-' '-1-2-' '-1-2-' + +When sw1p4 would leave a bridge, dsa_port_vlan_filtering would be +called for sw2 and sw3 with a non-existing port - leading to array +out-of-bounds accesses and crashes on mv88e6xxx. + +Fixes: d371b7c92d19 ("net: dsa: Unset vlan_filtering when ports leave the bridge") +Signed-off-by: Tobias Waldekranz +Reviewed-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Marek Behún +--- + net/dsa/switch.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -162,9 +162,11 @@ static int dsa_switch_bridge_leave(struc + info->sw_index, info->port, + info->br); + +- err = dsa_switch_sync_vlan_filtering(ds, info); +- if (err) +- return err; ++ if (dst->index == info->tree_index && ds->index == info->sw_index) { ++ err = dsa_switch_sync_vlan_filtering(ds, info); ++ if (err) ++ return err; ++ } + + return 0; + } diff --git a/target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch b/target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch new file mode 100644 index 0000000000..d7df0685dd --- /dev/null +++ b/target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch @@ -0,0 +1,73 @@ +From 7c496de538eebd8212dc2a3c9a468386b264d0d4 Mon Sep 17 00:00:00 2001 +From: Sasha Neftin +Date: Wed, 7 Jul 2021 08:14:40 +0300 +Subject: igc: Remove _I_PHY_ID checking + +i225 devices have only one PHY vendor. There is no point checking +_I_PHY_ID during the link establishment and auto-negotiation process. +This patch comes to clean up these pointless checkings. + +Signed-off-by: Sasha Neftin +Tested-by: Dvora Fuxbrumer +Signed-off-by: Tony Nguyen +--- + drivers/net/ethernet/intel/igc/igc_base.c | 10 +--------- + drivers/net/ethernet/intel/igc/igc_main.c | 3 +-- + drivers/net/ethernet/intel/igc/igc_phy.c | 6 ++---- + 3 files changed, 4 insertions(+), 15 deletions(-) + +(limited to 'drivers/net/ethernet/intel/igc') + +--- a/drivers/net/ethernet/intel/igc/igc_base.c ++++ b/drivers/net/ethernet/intel/igc/igc_base.c +@@ -187,15 +187,7 @@ static s32 igc_init_phy_params_base(stru + + igc_check_for_copper_link(hw); + +- /* Verify phy id and set remaining function pointers */ +- switch (phy->id) { +- case I225_I_PHY_ID: +- phy->type = igc_phy_i225; +- break; +- default: +- ret_val = -IGC_ERR_PHY; +- goto out; +- } ++ phy->type = igc_phy_i225; + + out: + return ret_val; +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -4189,8 +4189,7 @@ bool igc_has_link(struct igc_adapter *ad + break; + } + +- if (hw->mac.type == igc_i225 && +- hw->phy.id == I225_I_PHY_ID) { ++ if (hw->mac.type == igc_i225) { + if (!netif_carrier_ok(adapter->netdev)) { + adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; + } else if (!(adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)) { +--- a/drivers/net/ethernet/intel/igc/igc_phy.c ++++ b/drivers/net/ethernet/intel/igc/igc_phy.c +@@ -249,8 +249,7 @@ static s32 igc_phy_setup_autoneg(struct + return ret_val; + } + +- if ((phy->autoneg_mask & ADVERTISE_2500_FULL) && +- hw->phy.id == I225_I_PHY_ID) { ++ if (phy->autoneg_mask & ADVERTISE_2500_FULL) { + /* Read the MULTI GBT AN Control Register - reg 7.32 */ + ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK << + MMD_DEVADDR_SHIFT) | +@@ -390,8 +389,7 @@ static s32 igc_phy_setup_autoneg(struct + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, + mii_1000t_ctrl_reg); + +- if ((phy->autoneg_mask & ADVERTISE_2500_FULL) && +- hw->phy.id == I225_I_PHY_ID) ++ if (phy->autoneg_mask & ADVERTISE_2500_FULL) + ret_val = phy->ops.write_reg(hw, + (STANDARD_AN_REG_MASK << + MMD_DEVADDR_SHIFT) | diff --git a/target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch b/target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch new file mode 100644 index 0000000000..ad4d1bb0dc --- /dev/null +++ b/target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch @@ -0,0 +1,43 @@ +From 47bca7de6a4fb8dcb564c7ca14d885c91ed19e03 Mon Sep 17 00:00:00 2001 +From: Sasha Neftin +Date: Sat, 10 Jul 2021 20:57:50 +0300 +Subject: igc: Remove phy->type checking + +i225 devices have only one phy->type: copper. There is no point checking +phy->type during the igc_has_link method from the watchdog that +invoked every 2 seconds. +This patch comes to clean up these pointless checkings. + +Signed-off-by: Sasha Neftin +Tested-by: Dvora Fuxbrumer +Signed-off-by: Tony Nguyen +--- + drivers/net/ethernet/intel/igc/igc_main.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +(limited to 'drivers/net/ethernet/intel/igc') + +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -4177,17 +4177,10 @@ bool igc_has_link(struct igc_adapter *ad + * false until the igc_check_for_link establishes link + * for copper adapters ONLY + */ +- switch (hw->phy.media_type) { +- case igc_media_type_copper: +- if (!hw->mac.get_link_status) +- return true; +- hw->mac.ops.check_for_link(hw); +- link_active = !hw->mac.get_link_status; +- break; +- default: +- case igc_media_type_unknown: +- break; +- } ++ if (!hw->mac.get_link_status) ++ return true; ++ hw->mac.ops.check_for_link(hw); ++ link_active = !hw->mac.get_link_status; + + if (hw->mac.type == igc_i225) { + if (!netif_carrier_ok(adapter->netdev)) { diff --git a/target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch b/target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch new file mode 100644 index 0000000000..bec2867a48 --- /dev/null +++ b/target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch @@ -0,0 +1,72 @@ +From 586f04ce6a391419ca3cc9cef6b6f38570cede88 Mon Sep 17 00:00:00 2001 +From: Lee Jones +Date: Mon, 2 Nov 2020 11:45:04 +0000 +Subject: [PATCH] net: usb: r8152: Provide missing documentation for + some struct members + +commit 34e653efb602e0651867fb5ab14369b555a61dcd upstream. + +Fixes the following W=1 kernel build warning(s): + + drivers/net/usb/r8152.c:934: warning: Function parameter or member 'blk_hdr' not described in 'fw_mac' + drivers/net/usb/r8152.c:934: warning: Function parameter or member 'reserved' not described in 'fw_mac' + drivers/net/usb/r8152.c:947: warning: Function parameter or member 'blk_hdr' not described in 'fw_phy_patch_key' + drivers/net/usb/r8152.c:947: warning: Function parameter or member 'reserved' not described in 'fw_phy_patch_key' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'blk_hdr' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'mode_pre' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'mode_post' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'reserved' not described in 'fw_phy_nc' + +Signed-off-by: Lee Jones +Acked-by: Hayes Wang +Link: https://lore.kernel.org/r/20201102114512.1062724-23-lee.jones@linaro.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -899,6 +899,7 @@ struct fw_header { + * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. + * The layout of the firmware block is: + * + + . ++ * @blk_hdr: firmware descriptor (type, length) + * @fw_offset: offset of the firmware binary data. The start address of + * the data would be the address of struct fw_mac + @fw_offset. + * @fw_reg: the register to load the firmware. Depends on chip. +@@ -912,6 +913,7 @@ struct fw_header { + * @bp_num: the break point number which needs to be set for this firmware. + * Depends on the firmware. + * @bp: break points. Depends on firmware. ++ * @reserved: reserved space (unused) + * @fw_ver_reg: the register to store the fw version. + * @fw_ver_data: the firmware version of the current type. + * @info: additional information for debugging, and is followed by the +@@ -937,8 +939,10 @@ struct fw_mac { + /** + * struct fw_phy_patch_key - a firmware block used by RTL_FW_PHY_START. + * This is used to set patch key when loading the firmware of PHY. ++ * @blk_hdr: firmware descriptor (type, length) + * @key_reg: the register to write the patch key. + * @key_data: patch key. ++ * @reserved: reserved space (unused) + */ + struct fw_phy_patch_key { + struct fw_block blk_hdr; +@@ -951,6 +955,7 @@ struct fw_phy_patch_key { + * struct fw_phy_nc - a firmware block used by RTL_FW_PHY_NC. + * The layout of the firmware block is: + * + + . ++ * @blk_hdr: firmware descriptor (type, length) + * @fw_offset: offset of the firmware binary data. The start address of + * the data would be the address of struct fw_phy_nc + @fw_offset. + * @fw_reg: the register to load the firmware. Depends on chip. +@@ -961,6 +966,7 @@ struct fw_phy_patch_key { + * @mode_reg: the regitster of switching the mode. + * @mod_pre: the mode needing to be set before loading the firmware. + * @mod_post: the mode to be set when finishing to load the firmware. ++ * @reserved: reserved space (unused) + * @bp_start: the start register of break points. Depends on chip. + * @bp_num: the break point number which needs to be set for this firmware. + * Depends on the firmware. diff --git a/target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch b/target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch new file mode 100644 index 0000000000..aa2763e7de --- /dev/null +++ b/target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch @@ -0,0 +1,34 @@ +From 5fcfa846181de6676509696c4cd7b60a22e74077 Mon Sep 17 00:00:00 2001 +From: Lee Jones +Date: Mon, 2 Nov 2020 11:45:09 +0000 +Subject: [PATCH] net: usb: r8152: Fix a couple of spelling errors in + fw_phy_nc's docs + +commit 9f07814d01ad085b2d9f1d55b4ce532fb2c27110 upstream. + +Fixes the following W=1 kernel build warning(s): + + drivers/net/usb/r8152.c:992: warning: Function parameter or member 'mode_pre' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:992: warning: Function parameter or member 'mode_post' not described in 'fw_phy_nc' + +Signed-off-by: Lee Jones +Acked-by: Hayes Wang +Link: https://lore.kernel.org/r/20201102114512.1062724-28-lee.jones@linaro.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -964,8 +964,8 @@ struct fw_phy_patch_key { + * @patch_en_addr: the register of enabling patch mode. Depends on chip. + * @patch_en_value: patch mode enabled mask. Depends on the firmware. + * @mode_reg: the regitster of switching the mode. +- * @mod_pre: the mode needing to be set before loading the firmware. +- * @mod_post: the mode to be set when finishing to load the firmware. ++ * @mode_pre: the mode needing to be set before loading the firmware. ++ * @mode_post: the mode to be set when finishing to load the firmware. + * @reserved: reserved space (unused) + * @bp_start: the start register of break points. Depends on chip. + * @bp_num: the break point number which needs to be set for this firmware. diff --git a/target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch b/target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch new file mode 100644 index 0000000000..789de8e6fd --- /dev/null +++ b/target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch @@ -0,0 +1,320 @@ +From 0ef50460f7f053bd2a911ec53e01bfda646a5574 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Wed, 4 Nov 2020 10:19:22 +0800 +Subject: [PATCH] net/usb/r8153_ecm: support ECM mode for RTL8153 + +commit c1aedf015ebdd0232757a66e2daccf1246bd609c upstream. + +Support ECM mode based on cdc_ether with relative mii functions, +when CONFIG_USB_RTL8152 is not set, or the device is not supported +by r8152 driver. + +Both r8152 and r8153_ecm would check the return value of +rtl8152_get_version() in porbe(). If rtl8152_get_version() +return none zero value, the r8152 is used for the device +with vendor mode. Otherwise, the r8153_ecm is used for the +device with ECM mode. + +Signed-off-by: Hayes Wang +Link: https://lore.kernel.org/r/1394712342-15778-392-Taiwan-albertk@realtek.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/Makefile | 2 +- + drivers/net/usb/r8152.c | 30 +------ + drivers/net/usb/r8153_ecm.c | 162 ++++++++++++++++++++++++++++++++++++ + include/linux/usb/r8152.h | 37 ++++++++ + 4 files changed, 204 insertions(+), 27 deletions(-) + create mode 100644 drivers/net/usb/r8153_ecm.c + create mode 100644 include/linux/usb/r8152.h + +--- a/drivers/net/usb/Makefile ++++ b/drivers/net/usb/Makefile +@@ -13,7 +13,7 @@ obj-$(CONFIG_USB_LAN78XX) += lan78xx.o + obj-$(CONFIG_USB_NET_AX8817X) += asix.o + asix-y := asix_devices.o asix_common.o ax88172a.o + obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o +-obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o ++obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r8153_ecm.o + obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o + obj-$(CONFIG_USB_NET_DM9601) += dm9601.o + obj-$(CONFIG_USB_NET_SR9700) += sr9700.o +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + /* Information for net-next */ + #define NETNEXT_VERSION "11" +@@ -654,18 +655,6 @@ enum rtl_register_content { + + #define INTR_LINK 0x0004 + +-#define RTL8152_REQT_READ 0xc0 +-#define RTL8152_REQT_WRITE 0x40 +-#define RTL8152_REQ_GET_REGS 0x05 +-#define RTL8152_REQ_SET_REGS 0x05 +- +-#define BYTE_EN_DWORD 0xff +-#define BYTE_EN_WORD 0x33 +-#define BYTE_EN_BYTE 0x11 +-#define BYTE_EN_SIX_BYTES 0x3f +-#define BYTE_EN_START_MASK 0x0f +-#define BYTE_EN_END_MASK 0xf0 +- + #define RTL8153_MAX_PACKET 9216 /* 9K */ + #define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \ + ETH_FCS_LEN) +@@ -690,21 +679,9 @@ enum rtl8152_flags { + LENOVO_MACPASSTHRU, + }; + +-/* Define these values to match your device */ +-#define VENDOR_ID_REALTEK 0x0bda +-#define VENDOR_ID_MICROSOFT 0x045e +-#define VENDOR_ID_SAMSUNG 0x04e8 +-#define VENDOR_ID_LENOVO 0x17ef +-#define VENDOR_ID_LINKSYS 0x13b1 +-#define VENDOR_ID_NVIDIA 0x0955 +-#define VENDOR_ID_TPLINK 0x2357 +- + #define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2 0x3082 + #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2 0xa387 + +-#define MCU_TYPE_PLA 0x0100 +-#define MCU_TYPE_USB 0x0000 +- + struct tally_counter { + __le64 tx_packets; + __le64 rx_packets; +@@ -6625,7 +6602,7 @@ static int rtl_fw_init(struct r8152 *tp) + return 0; + } + +-static u8 rtl_get_version(struct usb_interface *intf) ++u8 rtl8152_get_version(struct usb_interface *intf) + { + struct usb_device *udev = interface_to_usbdev(intf); + u32 ocp_data = 0; +@@ -6683,12 +6660,13 @@ static u8 rtl_get_version(struct usb_int + + return version; + } ++EXPORT_SYMBOL_GPL(rtl8152_get_version); + + static int rtl8152_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { + struct usb_device *udev = interface_to_usbdev(intf); +- u8 version = rtl_get_version(intf); ++ u8 version = rtl8152_get_version(intf); + struct r8152 *tp; + struct net_device *netdev; + int ret; +--- /dev/null ++++ b/drivers/net/usb/r8153_ecm.c +@@ -0,0 +1,162 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define OCP_BASE 0xe86c ++ ++static int pla_read_word(struct usbnet *dev, u16 index) ++{ ++ u16 byen = BYTE_EN_WORD; ++ u8 shift = index & 2; ++ __le32 tmp; ++ int ret; ++ ++ if (shift) ++ byen <<= shift; ++ ++ index &= ~3; ++ ++ ret = usbnet_read_cmd(dev, RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, index, ++ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp)); ++ if (ret < 0) ++ goto out; ++ ++ ret = __le32_to_cpu(tmp); ++ ret >>= (shift * 8); ++ ret &= 0xffff; ++ ++out: ++ return ret; ++} ++ ++static int pla_write_word(struct usbnet *dev, u16 index, u32 data) ++{ ++ u32 mask = 0xffff; ++ u16 byen = BYTE_EN_WORD; ++ u8 shift = index & 2; ++ __le32 tmp; ++ int ret; ++ ++ data &= mask; ++ ++ if (shift) { ++ byen <<= shift; ++ mask <<= (shift * 8); ++ data <<= (shift * 8); ++ } ++ ++ index &= ~3; ++ ++ ret = usbnet_read_cmd(dev, RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, index, ++ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp)); ++ ++ if (ret < 0) ++ goto out; ++ ++ data |= __le32_to_cpu(tmp) & ~mask; ++ tmp = __cpu_to_le32(data); ++ ++ ret = usbnet_write_cmd(dev, RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, index, ++ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp)); ++ ++out: ++ return ret; ++} ++ ++static int r8153_ecm_mdio_read(struct net_device *netdev, int phy_id, int reg) ++{ ++ struct usbnet *dev = netdev_priv(netdev); ++ int ret; ++ ++ ret = pla_write_word(dev, OCP_BASE, 0xa000); ++ if (ret < 0) ++ goto out; ++ ++ ret = pla_read_word(dev, 0xb400 + reg * 2); ++ ++out: ++ return ret; ++} ++ ++static void r8153_ecm_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) ++{ ++ struct usbnet *dev = netdev_priv(netdev); ++ int ret; ++ ++ ret = pla_write_word(dev, OCP_BASE, 0xa000); ++ if (ret < 0) ++ return; ++ ++ ret = pla_write_word(dev, 0xb400 + reg * 2, val); ++} ++ ++static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) ++{ ++ int status; ++ ++ status = usbnet_cdc_bind(dev, intf); ++ if (status < 0) ++ return status; ++ ++ dev->mii.dev = dev->net; ++ dev->mii.mdio_read = r8153_ecm_mdio_read; ++ dev->mii.mdio_write = r8153_ecm_mdio_write; ++ dev->mii.reg_num_mask = 0x1f; ++ dev->mii.supports_gmii = 1; ++ ++ return status; ++} ++ ++static const struct driver_info r8153_info = { ++ .description = "RTL8153 ECM Device", ++ .flags = FLAG_ETHER, ++ .bind = r8153_bind, ++ .unbind = usbnet_cdc_unbind, ++ .status = usbnet_cdc_status, ++ .manage_power = usbnet_manage_power, ++}; ++ ++static const struct usb_device_id products[] = { ++{ ++ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_REALTEK, 0x8153, USB_CLASS_COMM, ++ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), ++ .driver_info = (unsigned long)&r8153_info, ++}, ++ ++ { }, /* END */ ++}; ++MODULE_DEVICE_TABLE(usb, products); ++ ++static int rtl8153_ecm_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++#if IS_REACHABLE(CONFIG_USB_RTL8152) ++ if (rtl8152_get_version(intf)) ++ return -ENODEV; ++#endif ++ ++ return usbnet_probe(intf, id); ++} ++ ++static struct usb_driver r8153_ecm_driver = { ++ .name = "r8153_ecm", ++ .id_table = products, ++ .probe = rtl8153_ecm_probe, ++ .disconnect = usbnet_disconnect, ++ .suspend = usbnet_suspend, ++ .resume = usbnet_resume, ++ .reset_resume = usbnet_resume, ++ .supports_autosuspend = 1, ++ .disable_hub_initiated_lpm = 1, ++}; ++ ++module_usb_driver(r8153_ecm_driver); ++ ++MODULE_AUTHOR("Hayes Wang"); ++MODULE_DESCRIPTION("Realtek USB ECM device"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/linux/usb/r8152.h +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2020 Realtek Semiconductor Corp. All rights reserved. ++ */ ++ ++#ifndef __LINUX_R8152_H ++#define __LINUX_R8152_H ++ ++#define RTL8152_REQT_READ 0xc0 ++#define RTL8152_REQT_WRITE 0x40 ++#define RTL8152_REQ_GET_REGS 0x05 ++#define RTL8152_REQ_SET_REGS 0x05 ++ ++#define BYTE_EN_DWORD 0xff ++#define BYTE_EN_WORD 0x33 ++#define BYTE_EN_BYTE 0x11 ++#define BYTE_EN_SIX_BYTES 0x3f ++#define BYTE_EN_START_MASK 0x0f ++#define BYTE_EN_END_MASK 0xf0 ++ ++#define MCU_TYPE_PLA 0x0100 ++#define MCU_TYPE_USB 0x0000 ++ ++/* Define these values to match your device */ ++#define VENDOR_ID_REALTEK 0x0bda ++#define VENDOR_ID_MICROSOFT 0x045e ++#define VENDOR_ID_SAMSUNG 0x04e8 ++#define VENDOR_ID_LENOVO 0x17ef ++#define VENDOR_ID_LINKSYS 0x13b1 ++#define VENDOR_ID_NVIDIA 0x0955 ++#define VENDOR_ID_TPLINK 0x2357 ++ ++#if IS_REACHABLE(CONFIG_USB_RTL8152) ++extern u8 rtl8152_get_version(struct usb_interface *intf); ++#endif ++ ++#endif /* __LINUX_R8152_H */ diff --git a/target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch b/target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch new file mode 100644 index 0000000000..b625d5ea99 --- /dev/null +++ b/target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch @@ -0,0 +1,41 @@ +From 90f1afc7f96c8f7cf19c82e5f4b39e61a63b053d Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing +Date: Sun, 31 Jan 2021 00:47:29 +0100 +Subject: [PATCH] net: usb: r8152: use new tasklet API + +commit f3163f1cb87141c7a41a15a5d4c98b353f807b04 upstream. + +This converts the driver to use the new tasklet API introduced in +commit 12cc923f1ccc ("tasklet: Introduce new initialization API") + +Signed-off-by: Emil Renner Berthing +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2394,11 +2394,9 @@ static void tx_bottom(struct r8152 *tp) + } while (res == 0); + } + +-static void bottom_half(unsigned long data) ++static void bottom_half(struct tasklet_struct *t) + { +- struct r8152 *tp; +- +- tp = (struct r8152 *)data; ++ struct r8152 *tp = from_tasklet(tp, t, tx_tl); + + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; +@@ -6718,7 +6716,7 @@ static int rtl8152_probe(struct usb_inte + mutex_init(&tp->control); + INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); + INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); +- tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp); ++ tasklet_setup(&tp->tx_tl, bottom_half); + tasklet_disable(&tp->tx_tl); + + netdev->netdev_ops = &rtl8152_netdev_ops; diff --git a/target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch b/target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch new file mode 100644 index 0000000000..bbb2b5c0c9 --- /dev/null +++ b/target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch @@ -0,0 +1,198 @@ +From 86b98abf4f8c691c260c5113d6a2d32f5377caca Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Wed, 3 Feb 2021 17:14:28 +0800 +Subject: [PATCH] r8152: replace several functions about phy patch + request + +commit a08c0d309d8c078d22717d815cf9853f6f2c07bd upstream. + +Replace r8153_patch_request() with rtl_phy_patch_request(). +Replace r8153_pre_ram_code() with rtl_pre_ram_code(). +Replace r8153_post_ram_code() with rtl_post_ram_code(). +Add rtl_patch_key_set(). + +The new functions have an additional parameter. It is used to wait +the patch request command finished. When the PHY is resumed from +the state of power cut, the PHY is at a safe mode and the +OCP_PHY_PATCH_STAT wouldn't be updated. For this situation, it is +safe to set patch request command without waiting OCP_PHY_PATCH_STAT. + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 84 ++++++++++++++++++++++++----------------- + 1 file changed, 50 insertions(+), 34 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3444,59 +3444,76 @@ static void rtl_clear_bp(struct r8152 *t + ocp_write_word(tp, type, PLA_BP_BA, 0); + } + +-static int r8153_patch_request(struct r8152 *tp, bool request) ++static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) + { +- u16 data; ++ u16 data, check; + int i; + + data = ocp_reg_read(tp, OCP_PHY_PATCH_CMD); +- if (request) ++ if (request) { + data |= PATCH_REQUEST; +- else ++ check = 0; ++ } else { + data &= ~PATCH_REQUEST; ++ check = PATCH_READY; ++ } + ocp_reg_write(tp, OCP_PHY_PATCH_CMD, data); + +- for (i = 0; request && i < 5000; i++) { ++ for (i = 0; wait && i < 5000; i++) { ++ u32 ocp_data; ++ + usleep_range(1000, 2000); +- if (ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY) ++ ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT); ++ if ((ocp_data & PATCH_READY) ^ check) + break; + } + +- if (request && !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { +- netif_err(tp, drv, tp->netdev, "patch request fail\n"); +- r8153_patch_request(tp, false); ++ if (request && wait && ++ !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { ++ dev_err(&tp->intf->dev, "PHY patch request fail\n"); ++ rtl_phy_patch_request(tp, false, false); + return -ETIME; + } else { + return 0; + } + } + +-static int r8153_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key) ++static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key) + { +- if (r8153_patch_request(tp, true)) { +- dev_err(&tp->intf->dev, "patch request fail\n"); +- return -ETIME; +- } ++ if (patch_key && key_addr) { ++ sram_write(tp, key_addr, patch_key); ++ sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); ++ } else if (key_addr) { ++ u16 data; + +- sram_write(tp, key_addr, patch_key); +- sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); ++ sram_write(tp, 0x0000, 0x0000); + +- return 0; ++ data = ocp_reg_read(tp, OCP_PHY_LOCK); ++ data &= ~PATCH_LOCK; ++ ocp_reg_write(tp, OCP_PHY_LOCK, data); ++ ++ sram_write(tp, key_addr, 0x0000); ++ } else { ++ WARN_ON_ONCE(1); ++ } + } + +-static int r8153_post_ram_code(struct r8152 *tp, u16 key_addr) ++static int ++rtl_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key, bool wait) + { +- u16 data; ++ if (rtl_phy_patch_request(tp, true, wait)) ++ return -ETIME; + +- sram_write(tp, 0x0000, 0x0000); ++ rtl_patch_key_set(tp, key_addr, patch_key); + +- data = ocp_reg_read(tp, OCP_PHY_LOCK); +- data &= ~PATCH_LOCK; +- ocp_reg_write(tp, OCP_PHY_LOCK, data); ++ return 0; ++} + +- sram_write(tp, key_addr, 0x0000); ++static int rtl_post_ram_code(struct r8152 *tp, u16 key_addr, bool wait) ++{ ++ rtl_patch_key_set(tp, key_addr, 0); + +- r8153_patch_request(tp, false); ++ rtl_phy_patch_request(tp, false, wait); + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); + +@@ -3981,7 +3998,7 @@ static void rtl8152_fw_mac_apply(struct + dev_dbg(&tp->intf->dev, "successfully applied %s\n", mac->info); + } + +-static void rtl8152_apply_firmware(struct r8152 *tp) ++static void rtl8152_apply_firmware(struct r8152 *tp, bool power_cut) + { + struct rtl_fw *rtl_fw = &tp->rtl_fw; + const struct firmware *fw; +@@ -4012,12 +4029,11 @@ static void rtl8152_apply_firmware(struc + case RTL_FW_PHY_START: + key = (struct fw_phy_patch_key *)block; + key_addr = __le16_to_cpu(key->key_reg); +- r8153_pre_ram_code(tp, key_addr, +- __le16_to_cpu(key->key_data)); ++ rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); + break; + case RTL_FW_PHY_STOP: + WARN_ON(!key_addr); +- r8153_post_ram_code(tp, key_addr); ++ rtl_post_ram_code(tp, key_addr, !power_cut); + break; + case RTL_FW_PHY_NC: + rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); +@@ -4222,7 +4238,7 @@ static void rtl8152_disable(struct r8152 + + static void r8152b_hw_phy_cfg(struct r8152 *tp) + { +- rtl8152_apply_firmware(tp); ++ rtl8152_apply_firmware(tp, false); + rtl_eee_enable(tp, tp->eee_en); + r8152_aldps_en(tp, true); + r8152b_enable_fc(tp); +@@ -4504,7 +4520,7 @@ static void r8153_hw_phy_cfg(struct r815 + /* disable EEE before updating the PHY parameters */ + rtl_eee_enable(tp, false); + +- rtl8152_apply_firmware(tp); ++ rtl8152_apply_firmware(tp, false); + + if (tp->version == RTL_VER_03) { + data = ocp_reg_read(tp, OCP_EEE_CFG); +@@ -4578,7 +4594,7 @@ static void r8153b_hw_phy_cfg(struct r81 + /* disable EEE before updating the PHY parameters */ + rtl_eee_enable(tp, false); + +- rtl8152_apply_firmware(tp); ++ rtl8152_apply_firmware(tp, false); + + r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); + +@@ -4619,7 +4635,7 @@ static void r8153b_hw_phy_cfg(struct r81 + ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); + + /* Advnace EEE */ +- if (!r8153_patch_request(tp, true)) { ++ if (!rtl_phy_patch_request(tp, true, true)) { + data = ocp_reg_read(tp, OCP_POWER_CFG); + data |= EEE_CLKDIV_EN; + ocp_reg_write(tp, OCP_POWER_CFG, data); +@@ -4636,7 +4652,7 @@ static void r8153b_hw_phy_cfg(struct r81 + ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5)); + tp->ups_info._250m_ckdiv = true; + +- r8153_patch_request(tp, false); ++ rtl_phy_patch_request(tp, false, true); + } + + if (tp->eee_en) diff --git a/target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch b/target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch new file mode 100644 index 0000000000..b28e89a43f --- /dev/null +++ b/target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch @@ -0,0 +1,134 @@ +From 29a61d8564ad3439d03c7ec135016a4e70072af1 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Wed, 3 Feb 2021 17:14:29 +0800 +Subject: [PATCH] r8152: adjust the flow of power cut for RTL8153B + +commit 80fd850b31f09263ad175b2f640d5c5c6f76ed41 upstream. + +For runtime resuming, the RTL8153B may be resumed from the state +of power cut, when enabling the feature of UPS. Then, the PHY +would be reset, so it is necessary to be initailized again. + +Besides, the USB_U1U2_TIMER also has to be set again, so I move +it from r8153b_init() to r8153b_hw_phy_cfg(). + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 68 ++++++++++++++++++++++++----------------- + 1 file changed, 40 insertions(+), 28 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -1372,6 +1372,10 @@ void write_mii_word(struct net_device *n + static int + r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags); + ++static int ++rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, ++ u32 advertising); ++ + static int rtl8152_set_mac_address(struct net_device *netdev, void *p) + { + struct r8152 *tp = netdev_priv(netdev); +@@ -3183,8 +3187,6 @@ static void r8153b_ups_en(struct r8152 * + ocp_data |= BIT(0); + ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); + } else { +- u16 data; +- + ocp_data &= ~(UPS_EN | USP_PREWAKE); + ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + +@@ -3192,31 +3194,20 @@ static void r8153b_ups_en(struct r8152 * + ocp_data &= ~BIT(0); + ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); + +- ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); +- ocp_data &= ~PCUT_STATUS; +- ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { ++ int i; + +- data = r8153_phy_status(tp, 0); ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ msleep(20); ++ } + +- switch (data) { +- case PHY_STAT_PWRDN: +- case PHY_STAT_EXT_INIT: +- r8153b_green_en(tp, +- test_bit(GREEN_ETHERNET, &tp->flags)); +- +- data = r8152_mdio_read(tp, MII_BMCR); +- data &= ~BMCR_PDOWN; +- data |= BMCR_RESET; +- r8152_mdio_write(tp, MII_BMCR, data); ++ tp->rtl_ops.hw_phy_cfg(tp); + +- data = r8153_phy_status(tp, PHY_STAT_LAN_ON); +- fallthrough; +- +- default: +- if (data != PHY_STAT_LAN_ON) +- netif_warn(tp, link, tp->netdev, +- "PHY not ready"); +- break; ++ rtl8152_set_speed(tp, tp->autoneg, tp->speed, ++ tp->duplex, tp->advertising); + } + } + } +@@ -4588,13 +4579,37 @@ static void r8153b_hw_phy_cfg(struct r81 + u32 ocp_data; + u16 data; + ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); ++ if (ocp_data & PCUT_STATUS) { ++ ocp_data &= ~PCUT_STATUS; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ } ++ + /* disable ALDPS before updating the PHY parameters */ + r8153_aldps_en(tp, false); + + /* disable EEE before updating the PHY parameters */ + rtl_eee_enable(tp, false); + +- rtl8152_apply_firmware(tp, false); ++ /* U1/U2/L1 idle timer. 500 us */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); ++ ++ data = r8153_phy_status(tp, 0); ++ ++ switch (data) { ++ case PHY_STAT_PWRDN: ++ case PHY_STAT_EXT_INIT: ++ rtl8152_apply_firmware(tp, true); ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ break; ++ case PHY_STAT_LAN_ON: ++ default: ++ rtl8152_apply_firmware(tp, false); ++ break; ++ } + + r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); + +@@ -5543,9 +5558,6 @@ static void r8153b_init(struct r8152 *tp + /* MSC timer = 0xfff * 8ms = 32760 ms */ + ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); + +- /* U1/U2/L1 idle timer. 500 us */ +- ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); +- + r8153b_power_cut_en(tp, false); + r8153b_ups_en(tp, false); + r8153_queue_wake(tp, false); diff --git a/target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch b/target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch new file mode 100644 index 0000000000..8cf91c3893 --- /dev/null +++ b/target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch @@ -0,0 +1,47 @@ +From 69b4339c0b9f3edc6a8f681f05efaaf4add1bb0e Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 19 Feb 2021 17:04:40 +0800 +Subject: [PATCH] r8152: enable U1/U2 for USB_SPEED_SUPER + +commit 7a0ae61acde2cebd69665837170405eced86a6c7 upstream. + +U1/U2 shoued be enabled for USB 3.0 or later. The USB 2.0 doesn't +support it. + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3336,7 +3336,7 @@ static void rtl8153b_runtime_enable(stru + r8153b_ups_en(tp, false); + r8153_queue_wake(tp, false); + rtl_runtime_suspend_enable(tp, false); +- if (tp->udev->speed != USB_SPEED_HIGH) ++ if (tp->udev->speed >= USB_SPEED_SUPER) + r8153b_u1u2en(tp, true); + } + } +@@ -5029,7 +5029,7 @@ static void rtl8153b_up(struct r8152 *tp + + r8153_aldps_en(tp, true); + +- if (tp->udev->speed != USB_SPEED_HIGH) ++ if (tp->udev->speed >= USB_SPEED_SUPER) + r8153b_u1u2en(tp, true); + } + +@@ -5571,8 +5571,9 @@ static void r8153b_init(struct r8152 *tp + ocp_data |= POLL_LINK_CHG; + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); + +- if (tp->udev->speed != USB_SPEED_HIGH) ++ if (tp->udev->speed >= USB_SPEED_SUPER) + r8153b_u1u2en(tp, true); ++ + usb_enable_lpm(tp->udev); + + /* MAC clock speed down */ diff --git a/target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch b/target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch new file mode 100644 index 0000000000..5bc4e2b0a1 --- /dev/null +++ b/target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch @@ -0,0 +1,51 @@ +From e78b75f5be204a0a235da995d01c778dc282bb42 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 19 Feb 2021 17:04:41 +0800 +Subject: [PATCH] r8152: check if the pointer of the function exists + +commit c79515e47935c747282c6ed2ee5b2ef039756eeb upstream. + +Return error code if autosuspend_en, eee_get, or eee_set don't exist. + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -5758,6 +5758,9 @@ static int rtl8152_runtime_suspend(struc + struct net_device *netdev = tp->netdev; + int ret = 0; + ++ if (!tp->rtl_ops.autosuspend_en) ++ return -EBUSY; ++ + set_bit(SELECTIVE_SUSPEND, &tp->flags); + smp_mb__after_atomic(); + +@@ -6157,6 +6160,11 @@ rtl_ethtool_get_eee(struct net_device *n + struct r8152 *tp = netdev_priv(net); + int ret; + ++ if (!tp->rtl_ops.eee_get) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ + ret = usb_autopm_get_interface(tp->intf); + if (ret < 0) + goto out; +@@ -6179,6 +6187,11 @@ rtl_ethtool_set_eee(struct net_device *n + struct r8152 *tp = netdev_priv(net); + int ret; + ++ if (!tp->rtl_ops.eee_set) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ + ret = usb_autopm_get_interface(tp->intf); + if (ret < 0) + goto out; diff --git a/target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch b/target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch new file mode 100644 index 0000000000..967b4ccc16 --- /dev/null +++ b/target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch @@ -0,0 +1,36 @@ +From 38e44c7926512cff0b2809dc329de2a8e769e523 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 19 Feb 2021 17:04:42 +0800 +Subject: [PATCH] r8152: replace netif_err with dev_err + +commit 156c3207611262266f0eea589ac3f00c5657320e upstream. + +Some messages are before calling register_netdev(), so replace +netif_err() with dev_err(). + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -6594,7 +6594,7 @@ static int rtl_ops_init(struct r8152 *tp + + default: + ret = -ENODEV; +- netif_err(tp, probe, tp->netdev, "Unknown Device\n"); ++ dev_err(&tp->intf->dev, "Unknown Device\n"); + break; + } + +@@ -6851,7 +6851,7 @@ static int rtl8152_probe(struct usb_inte + + ret = register_netdev(netdev); + if (ret != 0) { +- netif_err(tp, probe, netdev, "couldn't register the device\n"); ++ dev_err(&intf->dev, "couldn't register the device\n"); + goto out1; + } + diff --git a/target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch b/target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch new file mode 100644 index 0000000000..c49a4ce5b6 --- /dev/null +++ b/target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch @@ -0,0 +1,89 @@ +From 260814de2d6cb958767785ffcb2e76915d1be32b Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 19 Feb 2021 17:04:43 +0800 +Subject: [PATCH] r8152: spilt rtl_set_eee_plus and r8153b_green_en + +commit 40fa7568ac230446d888b7ad402cff9e20fe3ad5 upstream. + +Add rtl_eee_plus_en() and rtl_green_en(). + +Signed-off-by: Hayes Wang +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/r8152.c | 43 ++++++++++++++++++++++++++--------------- + 1 file changed, 27 insertions(+), 16 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2633,21 +2633,24 @@ static inline u8 rtl8152_get_speed(struc + return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); + } + +-static void rtl_set_eee_plus(struct r8152 *tp) ++static void rtl_eee_plus_en(struct r8152 *tp, bool enable) + { + u32 ocp_data; +- u8 speed; + +- speed = rtl8152_get_speed(tp); +- if (speed & _10bps) { +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ++ if (enable) + ocp_data |= EEEP_CR_EEEP_TX; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); +- } else { +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ++ else + ocp_data &= ~EEEP_CR_EEEP_TX; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); +- } ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); ++} ++ ++static void rtl_set_eee_plus(struct r8152 *tp) ++{ ++ if (rtl8152_get_speed(tp) & _10bps) ++ rtl_eee_plus_en(tp, true); ++ else ++ rtl_eee_plus_en(tp, false); + } + + static void rxdy_gated_en(struct r8152 *tp, bool enable) +@@ -3128,10 +3131,22 @@ static void r8153b_ups_flags(struct r815 + ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); + } + +-static void r8153b_green_en(struct r8152 *tp, bool enable) ++static void rtl_green_en(struct r8152 *tp, bool enable) + { + u16 data; + ++ data = sram_read(tp, SRAM_GREEN_CFG); ++ if (enable) ++ data |= GREEN_ETH_EN; ++ else ++ data &= ~GREEN_ETH_EN; ++ sram_write(tp, SRAM_GREEN_CFG, data); ++ ++ tp->ups_info.green = enable; ++} ++ ++static void r8153b_green_en(struct r8152 *tp, bool enable) ++{ + if (enable) { + sram_write(tp, 0x8045, 0); /* 10M abiq&ldvbias */ + sram_write(tp, 0x804d, 0x1222); /* 100M short abiq&ldvbias */ +@@ -3142,11 +3157,7 @@ static void r8153b_green_en(struct r8152 + sram_write(tp, 0x805d, 0x2444); /* 1000M short abiq&ldvbias */ + } + +- data = sram_read(tp, SRAM_GREEN_CFG); +- data |= GREEN_ETH_EN; +- sram_write(tp, SRAM_GREEN_CFG, data); +- +- tp->ups_info.green = enable; ++ rtl_green_en(tp, true); + } + + static u16 r8153_phy_status(struct r8152 *tp, u16 desired) diff --git a/target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch b/target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch new file mode 100644 index 0000000000..f2593e8f00 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch @@ -0,0 +1,75 @@ +From f1bbbb260a8016373adf239c716d2da90e6ced0b Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 16 Apr 2021 16:04:32 +0800 +Subject: [PATCH] r8152: set inter fram gap time depending on speed + +commit 5133bcc7481528e36fff0a3b056601efb704fb32 upstream. + +Set the maximum inter frame gap time (144ns) for speed 10M/half and +100M/half. It improves the performance for those speeds. And, there +is no effect for the other speeds. + +For 10M/half and 100M/half, the fast inter frame gap time let the +device couldn't use the feature of the aggregation effectively, +because the transfer would be completed fastly. Therefore, use the +maximum value to improve the effect of the aggregation. However, you +may not feel the improvement for fast CPUs, because they compensate +for the effect of the aggregation. + +Signed-off-by: Hayes Wang +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -250,6 +250,9 @@ + + /* PLA_TCR1 */ + #define VERSION_MASK 0x7cf0 ++#define IFG_MASK (BIT(3) | BIT(9) | BIT(8)) ++#define IFG_144NS BIT(9) ++#define IFG_96NS (BIT(9) | BIT(8)) + + /* PLA_MTPS */ + #define MTPS_JUMBO (12 * 1024 / 64) +@@ -2748,6 +2751,29 @@ static int rtl_stop_rx(struct r8152 *tp) + return 0; + } + ++static void rtl_set_ifg(struct r8152 *tp, u16 speed) ++{ ++ u32 ocp_data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1); ++ ocp_data &= ~IFG_MASK; ++ if ((speed & (_10bps | _100bps)) && !(speed & FULL_DUP)) { ++ ocp_data |= IFG_144NS; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR1, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data &= ~TX10MIDLE_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ } else { ++ ocp_data |= IFG_96NS; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR1, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data |= TX10MIDLE_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ } ++} ++ + static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp) + { + ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN, +@@ -2851,6 +2877,8 @@ static int rtl8153_enable(struct r8152 * + r8153_set_rx_early_timeout(tp); + r8153_set_rx_early_size(tp); + ++ rtl_set_ifg(tp, rtl8152_get_speed(tp)); ++ + if (tp->version == RTL_VER_09) { + u32 ocp_data; + diff --git a/target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch b/target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch new file mode 100644 index 0000000000..cddd39ea94 --- /dev/null +++ b/target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch @@ -0,0 +1,152 @@ +From f10c9edf47d3fa240d965e151a48c670f5035b73 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 16 Apr 2021 16:04:33 +0800 +Subject: [PATCH] r8152: adjust rtl8152_check_firmware function + +commit a8a7be178e81a3d4b6972cbeb0ccd091ca2f9f89 upstream. + +Use bits operations to record and check the firmware. + +Signed-off-by: Hayes Wang +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 51 +++++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 22 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -875,6 +875,14 @@ struct fw_header { + struct fw_block blocks[]; + } __packed; + ++enum rtl8152_fw_flags { ++ FW_FLAGS_USB = 0, ++ FW_FLAGS_PLA, ++ FW_FLAGS_START, ++ FW_FLAGS_STOP, ++ FW_FLAGS_NC, ++}; ++ + /** + * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. + * The layout of the firmware block is: +@@ -3801,10 +3809,7 @@ static long rtl8152_check_firmware(struc + { + const struct firmware *fw = rtl_fw->fw; + struct fw_header *fw_hdr = (struct fw_header *)fw->data; +- struct fw_mac *pla = NULL, *usb = NULL; +- struct fw_phy_patch_key *start = NULL; +- struct fw_phy_nc *phy_nc = NULL; +- struct fw_block *stop = NULL; ++ unsigned long fw_flags = 0; + long ret = -EFAULT; + int i; + +@@ -3833,50 +3838,52 @@ static long rtl8152_check_firmware(struc + goto fail; + goto fw_end; + case RTL_FW_PLA: +- if (pla) { ++ if (test_bit(FW_FLAGS_PLA, &fw_flags)) { + dev_err(&tp->intf->dev, + "multiple PLA firmware encountered"); + goto fail; + } + +- pla = (struct fw_mac *)block; +- if (!rtl8152_is_fw_mac_ok(tp, pla)) { ++ if (!rtl8152_is_fw_mac_ok(tp, (struct fw_mac *)block)) { + dev_err(&tp->intf->dev, + "check PLA firmware failed\n"); + goto fail; + } ++ __set_bit(FW_FLAGS_PLA, &fw_flags); + break; + case RTL_FW_USB: +- if (usb) { ++ if (test_bit(FW_FLAGS_USB, &fw_flags)) { + dev_err(&tp->intf->dev, + "multiple USB firmware encountered"); + goto fail; + } + +- usb = (struct fw_mac *)block; +- if (!rtl8152_is_fw_mac_ok(tp, usb)) { ++ if (!rtl8152_is_fw_mac_ok(tp, (struct fw_mac *)block)) { + dev_err(&tp->intf->dev, + "check USB firmware failed\n"); + goto fail; + } ++ __set_bit(FW_FLAGS_USB, &fw_flags); + break; + case RTL_FW_PHY_START: +- if (start || phy_nc || stop) { ++ if (test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, + "check PHY_START fail\n"); + goto fail; + } + +- if (__le32_to_cpu(block->length) != sizeof(*start)) { ++ if (__le32_to_cpu(block->length) != sizeof(struct fw_phy_patch_key)) { + dev_err(&tp->intf->dev, + "Invalid length for PHY_START\n"); + goto fail; + } +- +- start = (struct fw_phy_patch_key *)block; ++ __set_bit(FW_FLAGS_START, &fw_flags); + break; + case RTL_FW_PHY_STOP: +- if (stop || !start) { ++ if (test_bit(FW_FLAGS_STOP, &fw_flags) || ++ !test_bit(FW_FLAGS_START, &fw_flags)) { + dev_err(&tp->intf->dev, + "Check PHY_STOP fail\n"); + goto fail; +@@ -3887,28 +3894,28 @@ static long rtl8152_check_firmware(struc + "Invalid length for PHY_STOP\n"); + goto fail; + } +- +- stop = block; ++ __set_bit(FW_FLAGS_STOP, &fw_flags); + break; + case RTL_FW_PHY_NC: +- if (!start || stop) { ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, + "check PHY_NC fail\n"); + goto fail; + } + +- if (phy_nc) { ++ if (test_bit(FW_FLAGS_NC, &fw_flags)) { + dev_err(&tp->intf->dev, + "multiple PHY NC encountered\n"); + goto fail; + } + +- phy_nc = (struct fw_phy_nc *)block; +- if (!rtl8152_is_fw_phy_nc_ok(tp, phy_nc)) { ++ if (!rtl8152_is_fw_phy_nc_ok(tp, (struct fw_phy_nc *)block)) { + dev_err(&tp->intf->dev, + "check PHY NC firmware failed\n"); + goto fail; + } ++ __set_bit(FW_FLAGS_NC, &fw_flags); + + break; + default: +@@ -3922,7 +3929,7 @@ static long rtl8152_check_firmware(struc + } + + fw_end: +- if ((phy_nc || start) && !stop) { ++ if (test_bit(FW_FLAGS_START, &fw_flags) && !test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, "without PHY_STOP\n"); + goto fail; + } diff --git a/target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch b/target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch new file mode 100644 index 0000000000..3559e3b95a --- /dev/null +++ b/target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch @@ -0,0 +1,157 @@ +From f010a7d51cbb42bdb956f0a28b8868b15d7a3816 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 16 Apr 2021 16:04:34 +0800 +Subject: [PATCH] r8152: add help function to change mtu + +commit 67ce1a806f164e59a074fea8809725d3411eaa20 upstream. + +The different chips may have different requests when changing mtu. +Therefore, add a new help function of rtl_ops to change mtu. Besides, +reset the tx/rx after changing mtu. + +Additionally, add mtu_to_size() and size_to_mtu() macros to simplify +the code. + +Signed-off-by: Hayes Wang +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 53 ++++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 22 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -658,15 +658,13 @@ enum rtl_register_content { + + #define INTR_LINK 0x0004 + +-#define RTL8153_MAX_PACKET 9216 /* 9K */ +-#define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \ +- ETH_FCS_LEN) + #define RTL8152_RMS (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) + #define RTL8153_RMS RTL8153_MAX_PACKET + #define RTL8152_TX_TIMEOUT (5 * HZ) + #define RTL8152_NAPI_WEIGHT 64 +-#define rx_reserved_size(x) ((x) + VLAN_ETH_HLEN + ETH_FCS_LEN + \ +- sizeof(struct rx_desc) + RX_ALIGN) ++#define mtu_to_size(m) ((m) + VLAN_ETH_HLEN + ETH_FCS_LEN) ++#define size_to_mtu(s) ((s) - VLAN_ETH_HLEN - ETH_FCS_LEN) ++#define rx_reserved_size(x) (mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN) + + /* rtl8152 flags */ + enum rtl8152_flags { +@@ -796,6 +794,7 @@ struct r8152 { + bool (*in_nway)(struct r8152 *tp); + void (*hw_phy_cfg)(struct r8152 *tp); + void (*autosuspend_en)(struct r8152 *tp, bool enable); ++ void (*change_mtu)(struct r8152 *tp); + } rtl_ops; + + struct ups_info { +@@ -1022,8 +1021,7 @@ enum tx_csum_stat { + static const int multicast_filter_limit = 32; + static unsigned int agg_buf_sz = 16384; + +-#define RTL_LIMITED_TSO_SIZE (agg_buf_sz - sizeof(struct tx_desc) - \ +- VLAN_ETH_HLEN - ETH_FCS_LEN) ++#define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc)) + + static + int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) +@@ -2633,10 +2631,7 @@ static void rtl8152_nic_reset(struct r81 + + static void set_tx_qlen(struct r8152 *tp) + { +- struct net_device *netdev = tp->netdev; +- +- tp->tx_qlen = agg_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN + +- sizeof(struct tx_desc)); ++ tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc)); + } + + static inline u8 rtl8152_get_speed(struct r8152 *tp) +@@ -4725,6 +4720,12 @@ static void r8153b_hw_phy_cfg(struct r81 + set_bit(PHY_RESET, &tp->flags); + } + ++static void rtl8153_change_mtu(struct r8152 *tp) ++{ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); ++} ++ + static void r8153_first_init(struct r8152 *tp) + { + u32 ocp_data; +@@ -4757,9 +4758,7 @@ static void r8153_first_init(struct r815 + + rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); + +- ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); +- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); ++ rtl8153_change_mtu(tp); + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); + ocp_data |= TCR0_AUTO_FIFO; +@@ -4794,8 +4793,7 @@ static void r8153_enter_oob(struct r8152 + + wait_oob_link_list_ready(tp); + +- ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); + + switch (tp->version) { + case RTL_VER_03: +@@ -6518,12 +6516,21 @@ static int rtl8152_change_mtu(struct net + dev->mtu = new_mtu; + + if (netif_running(dev)) { +- u32 rms = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; +- +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rms); ++ if (tp->rtl_ops.change_mtu) ++ tp->rtl_ops.change_mtu(tp); + +- if (netif_carrier_ok(dev)) +- r8153_set_rx_early_size(tp); ++ if (netif_carrier_ok(dev)) { ++ netif_stop_queue(dev); ++ napi_disable(&tp->napi); ++ tasklet_disable(&tp->tx_tl); ++ tp->rtl_ops.disable(tp); ++ tp->rtl_ops.enable(tp); ++ rtl_start_rx(tp); ++ tasklet_enable(&tp->tx_tl); ++ napi_enable(&tp->napi); ++ rtl8152_set_rx_mode(dev); ++ netif_wake_queue(dev); ++ } + } + + mutex_unlock(&tp->control); +@@ -6612,6 +6619,7 @@ static int rtl_ops_init(struct r8152 *tp + ops->in_nway = rtl8153_in_nway; + ops->hw_phy_cfg = r8153_hw_phy_cfg; + ops->autosuspend_en = rtl8153_runtime_enable; ++ ops->change_mtu = rtl8153_change_mtu; + if (tp->udev->speed < USB_SPEED_SUPER) + tp->rx_buf_sz = 16 * 1024; + else +@@ -6633,6 +6641,7 @@ static int rtl_ops_init(struct r8152 *tp + ops->in_nway = rtl8153_in_nway; + ops->hw_phy_cfg = r8153b_hw_phy_cfg; + ops->autosuspend_en = rtl8153b_runtime_enable; ++ ops->change_mtu = rtl8153_change_mtu; + tp->rx_buf_sz = 32 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; +@@ -6853,7 +6862,7 @@ static int rtl8152_probe(struct usb_inte + netdev->max_mtu = ETH_DATA_LEN; + break; + default: +- netdev->max_mtu = RTL8153_MAX_MTU; ++ netdev->max_mtu = size_to_mtu(9 * 1024); + break; + } + diff --git a/target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch b/target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch new file mode 100644 index 0000000000..06a141b451 --- /dev/null +++ b/target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch @@ -0,0 +1,2886 @@ +From e7439e7fd384f55f55837f7e4866e74d8dca3827 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 16 Apr 2021 16:04:35 +0800 +Subject: [PATCH] r8152: support new chips + +commit 195aae321c829dd1945900d75561e6aa79cce208 upstream. + +Support RTL8153C, RTL8153D, RTL8156A, and RTL8156B. The RTL8156A +and RTL8156B are the 2.5G ethernet. + +Signed-off-by: Hayes Wang +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 2634 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 2359 insertions(+), 275 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -44,10 +44,14 @@ + + #define PLA_IDR 0xc000 + #define PLA_RCR 0xc010 ++#define PLA_RCR1 0xc012 + #define PLA_RMS 0xc016 + #define PLA_RXFIFO_CTRL0 0xc0a0 ++#define PLA_RXFIFO_FULL 0xc0a2 + #define PLA_RXFIFO_CTRL1 0xc0a4 ++#define PLA_RX_FIFO_FULL 0xc0a6 + #define PLA_RXFIFO_CTRL2 0xc0a8 ++#define PLA_RX_FIFO_EMPTY 0xc0aa + #define PLA_DMY_REG0 0xc0b0 + #define PLA_FMC 0xc0b4 + #define PLA_CFG_WOL 0xc0b6 +@@ -64,6 +68,8 @@ + #define PLA_MACDBG_PRE 0xd38c /* RTL_VER_04 only */ + #define PLA_MACDBG_POST 0xd38e /* RTL_VER_04 only */ + #define PLA_EXTRA_STATUS 0xd398 ++#define PLA_GPHY_CTRL 0xd3ae ++#define PLA_POL_GPIO_CTRL 0xdc6a + #define PLA_EFUSE_DATA 0xdd00 + #define PLA_EFUSE_CMD 0xdd02 + #define PLA_LEDSEL 0xdd90 +@@ -73,6 +79,8 @@ + #define PLA_LWAKE_CTRL_REG 0xe007 + #define PLA_GPHY_INTR_IMR 0xe022 + #define PLA_EEE_CR 0xe040 ++#define PLA_EEE_TXTWSYS 0xe04c ++#define PLA_EEE_TXTWSYS_2P5G 0xe058 + #define PLA_EEEP_CR 0xe080 + #define PLA_MAC_PWR_CTRL 0xe0c0 + #define PLA_MAC_PWR_CTRL2 0xe0ca +@@ -83,6 +91,7 @@ + #define PLA_TCR1 0xe612 + #define PLA_MTPS 0xe615 + #define PLA_TXFIFO_CTRL 0xe618 ++#define PLA_TXFIFO_FULL 0xe61a + #define PLA_RSTTALLY 0xe800 + #define PLA_CR 0xe813 + #define PLA_CRWECR 0xe81c +@@ -99,6 +108,7 @@ + #define PLA_SFF_STS_7 0xe8de + #define PLA_PHYSTATUS 0xe908 + #define PLA_CONFIG6 0xe90a /* CONFIG6 */ ++#define PLA_USB_CFG 0xe952 + #define PLA_BP_BA 0xfc26 + #define PLA_BP_0 0xfc28 + #define PLA_BP_1 0xfc2a +@@ -113,6 +123,7 @@ + #define USB_USB2PHY 0xb41e + #define USB_SSPHYLINK1 0xb426 + #define USB_SSPHYLINK2 0xb428 ++#define USB_L1_CTRL 0xb45e + #define USB_U2P3_CTRL 0xb460 + #define USB_CSR_DUMMY1 0xb464 + #define USB_CSR_DUMMY2 0xb466 +@@ -123,7 +134,12 @@ + #define USB_FW_FIX_EN0 0xcfca + #define USB_FW_FIX_EN1 0xcfcc + #define USB_LPM_CONFIG 0xcfd8 ++#define USB_ECM_OPTION 0xcfee + #define USB_CSTMR 0xcfef /* RTL8153A */ ++#define USB_MISC_2 0xcfff ++#define USB_ECM_OP 0xd26b ++#define USB_GPHY_CTRL 0xd284 ++#define USB_SPEED_OPTION 0xd32a + #define USB_FW_CTRL 0xd334 /* RTL8153B */ + #define USB_FC_TIMER 0xd340 + #define USB_USB_CTRL 0xd406 +@@ -137,16 +153,20 @@ + #define USB_RX_EXTRA_AGGR_TMR 0xd432 /* RTL8153B */ + #define USB_TX_DMA 0xd434 + #define USB_UPT_RXDMA_OWN 0xd437 ++#define USB_UPHY3_MDCMDIO 0xd480 + #define USB_TOLERANCE 0xd490 + #define USB_LPM_CTRL 0xd41a + #define USB_BMU_RESET 0xd4b0 ++#define USB_BMU_CONFIG 0xd4b4 + #define USB_U1U2_TIMER 0xd4da + #define USB_FW_TASK 0xd4e8 /* RTL8153B */ ++#define USB_RX_AGGR_NUM 0xd4ee + #define USB_UPS_CTRL 0xd800 + #define USB_POWER_CUT 0xd80a + #define USB_MISC_0 0xd81a + #define USB_MISC_1 0xd81f + #define USB_AFE_CTRL2 0xd824 ++#define USB_UPHY_XTAL 0xd826 + #define USB_UPS_CFG 0xd842 + #define USB_UPS_FLAGS 0xd848 + #define USB_WDT1_CTRL 0xe404 +@@ -189,6 +209,9 @@ + #define OCP_EEE_ABLE 0xa5c4 + #define OCP_EEE_ADV 0xa5d0 + #define OCP_EEE_LPABLE 0xa5d2 ++#define OCP_10GBT_CTRL 0xa5d4 ++#define OCP_10GBT_STAT 0xa5d6 ++#define OCP_EEE_ADV2 0xa6d4 + #define OCP_PHY_STATE 0xa708 /* nway state for 8153 */ + #define OCP_PHY_PATCH_STAT 0xb800 + #define OCP_PHY_PATCH_CMD 0xb820 +@@ -200,6 +223,7 @@ + /* SRAM Register */ + #define SRAM_GREEN_CFG 0x8011 + #define SRAM_LPF_CFG 0x8012 ++#define SRAM_GPHY_FW_VER 0x801e + #define SRAM_10M_AMP1 0x8080 + #define SRAM_10M_AMP2 0x8082 + #define SRAM_IMPEDANCE 0x8084 +@@ -211,11 +235,19 @@ + #define RCR_AM 0x00000004 + #define RCR_AB 0x00000008 + #define RCR_ACPT_ALL (RCR_AAP | RCR_APM | RCR_AM | RCR_AB) ++#define SLOT_EN BIT(11) ++ ++/* PLA_RCR1 */ ++#define OUTER_VLAN BIT(7) ++#define INNER_VLAN BIT(6) + + /* PLA_RXFIFO_CTRL0 */ + #define RXFIFO_THR1_NORMAL 0x00080002 + #define RXFIFO_THR1_OOB 0x01800003 + ++/* PLA_RXFIFO_FULL */ ++#define RXFIFO_FULL_MASK 0xfff ++ + /* PLA_RXFIFO_CTRL1 */ + #define RXFIFO_THR2_FULL 0x00000060 + #define RXFIFO_THR2_HIGH 0x00000038 +@@ -286,6 +318,7 @@ + #define MCU_BORW_EN 0x4000 + + /* PLA_CPCR */ ++#define FLOW_CTRL_EN BIT(0) + #define CPCR_RX_VLAN 0x0040 + + /* PLA_CFG_WOL */ +@@ -311,6 +344,10 @@ + /* PLA_CONFIG6 */ + #define LANWAKE_CLR_EN BIT(0) + ++/* PLA_USB_CFG */ ++#define EN_XG_LIP BIT(1) ++#define EN_G_LIP BIT(2) ++ + /* PLA_CONFIG5 */ + #define BWF_EN 0x0040 + #define MWF_EN 0x0020 +@@ -334,6 +371,7 @@ + /* PLA_MAC_PWR_CTRL2 */ + #define EEE_SPDWN_RATIO 0x8007 + #define MAC_CLK_SPDWN_EN BIT(15) ++#define EEE_SPDWN_RATIO_MASK 0xff + + /* PLA_MAC_PWR_CTRL3 */ + #define PLA_MCU_SPDWN_EN BIT(14) +@@ -346,6 +384,7 @@ + #define PWRSAVE_SPDWN_EN 0x1000 + #define RXDV_SPDWN_EN 0x0800 + #define TX10MIDLE_EN 0x0100 ++#define IDLE_SPDWN_EN BIT(6) + #define TP100_SPDWN_EN 0x0020 + #define TP500_SPDWN_EN 0x0010 + #define TP1000_SPDWN_EN 0x0008 +@@ -386,6 +425,13 @@ + #define LINK_CHANGE_FLAG BIT(8) + #define POLL_LINK_CHG BIT(0) + ++/* PLA_GPHY_CTRL */ ++#define GPHY_FLASH BIT(1) ++ ++/* PLA_POL_GPIO_CTRL */ ++#define DACK_DET_EN BIT(15) ++#define POL_GPHY_PATCH BIT(4) ++ + /* USB_USB2PHY */ + #define USB2PHY_SUSPEND 0x0001 + #define USB2PHY_L1 0x0002 +@@ -434,6 +480,9 @@ + #define BMU_RESET_EP_IN 0x01 + #define BMU_RESET_EP_OUT 0x02 + ++/* USB_BMU_CONFIG */ ++#define ACT_ODMA BIT(1) ++ + /* USB_UPT_RXDMA_OWN */ + #define OWN_UPDATE BIT(0) + #define OWN_CLEAR BIT(1) +@@ -441,27 +490,52 @@ + /* USB_FW_TASK */ + #define FC_PATCH_TASK BIT(1) + ++/* USB_RX_AGGR_NUM */ ++#define RX_AGGR_NUM_MASK 0x1ff ++ + /* USB_UPS_CTRL */ + #define POWER_CUT 0x0100 + + /* USB_PM_CTRL_STATUS */ + #define RESUME_INDICATE 0x0001 + ++/* USB_ECM_OPTION */ ++#define BYPASS_MAC_RESET BIT(5) ++ + /* USB_CSTMR */ + #define FORCE_SUPER BIT(0) + ++/* USB_MISC_2 */ ++#define UPS_FORCE_PWR_DOWN BIT(0) ++ ++/* USB_ECM_OP */ ++#define EN_ALL_SPEED BIT(0) ++ ++/* USB_GPHY_CTRL */ ++#define GPHY_PATCH_DONE BIT(2) ++#define BYPASS_FLASH BIT(5) ++#define BACKUP_RESTRORE BIT(6) ++ ++/* USB_SPEED_OPTION */ ++#define RG_PWRDN_EN BIT(8) ++#define ALL_SPEED_OFF BIT(9) ++ + /* USB_FW_CTRL */ + #define FLOW_CTRL_PATCH_OPT BIT(1) ++#define AUTO_SPEEDUP BIT(3) ++#define FLOW_CTRL_PATCH_2 BIT(8) + + /* USB_FC_TIMER */ + #define CTRL_TIMER_EN BIT(15) + + /* USB_USB_CTRL */ ++#define CDC_ECM_EN BIT(3) + #define RX_AGG_DISABLE 0x0010 + #define RX_ZERO_EN 0x0080 + + /* USB_U2P3_CTRL */ + #define U2P3_ENABLE 0x0001 ++#define RX_DETECT8 BIT(3) + + /* USB_POWER_CUT */ + #define PWR_EN 0x0001 +@@ -497,8 +571,12 @@ + #define SEN_VAL_NORMAL 0xa000 + #define SEL_RXIDLE 0x0100 + ++/* USB_UPHY_XTAL */ ++#define OOBS_POLLING BIT(8) ++ + /* USB_UPS_CFG */ + #define SAW_CNT_1MS_MASK 0x0fff ++#define MID_REVERSE BIT(5) /* RTL8156A */ + + /* USB_UPS_FLAGS */ + #define UPS_FLAGS_R_TUNE BIT(0) +@@ -506,6 +584,7 @@ + #define UPS_FLAGS_250M_CKDIV BIT(2) + #define UPS_FLAGS_EN_ALDPS BIT(3) + #define UPS_FLAGS_CTAP_SHORT_DIS BIT(4) ++#define UPS_FLAGS_SPEED_MASK (0xf << 16) + #define ups_flags_speed(x) ((x) << 16) + #define UPS_FLAGS_EN_EEE BIT(20) + #define UPS_FLAGS_EN_500M_EEE BIT(21) +@@ -526,6 +605,8 @@ enum spd_duplex { + FORCE_10M_FULL, + FORCE_100M_HALF, + FORCE_100M_FULL, ++ FORCE_1000M_FULL, ++ NWAY_2500M_FULL, + }; + + /* OCP_ALDPS_CONFIG */ +@@ -590,6 +671,9 @@ enum spd_duplex { + #define EN_10M_CLKDIV BIT(11) + #define EN_10M_BGOFF 0x0080 + ++/* OCP_10GBT_CTRL */ ++#define RTL_ADV2_5G_F_R BIT(5) /* Advertise 2.5GBASE-T fast-retrain */ ++ + /* OCP_PHY_STATE */ + #define TXDIS_STATE 0x01 + #define ABD_STATE 0x02 +@@ -609,7 +693,8 @@ enum spd_duplex { + #define EN_EMI_L 0x0040 + + /* OCP_SYSCLK_CFG */ +-#define clk_div_expo(x) (min(x, 5) << 8) ++#define sysclk_div_expo(x) (min(x, 5) << 8) ++#define clk_div_expo(x) (min(x, 5) << 4) + + /* SRAM_GREEN_CFG */ + #define GREEN_ETH_EN BIT(15) +@@ -640,6 +725,11 @@ enum spd_duplex { + #define BP4_SUPER_ONLY 0x1578 /* RTL_VER_04 only */ + + enum rtl_register_content { ++ _2500bps = BIT(10), ++ _1250bps = BIT(9), ++ _500bps = BIT(8), ++ _tx_flow = BIT(6), ++ _rx_flow = BIT(5), + _1000bps = 0x10, + _100bps = 0x08, + _10bps = 0x04, +@@ -647,6 +737,9 @@ enum rtl_register_content { + FULL_DUP = 0x01, + }; + ++#define is_speed_2500(_speed) (((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS)) ++#define is_flow_control(_speed) (((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow)) ++ + #define RTL8152_MAX_TX 4 + #define RTL8152_MAX_RX 10 + #define INTBUFSIZE 2 +@@ -661,7 +754,6 @@ enum rtl_register_content { + #define RTL8152_RMS (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) + #define RTL8153_RMS RTL8153_MAX_PACKET + #define RTL8152_TX_TIMEOUT (5 * HZ) +-#define RTL8152_NAPI_WEIGHT 64 + #define mtu_to_size(m) ((m) + VLAN_ETH_HLEN + ETH_FCS_LEN) + #define size_to_mtu(s) ((s) - VLAN_ETH_HLEN - ETH_FCS_LEN) + #define rx_reserved_size(x) (mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN) +@@ -798,6 +890,7 @@ struct r8152 { + } rtl_ops; + + struct ups_info { ++ u32 r_tune:1; + u32 _10m_ckdiv:1; + u32 _250m_ckdiv:1; + u32 aldps:1; +@@ -839,7 +932,9 @@ struct r8152 { + u32 rx_buf_sz; + u32 rx_copybreak; + u32 rx_pending; ++ u32 fc_pause_on, fc_pause_off; + ++ u32 support_2500full:1; + u16 ocp_base; + u16 speed; + u16 eee_adv; +@@ -999,6 +1094,15 @@ enum rtl_version { + RTL_VER_07, + RTL_VER_08, + RTL_VER_09, ++ ++ RTL_TEST_01, ++ RTL_VER_10, ++ RTL_VER_11, ++ RTL_VER_12, ++ RTL_VER_13, ++ RTL_VER_14, ++ RTL_VER_15, ++ + RTL_VER_MAX + }; + +@@ -1014,6 +1118,7 @@ enum tx_csum_stat { + #define RTL_ADVERTISED_100_FULL BIT(3) + #define RTL_ADVERTISED_1000_HALF BIT(4) + #define RTL_ADVERTISED_1000_FULL BIT(5) ++#define RTL_ADVERTISED_2500_FULL BIT(6) + + /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + * The RTL chips use a 64 element hash table based on the Ethernet CRC. +@@ -2607,7 +2712,7 @@ static netdev_tx_t rtl8152_start_xmit(st + + static void r8152b_reset_packet_filter(struct r8152 *tp) + { +- u32 ocp_data; ++ u32 ocp_data; + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC); + ocp_data &= ~FMC_FCR_MCU_EN; +@@ -2618,14 +2723,47 @@ static void r8152b_reset_packet_filter(s + + static void rtl8152_nic_reset(struct r8152 *tp) + { +- int i; ++ u32 ocp_data; ++ int i; + +- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST); ++ switch (tp->version) { ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); ++ ocp_data &= ~CR_TE; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_RESET); ++ ocp_data &= ~BMU_RESET_EP_IN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data |= CDC_ECM_EN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); ++ ocp_data &= ~CR_RE; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_RESET); ++ ocp_data |= BMU_RESET_EP_IN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~CDC_ECM_EN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ break; + +- for (i = 0; i < 1000; i++) { +- if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST)) +- break; +- usleep_range(100, 400); ++ default: ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST); ++ ++ for (i = 0; i < 1000; i++) { ++ if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST)) ++ break; ++ usleep_range(100, 400); ++ } ++ break; + } + } + +@@ -2634,9 +2772,9 @@ static void set_tx_qlen(struct r8152 *tp + tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc)); + } + +-static inline u8 rtl8152_get_speed(struct r8152 *tp) ++static inline u16 rtl8152_get_speed(struct r8152 *tp) + { +- return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); ++ return ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); + } + + static void rtl_eee_plus_en(struct r8152 *tp, bool enable) +@@ -2796,6 +2934,7 @@ static int rtl_enable(struct r8152 *tp) + switch (tp->version) { + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + r8153b_rx_agg_chg_indicate(tp); + break; + default: +@@ -2833,6 +2972,7 @@ static void r8153_set_rx_early_timeout(s + + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + /* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout + * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 128ns. + */ +@@ -2842,6 +2982,18 @@ static void r8153_set_rx_early_timeout(s + ocp_data); + break; + ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, ++ 640 / 8); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR, ++ ocp_data); ++ r8153b_rx_agg_chg_indicate(tp); ++ break; ++ + default: + break; + } +@@ -2861,8 +3013,19 @@ static void r8153_set_rx_early_size(stru + break; + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ++ ocp_data / 8); ++ break; ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: + ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, + ocp_data / 8); ++ r8153b_rx_agg_chg_indicate(tp); + break; + default: + WARN_ON_ONCE(1); +@@ -2872,6 +3035,8 @@ static void r8153_set_rx_early_size(stru + + static int rtl8153_enable(struct r8152 *tp) + { ++ u32 ocp_data; ++ + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return -ENODEV; + +@@ -2882,15 +3047,18 @@ static int rtl8153_enable(struct r8152 * + + rtl_set_ifg(tp, rtl8152_get_speed(tp)); + +- if (tp->version == RTL_VER_09) { +- u32 ocp_data; +- ++ switch (tp->version) { ++ case RTL_VER_09: ++ case RTL_VER_14: + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); + ocp_data &= ~FC_PATCH_TASK; + ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); + usleep_range(1000, 2000); + ocp_data |= FC_PATCH_TASK; + ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ break; ++ default: ++ break; + } + + return rtl_enable(tp); +@@ -2955,12 +3123,40 @@ static void rtl_rx_vlan_en(struct r8152 + { + u32 ocp_data; + +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); +- if (enable) +- ocp_data |= CPCR_RX_VLAN; +- else +- ocp_data &= ~CPCR_RX_VLAN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); ++ switch (tp->version) { ++ case RTL_VER_01: ++ case RTL_VER_02: ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ case RTL_VER_07: ++ case RTL_VER_08: ++ case RTL_VER_09: ++ case RTL_VER_14: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); ++ if (enable) ++ ocp_data |= CPCR_RX_VLAN; ++ else ++ ocp_data &= ~CPCR_RX_VLAN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); ++ break; ++ ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ default: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR1); ++ if (enable) ++ ocp_data |= OUTER_VLAN | INNER_VLAN; ++ else ++ ocp_data &= ~(OUTER_VLAN | INNER_VLAN); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR1, ocp_data); ++ break; ++ } + } + + static int rtl8152_set_features(struct net_device *dev, +@@ -3053,6 +3249,40 @@ static void __rtl_set_wol(struct r8152 * + device_set_wakeup_enable(&tp->udev->dev, false); + } + ++static void r8153_mac_clk_speed_down(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); ++ ++ /* MAC clock speed down */ ++ if (enable) ++ ocp_data |= MAC_CLK_SPDWN_EN; ++ else ++ ocp_data &= ~MAC_CLK_SPDWN_EN; ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++} ++ ++static void r8156_mac_clk_spd(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data; ++ ++ /* MAC clock speed down */ ++ if (enable) { ++ /* aldps_spdwn_ratio, tp10_spdwn_ratio */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ++ 0x0403); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); ++ ocp_data &= ~EEE_SPDWN_RATIO_MASK; ++ ocp_data |= MAC_CLK_SPDWN_EN | 0x03; /* eee_spdwn_ratio */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++ } else { ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); ++ ocp_data &= ~MAC_CLK_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++ } ++} ++ + static void r8153_u1u2en(struct r8152 *tp, bool enable) + { + u8 u1u2[8]; +@@ -3112,6 +3342,9 @@ static void r8153b_ups_flags(struct r815 + if (tp->ups_info.eee_cmod_lv) + ups_flags |= UPS_FLAGS_EEE_CMOD_LV_EN; + ++ if (tp->ups_info.r_tune) ++ ups_flags |= UPS_FLAGS_R_TUNE; ++ + if (tp->ups_info._10m_ckdiv) + ups_flags |= UPS_FLAGS_EN_10M_CKDIV; + +@@ -3162,6 +3395,88 @@ static void r8153b_ups_flags(struct r815 + ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); + } + ++static void r8156_ups_flags(struct r8152 *tp) ++{ ++ u32 ups_flags = 0; ++ ++ if (tp->ups_info.green) ++ ups_flags |= UPS_FLAGS_EN_GREEN; ++ ++ if (tp->ups_info.aldps) ++ ups_flags |= UPS_FLAGS_EN_ALDPS; ++ ++ if (tp->ups_info.eee) ++ ups_flags |= UPS_FLAGS_EN_EEE; ++ ++ if (tp->ups_info.flow_control) ++ ups_flags |= UPS_FLAGS_EN_FLOW_CTR; ++ ++ if (tp->ups_info.eee_ckdiv) ++ ups_flags |= UPS_FLAGS_EN_EEE_CKDIV; ++ ++ if (tp->ups_info._10m_ckdiv) ++ ups_flags |= UPS_FLAGS_EN_10M_CKDIV; ++ ++ if (tp->ups_info.eee_plloff_100) ++ ups_flags |= UPS_FLAGS_EEE_PLLOFF_100; ++ ++ if (tp->ups_info.eee_plloff_giga) ++ ups_flags |= UPS_FLAGS_EEE_PLLOFF_GIGA; ++ ++ if (tp->ups_info._250m_ckdiv) ++ ups_flags |= UPS_FLAGS_250M_CKDIV; ++ ++ switch (tp->ups_info.speed_duplex) { ++ case FORCE_10M_HALF: ++ ups_flags |= ups_flags_speed(0); ++ break; ++ case FORCE_10M_FULL: ++ ups_flags |= ups_flags_speed(1); ++ break; ++ case FORCE_100M_HALF: ++ ups_flags |= ups_flags_speed(2); ++ break; ++ case FORCE_100M_FULL: ++ ups_flags |= ups_flags_speed(3); ++ break; ++ case NWAY_10M_HALF: ++ ups_flags |= ups_flags_speed(4); ++ break; ++ case NWAY_10M_FULL: ++ ups_flags |= ups_flags_speed(5); ++ break; ++ case NWAY_100M_HALF: ++ ups_flags |= ups_flags_speed(6); ++ break; ++ case NWAY_100M_FULL: ++ ups_flags |= ups_flags_speed(7); ++ break; ++ case NWAY_1000M_FULL: ++ ups_flags |= ups_flags_speed(8); ++ break; ++ case NWAY_2500M_FULL: ++ ups_flags |= ups_flags_speed(9); ++ break; ++ default: ++ break; ++ } ++ ++ switch (tp->ups_info.lite_mode) { ++ case 1: ++ ups_flags |= 0 << 5; ++ break; ++ case 2: ++ ups_flags |= 2 << 5; ++ break; ++ case 0: ++ default: ++ ups_flags |= 1 << 5; ++ break; ++ } ++ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); ++} ++ + static void rtl_green_en(struct r8152 *tp, bool enable) + { + u16 data; +@@ -3225,16 +3540,16 @@ static void r8153b_ups_en(struct r8152 * + ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; + ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + +- ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff); +- ocp_data |= BIT(0); +- ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data |= UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); + } else { + ocp_data &= ~(UPS_EN | USP_PREWAKE); + ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + +- ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff); +- ocp_data &= ~BIT(0); +- ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); + + if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { + int i; +@@ -3254,6 +3569,95 @@ static void r8153b_ups_en(struct r8152 * + } + } + ++static void r8153c_ups_en(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT); ++ ++ if (enable) { ++ r8153b_ups_flags(tp); ++ ++ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data |= UPS_FORCE_PWR_DOWN; ++ ocp_data &= ~BIT(7); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ } else { ++ ocp_data &= ~(UPS_EN | USP_PREWAKE); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { ++ int i; ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ msleep(20); ++ } ++ ++ tp->rtl_ops.hw_phy_cfg(tp); ++ ++ rtl8152_set_speed(tp, tp->autoneg, tp->speed, ++ tp->duplex, tp->advertising); ++ } ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); ++ ocp_data |= BIT(8); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); ++ } ++} ++ ++static void r8156_ups_en(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT); ++ ++ if (enable) { ++ r8156_ups_flags(tp); ++ ++ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data |= UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ switch (tp->version) { ++ case RTL_VER_13: ++ case RTL_VER_15: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPHY_XTAL); ++ ocp_data &= ~OOBS_POLLING; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_UPHY_XTAL, ocp_data); ++ break; ++ default: ++ break; ++ } ++ } else { ++ ocp_data &= ~(UPS_EN | USP_PREWAKE); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { ++ tp->rtl_ops.hw_phy_cfg(tp); ++ ++ rtl8152_set_speed(tp, tp->autoneg, tp->speed, ++ tp->duplex, tp->advertising); ++ } ++ } ++} ++ + static void r8153_power_cut_en(struct r8152 *tp, bool enable) + { + u32 ocp_data; +@@ -3383,6 +3787,38 @@ static void rtl8153b_runtime_enable(stru + } + } + ++static void rtl8153c_runtime_enable(struct r8152 *tp, bool enable) ++{ ++ if (enable) { ++ r8153_queue_wake(tp, true); ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ rtl_runtime_suspend_enable(tp, true); ++ r8153c_ups_en(tp, true); ++ } else { ++ r8153c_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ r8153b_u1u2en(tp, true); ++ } ++} ++ ++static void rtl8156_runtime_enable(struct r8152 *tp, bool enable) ++{ ++ if (enable) { ++ r8153_queue_wake(tp, true); ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ rtl_runtime_suspend_enable(tp, true); ++ } else { ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ r8153_u2p3en(tp, true); ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++ } ++} ++ + static void r8153_teredo_off(struct r8152 *tp) + { + u32 ocp_data; +@@ -3403,14 +3839,19 @@ static void r8153_teredo_off(struct r815 + + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: ++ default: + /* The bit 0 ~ 7 are relative with teredo settings. They are + * W1C (write 1 to clear), so set all 1 to disable it. + */ + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, 0xff); + break; +- +- default: +- break; + } + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE); +@@ -3445,6 +3886,12 @@ static void rtl_clear_bp(struct r8152 *t + break; + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: + default: + if (type == MCU_TYPE_USB) { + ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); +@@ -3654,6 +4101,11 @@ static bool rtl8152_is_fw_mac_ok(struct + case RTL_VER_06: + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: + fw_reg = 0xf800; + bp_ba_addr = PLA_BP_BA; + bp_en_addr = PLA_BP_EN; +@@ -3677,6 +4129,11 @@ static bool rtl8152_is_fw_mac_ok(struct + break; + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: + fw_reg = 0xe600; + bp_ba_addr = USB_BP_BA; + bp_en_addr = USB_BP2_EN; +@@ -4216,6 +4673,22 @@ static void r8153_eee_en(struct r8152 *t + tp->ups_info.eee = enable; + } + ++static void r8156_eee_en(struct r8152 *tp, bool enable) ++{ ++ u16 config; ++ ++ r8153_eee_en(tp, enable); ++ ++ config = ocp_reg_read(tp, OCP_EEE_ADV2); ++ ++ if (enable) ++ config |= MDIO_EEE_2_5GT; ++ else ++ config &= ~MDIO_EEE_2_5GT; ++ ++ ocp_reg_write(tp, OCP_EEE_ADV2, config); ++} ++ + static void rtl_eee_enable(struct r8152 *tp, bool enable) + { + switch (tp->version) { +@@ -4237,6 +4710,7 @@ static void rtl_eee_enable(struct r8152 + case RTL_VER_06: + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + if (enable) { + r8153_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); +@@ -4245,6 +4719,19 @@ static void rtl_eee_enable(struct r8152 + ocp_reg_write(tp, OCP_EEE_ADV, 0); + } + break; ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ if (enable) { ++ r8156_eee_en(tp, true); ++ ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); ++ } else { ++ r8156_eee_en(tp, false); ++ ocp_reg_write(tp, OCP_EEE_ADV, 0); ++ } ++ break; + default: + break; + } +@@ -4291,6 +4778,20 @@ static void wait_oob_link_list_ready(str + } + } + ++static void r8156b_wait_loading_flash(struct r8152 *tp) ++{ ++ if ((ocp_read_word(tp, MCU_TYPE_PLA, PLA_GPHY_CTRL) & GPHY_FLASH) && ++ !(ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL) & BYPASS_FLASH)) { ++ int i; ++ ++ for (i = 0; i < 100; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL) & GPHY_PATCH_DONE) ++ break; ++ usleep_range(1000, 2000); ++ } ++ } ++} ++ + static void r8152b_exit_oob(struct r8152 *tp) + { + u32 ocp_data; +@@ -4341,7 +4842,7 @@ static void r8152b_exit_oob(struct r8152 + } + + /* TX share fifo free credit full threshold */ +- ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL); ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2); + + ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD); + ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH); +@@ -4518,6 +5019,21 @@ static int r8153b_post_firmware_1(struct + return 0; + } + ++static int r8153c_post_firmware_1(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL); ++ ocp_data |= FLOW_CTRL_PATCH_2; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); ++ ocp_data |= FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ ++ return 0; ++} ++ + static void r8153_aldps_en(struct r8152 *tp, bool enable) + { + u16 data; +@@ -4720,6 +5236,13 @@ static void r8153b_hw_phy_cfg(struct r81 + set_bit(PHY_RESET, &tp->flags); + } + ++static void r8153c_hw_phy_cfg(struct r8152 *tp) ++{ ++ r8153b_hw_phy_cfg(tp); ++ ++ tp->ups_info.r_tune = true; ++} ++ + static void rtl8153_change_mtu(struct r8152 *tp) + { + ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); +@@ -4807,6 +5330,7 @@ static void r8153_enter_oob(struct r8152 + + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + /* Clear teredo wake event. bit[15:8] is the teredo wakeup + * type. Set it to zero. bits[7:0] are the W1C bits about + * the events. Set them to all 1 to clear them. +@@ -4843,6 +5367,96 @@ static void rtl8153_disable(struct r8152 + r8153_aldps_en(tp, true); + } + ++static int rtl8156_enable(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 speed; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return -ENODEV; ++ ++ set_tx_qlen(tp); ++ rtl_set_eee_plus(tp); ++ r8153_set_rx_early_timeout(tp); ++ r8153_set_rx_early_size(tp); ++ ++ speed = rtl8152_get_speed(tp); ++ rtl_set_ifg(tp, speed); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ if (speed & _2500bps) ++ ocp_data &= ~IDLE_SPDWN_EN; ++ else ++ ocp_data |= IDLE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ if (speed & _1000bps) ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11); ++ else if (speed & _500bps) ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d); ++ ++ if (tp->udev->speed == USB_SPEED_HIGH) { ++ /* USB 0xb45e[3:0] l1_nyet_hird */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL); ++ ocp_data &= ~0xf; ++ if (is_flow_control(speed)) ++ ocp_data |= 0xf; ++ else ++ ocp_data |= 0x1; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data); ++ } ++ ++ return rtl_enable(tp); ++} ++ ++static int rtl8156b_enable(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 speed; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return -ENODEV; ++ ++ set_tx_qlen(tp); ++ rtl_set_eee_plus(tp); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM); ++ ocp_data &= ~RX_AGGR_NUM_MASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, ocp_data); ++ ++ r8153_set_rx_early_timeout(tp); ++ r8153_set_rx_early_size(tp); ++ ++ speed = rtl8152_get_speed(tp); ++ rtl_set_ifg(tp, speed); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ if (speed & _2500bps) ++ ocp_data &= ~IDLE_SPDWN_EN; ++ else ++ ocp_data |= IDLE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ if (tp->udev->speed == USB_SPEED_HIGH) { ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL); ++ ocp_data &= ~0xf; ++ if (is_flow_control(speed)) ++ ocp_data |= 0xf; ++ else ++ ocp_data |= 0x1; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data); ++ } ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); ++ ocp_data &= ~FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ usleep_range(1000, 2000); ++ ocp_data |= FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ ++ return rtl_enable(tp); ++} ++ + static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, + u32 advertising) + { +@@ -4891,58 +5505,73 @@ static int rtl8152_set_speed(struct r815 + + tp->mii.force_media = 1; + } else { +- u16 anar, tmp1; ++ u16 orig, new1; + u32 support; + + support = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | + RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; + +- if (tp->mii.supports_gmii) ++ if (tp->mii.supports_gmii) { + support |= RTL_ADVERTISED_1000_FULL; + ++ if (tp->support_2500full) ++ support |= RTL_ADVERTISED_2500_FULL; ++ } ++ + if (!(advertising & support)) + return -EINVAL; + +- anar = r8152_mdio_read(tp, MII_ADVERTISE); +- tmp1 = anar & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | ++ orig = r8152_mdio_read(tp, MII_ADVERTISE); ++ new1 = orig & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL); + if (advertising & RTL_ADVERTISED_10_HALF) { +- tmp1 |= ADVERTISE_10HALF; ++ new1 |= ADVERTISE_10HALF; + tp->ups_info.speed_duplex = NWAY_10M_HALF; + } + if (advertising & RTL_ADVERTISED_10_FULL) { +- tmp1 |= ADVERTISE_10FULL; ++ new1 |= ADVERTISE_10FULL; + tp->ups_info.speed_duplex = NWAY_10M_FULL; + } + + if (advertising & RTL_ADVERTISED_100_HALF) { +- tmp1 |= ADVERTISE_100HALF; ++ new1 |= ADVERTISE_100HALF; + tp->ups_info.speed_duplex = NWAY_100M_HALF; + } + if (advertising & RTL_ADVERTISED_100_FULL) { +- tmp1 |= ADVERTISE_100FULL; ++ new1 |= ADVERTISE_100FULL; + tp->ups_info.speed_duplex = NWAY_100M_FULL; + } + +- if (anar != tmp1) { +- r8152_mdio_write(tp, MII_ADVERTISE, tmp1); +- tp->mii.advertising = tmp1; ++ if (orig != new1) { ++ r8152_mdio_write(tp, MII_ADVERTISE, new1); ++ tp->mii.advertising = new1; + } + + if (tp->mii.supports_gmii) { +- u16 gbcr; +- +- gbcr = r8152_mdio_read(tp, MII_CTRL1000); +- tmp1 = gbcr & ~(ADVERTISE_1000FULL | ++ orig = r8152_mdio_read(tp, MII_CTRL1000); ++ new1 = orig & ~(ADVERTISE_1000FULL | + ADVERTISE_1000HALF); + + if (advertising & RTL_ADVERTISED_1000_FULL) { +- tmp1 |= ADVERTISE_1000FULL; ++ new1 |= ADVERTISE_1000FULL; + tp->ups_info.speed_duplex = NWAY_1000M_FULL; + } + +- if (gbcr != tmp1) +- r8152_mdio_write(tp, MII_CTRL1000, tmp1); ++ if (orig != new1) ++ r8152_mdio_write(tp, MII_CTRL1000, new1); ++ } ++ ++ if (tp->support_2500full) { ++ orig = ocp_reg_read(tp, OCP_10GBT_CTRL); ++ new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ if (advertising & RTL_ADVERTISED_2500_FULL) { ++ new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G; ++ tp->ups_info.speed_duplex = NWAY_2500M_FULL; ++ } ++ ++ if (orig != new1) ++ ocp_reg_write(tp, OCP_10GBT_CTRL, new1); + } + + bmcr = BMCR_ANENABLE | BMCR_ANRESTART; +@@ -5098,6 +5727,253 @@ static void rtl8153b_down(struct r8152 * + r8153_aldps_en(tp, true); + } + ++static void rtl8153c_change_mtu(struct r8152 *tp) ++{ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, 10 * 1024 / 64); ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64); ++ ++ /* Adjust the tx fifo free credit full threshold, otherwise ++ * the fifo would be too small to send a jumbo frame packet. ++ */ ++ if (tp->netdev->mtu < 8000) ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, 2048 / 8); ++ else ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, 900 / 8); ++} ++ ++static void rtl8153c_up(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ r8153_aldps_en(tp, false); ++ ++ rxdy_gated_en(tp, true); ++ r8153_teredo_off(tp); ++ ++ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data &= ~RCR_ACPT_ALL; ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ rtl8152_nic_reset(tp); ++ rtl_reset_bmu(tp); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data &= ~NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); ++ ocp_data &= ~MCU_BORW_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); ++ ++ wait_oob_link_list_ready(tp); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); ++ ocp_data |= RE_INIT_LL; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); ++ ++ wait_oob_link_list_ready(tp); ++ ++ rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); ++ ++ rtl8153c_change_mtu(tp); ++ ++ rtl8152_nic_reset(tp); ++ ++ /* rx share fifo credit full threshold */ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, 0x02); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 0x08); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL); ++ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B); ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); ++ ocp_data |= BIT(8); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ r8153_aldps_en(tp, true); ++ r8153b_u1u2en(tp, true); ++} ++ ++static inline u32 fc_pause_on_auto(struct r8152 *tp) ++{ ++ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024); ++} ++ ++static inline u32 fc_pause_off_auto(struct r8152 *tp) ++{ ++ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024); ++} ++ ++static void r8156_fc_parameter(struct r8152 *tp) ++{ ++ u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp); ++ u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp); ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 8); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 8); ++ break; ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void rtl8156_change_mtu(struct r8152 *tp) ++{ ++ u32 rx_max_size = mtu_to_size(tp->netdev->mtu); ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rx_max_size); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); ++ r8156_fc_parameter(tp); ++ ++ /* TX share fifo free credit full threshold */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, ++ ALIGN(rx_max_size + sizeof(struct tx_desc), 1024) / 16); ++} ++ ++static void rtl8156_up(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ r8153_aldps_en(tp, false); ++ ++ rxdy_gated_en(tp, true); ++ r8153_teredo_off(tp); ++ ++ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data &= ~RCR_ACPT_ALL; ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ rtl8152_nic_reset(tp); ++ rtl_reset_bmu(tp); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data &= ~NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); ++ ocp_data &= ~MCU_BORW_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); ++ ++ rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); ++ ++ rtl8156_change_mtu(tp); ++ ++ switch (tp->version) { ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG); ++ ocp_data |= ACT_ODMA; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); ++ break; ++ default: ++ break; ++ } ++ ++ /* share FIFO settings */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL); ++ ocp_data &= ~RXFIFO_FULL_MASK; ++ ocp_data |= 0x08; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION); ++ ocp_data &= ~(RG_PWRDN_EN | ALL_SPEED_OFF); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, ocp_data); ++ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400); ++ ++ if (tp->saved_wolopts != __rtl_get_wol(tp)) { ++ netif_warn(tp, ifup, tp->netdev, "wol setting is changed\n"); ++ __rtl_set_wol(tp, tp->saved_wolopts); ++ } ++ ++ r8153_aldps_en(tp, true); ++ r8153_u2p3en(tp, true); ++ ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++} ++ ++static void rtl8156_down(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) { ++ rtl_drop_queued_tx(tp); ++ return; ++ } ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data |= PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ r8153b_power_cut_en(tp, false); ++ r8153_aldps_en(tp, false); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data &= ~NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ rtl_disable(tp); ++ rtl_reset_bmu(tp); ++ ++ /* Clear teredo wake event. bit[15:8] is the teredo wakeup ++ * type. Set it to zero. bits[7:0] are the W1C bits about ++ * the events. Set them to all 1 to clear them. ++ */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data |= NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ rtl_rx_vlan_en(tp, true); ++ rxdy_gated_en(tp, false); ++ ++ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data |= RCR_APM | RCR_AM | RCR_AB; ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ r8153_aldps_en(tp, true); ++} ++ + static bool rtl8152_in_nway(struct r8152 *tp) + { + u16 nway_state; +@@ -5128,7 +6004,7 @@ static void set_carrier(struct r8152 *tp + { + struct net_device *netdev = tp->netdev; + struct napi_struct *napi = &tp->napi; +- u8 speed; ++ u16 speed; + + speed = rtl8152_get_speed(tp); + +@@ -5141,7 +6017,7 @@ static void set_carrier(struct r8152 *tp + rtl_start_rx(tp); + clear_bit(RTL8152_SET_RX_MODE, &tp->flags); + _rtl8152_set_rx_mode(netdev); +- napi_enable(&tp->napi); ++ napi_enable(napi); + netif_wake_queue(netdev); + netif_info(tp, link, netdev, "carrier on\n"); + } else if (netif_queue_stopped(netdev) && +@@ -5521,14 +6397,9 @@ static void r8153_init(struct r8152 *tp) + + ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); + +- /* MAC clock speed down */ +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0); +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0); +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0); +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0); +- + r8153_power_cut_en(tp, false); + rtl_runtime_suspend_enable(tp, false); ++ r8153_mac_clk_speed_down(tp, false); + r8153_u1u2en(tp, true); + usb_enable_lpm(tp->udev); + +@@ -5621,9 +6492,7 @@ static void r8153b_init(struct r8152 *tp + usb_enable_lpm(tp->udev); + + /* MAC clock speed down */ +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); +- ocp_data |= MAC_CLK_SPDWN_EN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++ r8153_mac_clk_speed_down(tp, true); + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); + ocp_data &= ~PLA_MCU_SPDWN_EN; +@@ -5652,6 +6521,1069 @@ static void r8153b_init(struct r8152 *tp + r8152_led_configuration(tp); + } + ++static void r8153c_init(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ int i; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ r8153b_u1u2en(tp, false); ++ ++ /* Disable spi_en */ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5); ++ ocp_data &= ~BIT(3); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data); ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, 0xcbf0); ++ ocp_data |= BIT(1); ++ ocp_write_word(tp, MCU_TYPE_USB, 0xcbf0, ocp_data); ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ ++ msleep(20); ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ ++ r8153_u2p3en(tp, false); ++ ++ /* MSC timer = 0xfff * 8ms = 32760 ms */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); ++ ++ r8153b_power_cut_en(tp, false); ++ r8153c_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); ++ if (rtl8152_get_speed(tp) & LINK_STATUS) ++ ocp_data |= CUR_LINK_OK; ++ else ++ ocp_data &= ~CUR_LINK_OK; ++ ++ ocp_data |= POLL_LINK_CHG; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); ++ ++ r8153b_u1u2en(tp, true); ++ ++ usb_enable_lpm(tp->udev); ++ ++ /* MAC clock speed down */ ++ r8153_mac_clk_speed_down(tp, true); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~BIT(7); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ set_bit(GREEN_ETHERNET, &tp->flags); ++ ++ /* rx aggregation */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ rtl_tally_reset(tp); ++ ++ tp->coalesce = 15000; /* 15 us */ ++} ++ ++static void r8156_hw_phy_cfg(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); ++ if (ocp_data & PCUT_STATUS) { ++ ocp_data &= ~PCUT_STATUS; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ switch (data) { ++ case PHY_STAT_EXT_INIT: ++ rtl8152_apply_firmware(tp, true); ++ ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ break; ++ case PHY_STAT_LAN_ON: ++ case PHY_STAT_PWRDN: ++ default: ++ rtl8152_apply_firmware(tp, false); ++ break; ++ } ++ ++ /* disable ALDPS before updating the PHY parameters */ ++ r8153_aldps_en(tp, false); ++ ++ /* disable EEE before updating the PHY parameters */ ++ rtl_eee_enable(tp, false); ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); ++ ocp_data |= PFM_PWM_SWITCH; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ data = ocp_reg_read(tp, 0xad40); ++ data &= ~0x3ff; ++ data |= BIT(7) | BIT(2); ++ ocp_reg_write(tp, 0xad40, data); ++ ++ data = ocp_reg_read(tp, 0xad4e); ++ data |= BIT(4); ++ ocp_reg_write(tp, 0xad4e, data); ++ data = ocp_reg_read(tp, 0xad16); ++ data &= ~0x3ff; ++ data |= 0x6; ++ ocp_reg_write(tp, 0xad16, data); ++ data = ocp_reg_read(tp, 0xad32); ++ data &= ~0x3f; ++ data |= 6; ++ ocp_reg_write(tp, 0xad32, data); ++ data = ocp_reg_read(tp, 0xac08); ++ data &= ~(BIT(12) | BIT(8)); ++ ocp_reg_write(tp, 0xac08, data); ++ data = ocp_reg_read(tp, 0xac8a); ++ data |= BIT(12) | BIT(13) | BIT(14); ++ data &= ~BIT(15); ++ ocp_reg_write(tp, 0xac8a, data); ++ data = ocp_reg_read(tp, 0xad18); ++ data |= BIT(10); ++ ocp_reg_write(tp, 0xad18, data); ++ data = ocp_reg_read(tp, 0xad1a); ++ data |= 0x3ff; ++ ocp_reg_write(tp, 0xad1a, data); ++ data = ocp_reg_read(tp, 0xad1c); ++ data |= 0x3ff; ++ ocp_reg_write(tp, 0xad1c, data); ++ ++ data = sram_read(tp, 0x80ea); ++ data &= ~0xff00; ++ data |= 0xc400; ++ sram_write(tp, 0x80ea, data); ++ data = sram_read(tp, 0x80eb); ++ data &= ~0x0700; ++ data |= 0x0300; ++ sram_write(tp, 0x80eb, data); ++ data = sram_read(tp, 0x80f8); ++ data &= ~0xff00; ++ data |= 0x1c00; ++ sram_write(tp, 0x80f8, data); ++ data = sram_read(tp, 0x80f1); ++ data &= ~0xff00; ++ data |= 0x3000; ++ sram_write(tp, 0x80f1, data); ++ ++ data = sram_read(tp, 0x80fe); ++ data &= ~0xff00; ++ data |= 0xa500; ++ sram_write(tp, 0x80fe, data); ++ data = sram_read(tp, 0x8102); ++ data &= ~0xff00; ++ data |= 0x5000; ++ sram_write(tp, 0x8102, data); ++ data = sram_read(tp, 0x8015); ++ data &= ~0xff00; ++ data |= 0x3300; ++ sram_write(tp, 0x8015, data); ++ data = sram_read(tp, 0x8100); ++ data &= ~0xff00; ++ data |= 0x7000; ++ sram_write(tp, 0x8100, data); ++ data = sram_read(tp, 0x8014); ++ data &= ~0xff00; ++ data |= 0xf000; ++ sram_write(tp, 0x8014, data); ++ data = sram_read(tp, 0x8016); ++ data &= ~0xff00; ++ data |= 0x6500; ++ sram_write(tp, 0x8016, data); ++ data = sram_read(tp, 0x80dc); ++ data &= ~0xff00; ++ data |= 0xed00; ++ sram_write(tp, 0x80dc, data); ++ data = sram_read(tp, 0x80df); ++ data |= BIT(8); ++ sram_write(tp, 0x80df, data); ++ data = sram_read(tp, 0x80e1); ++ data &= ~BIT(8); ++ sram_write(tp, 0x80e1, data); ++ ++ data = ocp_reg_read(tp, 0xbf06); ++ data &= ~0x003f; ++ data |= 0x0038; ++ ocp_reg_write(tp, 0xbf06, data); ++ ++ sram_write(tp, 0x819f, 0xddb6); ++ ++ ocp_reg_write(tp, 0xbc34, 0x5555); ++ data = ocp_reg_read(tp, 0xbf0a); ++ data &= ~0x0e00; ++ data |= 0x0a00; ++ ocp_reg_write(tp, 0xbf0a, data); ++ ++ data = ocp_reg_read(tp, 0xbd2c); ++ data &= ~BIT(13); ++ ocp_reg_write(tp, 0xbd2c, data); ++ break; ++ case RTL_VER_11: ++ data = ocp_reg_read(tp, 0xad16); ++ data |= 0x3ff; ++ ocp_reg_write(tp, 0xad16, data); ++ data = ocp_reg_read(tp, 0xad32); ++ data &= ~0x3f; ++ data |= 6; ++ ocp_reg_write(tp, 0xad32, data); ++ data = ocp_reg_read(tp, 0xac08); ++ data &= ~(BIT(12) | BIT(8)); ++ ocp_reg_write(tp, 0xac08, data); ++ data = ocp_reg_read(tp, 0xacc0); ++ data &= ~0x3; ++ data |= BIT(1); ++ ocp_reg_write(tp, 0xacc0, data); ++ data = ocp_reg_read(tp, 0xad40); ++ data &= ~0xe7; ++ data |= BIT(6) | BIT(2); ++ ocp_reg_write(tp, 0xad40, data); ++ data = ocp_reg_read(tp, 0xac14); ++ data &= ~BIT(7); ++ ocp_reg_write(tp, 0xac14, data); ++ data = ocp_reg_read(tp, 0xac80); ++ data &= ~(BIT(8) | BIT(9)); ++ ocp_reg_write(tp, 0xac80, data); ++ data = ocp_reg_read(tp, 0xac5e); ++ data &= ~0x7; ++ data |= BIT(1); ++ ocp_reg_write(tp, 0xac5e, data); ++ ocp_reg_write(tp, 0xad4c, 0x00a8); ++ ocp_reg_write(tp, 0xac5c, 0x01ff); ++ data = ocp_reg_read(tp, 0xac8a); ++ data &= ~0xf0; ++ data |= BIT(4) | BIT(5); ++ ocp_reg_write(tp, 0xac8a, data); ++ ocp_reg_write(tp, 0xb87c, 0x8157); ++ data = ocp_reg_read(tp, 0xb87e); ++ data &= ~0xff00; ++ data |= 0x0500; ++ ocp_reg_write(tp, 0xb87e, data); ++ ocp_reg_write(tp, 0xb87c, 0x8159); ++ data = ocp_reg_read(tp, 0xb87e); ++ data &= ~0xff00; ++ data |= 0x0700; ++ ocp_reg_write(tp, 0xb87e, data); ++ ++ /* AAGC */ ++ ocp_reg_write(tp, 0xb87c, 0x80a2); ++ ocp_reg_write(tp, 0xb87e, 0x0153); ++ ocp_reg_write(tp, 0xb87c, 0x809c); ++ ocp_reg_write(tp, 0xb87e, 0x0153); ++ ++ /* EEE parameter */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS_2P5G, 0x0056); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_USB_CFG); ++ ocp_data |= EN_XG_LIP | EN_G_LIP; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_USB_CFG, ocp_data); ++ ++ sram_write(tp, 0x8257, 0x020f); /* XG PLL */ ++ sram_write(tp, 0x80ea, 0x7843); /* GIGA Master */ ++ ++ if (rtl_phy_patch_request(tp, true, true)) ++ return; ++ ++ /* Advance EEE */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data |= EEE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ data = ocp_reg_read(tp, OCP_DOWN_SPEED); ++ data &= ~(EN_EEE_100 | EN_EEE_1000); ++ data |= EN_10M_CLKDIV; ++ ocp_reg_write(tp, OCP_DOWN_SPEED, data); ++ tp->ups_info._10m_ckdiv = true; ++ tp->ups_info.eee_plloff_100 = false; ++ tp->ups_info.eee_plloff_giga = false; ++ ++ data = ocp_reg_read(tp, OCP_POWER_CFG); ++ data &= ~EEE_CLKDIV_EN; ++ ocp_reg_write(tp, OCP_POWER_CFG, data); ++ tp->ups_info.eee_ckdiv = false; ++ ++ ocp_reg_write(tp, OCP_SYSCLK_CFG, 0); ++ ocp_reg_write(tp, OCP_SYSCLK_CFG, sysclk_div_expo(5)); ++ tp->ups_info._250m_ckdiv = false; ++ ++ rtl_phy_patch_request(tp, false, true); ++ ++ /* enable ADC Ibias Cal */ ++ data = ocp_reg_read(tp, 0xd068); ++ data |= BIT(13); ++ ocp_reg_write(tp, 0xd068, data); ++ ++ /* enable Thermal Sensor */ ++ data = sram_read(tp, 0x81a2); ++ data &= ~BIT(8); ++ sram_write(tp, 0x81a2, data); ++ data = ocp_reg_read(tp, 0xb54c); ++ data &= ~0xff00; ++ data |= 0xdb00; ++ ocp_reg_write(tp, 0xb54c, data); ++ ++ /* Nway 2.5G Lite */ ++ data = ocp_reg_read(tp, 0xa454); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa454, data); ++ ++ /* CS DSP solution */ ++ data = ocp_reg_read(tp, OCP_10GBT_CTRL); ++ data |= RTL_ADV2_5G_F_R; ++ ocp_reg_write(tp, OCP_10GBT_CTRL, data); ++ data = ocp_reg_read(tp, 0xad4e); ++ data &= ~BIT(4); ++ ocp_reg_write(tp, 0xad4e, data); ++ data = ocp_reg_read(tp, 0xa86a); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa86a, data); ++ ++ /* MDI SWAP */ ++ if ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) & MID_REVERSE) && ++ (ocp_reg_read(tp, 0xd068) & BIT(1))) { ++ u16 swap_a, swap_b; ++ ++ data = ocp_reg_read(tp, 0xd068); ++ data &= ~0x1f; ++ data |= 0x1; /* p0 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_a = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; ++ data |= 0x18; /* p3 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_b = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; /* p0 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_a & ~0x7ff) | (swap_b & 0x7ff)); ++ data |= 0x18; /* p3 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_b & ~0x7ff) | (swap_a & 0x7ff)); ++ data &= ~0x18; ++ data |= 0x08; /* p1 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_a = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; ++ data |= 0x10; /* p2 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_b = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; ++ data |= 0x08; /* p1 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_a & ~0x7ff) | (swap_b & 0x7ff)); ++ data &= ~0x18; ++ data |= 0x10; /* p2 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_b & ~0x7ff) | (swap_a & 0x7ff)); ++ swap_a = ocp_reg_read(tp, 0xbd5a); ++ swap_b = ocp_reg_read(tp, 0xbd5c); ++ ocp_reg_write(tp, 0xbd5a, (swap_a & ~0x1f1f) | ++ ((swap_b & 0x1f) << 8) | ++ ((swap_b >> 8) & 0x1f)); ++ ocp_reg_write(tp, 0xbd5c, (swap_b & ~0x1f1f) | ++ ((swap_a & 0x1f) << 8) | ++ ((swap_a >> 8) & 0x1f)); ++ swap_a = ocp_reg_read(tp, 0xbc18); ++ swap_b = ocp_reg_read(tp, 0xbc1a); ++ ocp_reg_write(tp, 0xbc18, (swap_a & ~0x1f1f) | ++ ((swap_b & 0x1f) << 8) | ++ ((swap_b >> 8) & 0x1f)); ++ ocp_reg_write(tp, 0xbc1a, (swap_b & ~0x1f1f) | ++ ((swap_a & 0x1f) << 8) | ++ ((swap_a >> 8) & 0x1f)); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); ++ ++ data = ocp_reg_read(tp, 0xa428); ++ data &= ~BIT(9); ++ ocp_reg_write(tp, 0xa428, data); ++ data = ocp_reg_read(tp, 0xa5ea); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa5ea, data); ++ tp->ups_info.lite_mode = 0; ++ ++ if (tp->eee_en) ++ rtl_eee_enable(tp, true); ++ ++ r8153_aldps_en(tp, true); ++ r8152b_enable_fc(tp); ++ r8153_u2p3en(tp, true); ++ ++ set_bit(PHY_RESET, &tp->flags); ++} ++ ++static void r8156b_hw_phy_cfg(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ ++ switch (tp->version) { ++ case RTL_VER_12: ++ ocp_reg_write(tp, 0xbf86, 0x9000); ++ data = ocp_reg_read(tp, 0xc402); ++ data |= BIT(10); ++ ocp_reg_write(tp, 0xc402, data); ++ data &= ~BIT(10); ++ ocp_reg_write(tp, 0xc402, data); ++ ocp_reg_write(tp, 0xbd86, 0x1010); ++ ocp_reg_write(tp, 0xbd88, 0x1010); ++ data = ocp_reg_read(tp, 0xbd4e); ++ data &= ~(BIT(10) | BIT(11)); ++ data |= BIT(11); ++ ocp_reg_write(tp, 0xbd4e, data); ++ data = ocp_reg_read(tp, 0xbf46); ++ data &= ~0xf00; ++ data |= 0x700; ++ ocp_reg_write(tp, 0xbf46, data); ++ break; ++ case RTL_VER_13: ++ case RTL_VER_15: ++ r8156b_wait_loading_flash(tp); ++ break; ++ default: ++ break; ++ } ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); ++ if (ocp_data & PCUT_STATUS) { ++ ocp_data &= ~PCUT_STATUS; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ switch (data) { ++ case PHY_STAT_EXT_INIT: ++ rtl8152_apply_firmware(tp, true); ++ ++ data = ocp_reg_read(tp, 0xa466); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa466, data); ++ ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ break; ++ case PHY_STAT_LAN_ON: ++ case PHY_STAT_PWRDN: ++ default: ++ rtl8152_apply_firmware(tp, false); ++ break; ++ } ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ /* disable ALDPS before updating the PHY parameters */ ++ r8153_aldps_en(tp, false); ++ ++ /* disable EEE before updating the PHY parameters */ ++ rtl_eee_enable(tp, false); ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); ++ ocp_data |= PFM_PWM_SWITCH; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); ++ ++ switch (tp->version) { ++ case RTL_VER_12: ++ data = ocp_reg_read(tp, 0xbc08); ++ data |= BIT(3) | BIT(2); ++ ocp_reg_write(tp, 0xbc08, data); ++ ++ data = sram_read(tp, 0x8fff); ++ data &= ~0xff00; ++ data |= 0x0400; ++ sram_write(tp, 0x8fff, data); ++ ++ data = ocp_reg_read(tp, 0xacda); ++ data |= 0xff00; ++ ocp_reg_write(tp, 0xacda, data); ++ data = ocp_reg_read(tp, 0xacde); ++ data |= 0xf000; ++ ocp_reg_write(tp, 0xacde, data); ++ ocp_reg_write(tp, 0xac8c, 0x0ffc); ++ ocp_reg_write(tp, 0xac46, 0xb7b4); ++ ocp_reg_write(tp, 0xac50, 0x0fbc); ++ ocp_reg_write(tp, 0xac3c, 0x9240); ++ ocp_reg_write(tp, 0xac4e, 0x0db4); ++ ocp_reg_write(tp, 0xacc6, 0x0707); ++ ocp_reg_write(tp, 0xacc8, 0xa0d3); ++ ocp_reg_write(tp, 0xad08, 0x0007); ++ ++ ocp_reg_write(tp, 0xb87c, 0x8560); ++ ocp_reg_write(tp, 0xb87e, 0x19cc); ++ ocp_reg_write(tp, 0xb87c, 0x8562); ++ ocp_reg_write(tp, 0xb87e, 0x19cc); ++ ocp_reg_write(tp, 0xb87c, 0x8564); ++ ocp_reg_write(tp, 0xb87e, 0x19cc); ++ ocp_reg_write(tp, 0xb87c, 0x8566); ++ ocp_reg_write(tp, 0xb87e, 0x147d); ++ ocp_reg_write(tp, 0xb87c, 0x8568); ++ ocp_reg_write(tp, 0xb87e, 0x147d); ++ ocp_reg_write(tp, 0xb87c, 0x856a); ++ ocp_reg_write(tp, 0xb87e, 0x147d); ++ ocp_reg_write(tp, 0xb87c, 0x8ffe); ++ ocp_reg_write(tp, 0xb87e, 0x0907); ++ ocp_reg_write(tp, 0xb87c, 0x80d6); ++ ocp_reg_write(tp, 0xb87e, 0x2801); ++ ocp_reg_write(tp, 0xb87c, 0x80f2); ++ ocp_reg_write(tp, 0xb87e, 0x2801); ++ ocp_reg_write(tp, 0xb87c, 0x80f4); ++ ocp_reg_write(tp, 0xb87e, 0x6077); ++ ocp_reg_write(tp, 0xb506, 0x01e7); ++ ++ ocp_reg_write(tp, 0xb87c, 0x8013); ++ ocp_reg_write(tp, 0xb87e, 0x0700); ++ ocp_reg_write(tp, 0xb87c, 0x8fb9); ++ ocp_reg_write(tp, 0xb87e, 0x2801); ++ ocp_reg_write(tp, 0xb87c, 0x8fba); ++ ocp_reg_write(tp, 0xb87e, 0x0100); ++ ocp_reg_write(tp, 0xb87c, 0x8fbc); ++ ocp_reg_write(tp, 0xb87e, 0x1900); ++ ocp_reg_write(tp, 0xb87c, 0x8fbe); ++ ocp_reg_write(tp, 0xb87e, 0xe100); ++ ocp_reg_write(tp, 0xb87c, 0x8fc0); ++ ocp_reg_write(tp, 0xb87e, 0x0800); ++ ocp_reg_write(tp, 0xb87c, 0x8fc2); ++ ocp_reg_write(tp, 0xb87e, 0xe500); ++ ocp_reg_write(tp, 0xb87c, 0x8fc4); ++ ocp_reg_write(tp, 0xb87e, 0x0f00); ++ ocp_reg_write(tp, 0xb87c, 0x8fc6); ++ ocp_reg_write(tp, 0xb87e, 0xf100); ++ ocp_reg_write(tp, 0xb87c, 0x8fc8); ++ ocp_reg_write(tp, 0xb87e, 0x0400); ++ ocp_reg_write(tp, 0xb87c, 0x8fca); ++ ocp_reg_write(tp, 0xb87e, 0xf300); ++ ocp_reg_write(tp, 0xb87c, 0x8fcc); ++ ocp_reg_write(tp, 0xb87e, 0xfd00); ++ ocp_reg_write(tp, 0xb87c, 0x8fce); ++ ocp_reg_write(tp, 0xb87e, 0xff00); ++ ocp_reg_write(tp, 0xb87c, 0x8fd0); ++ ocp_reg_write(tp, 0xb87e, 0xfb00); ++ ocp_reg_write(tp, 0xb87c, 0x8fd2); ++ ocp_reg_write(tp, 0xb87e, 0x0100); ++ ocp_reg_write(tp, 0xb87c, 0x8fd4); ++ ocp_reg_write(tp, 0xb87e, 0xf400); ++ ocp_reg_write(tp, 0xb87c, 0x8fd6); ++ ocp_reg_write(tp, 0xb87e, 0xff00); ++ ocp_reg_write(tp, 0xb87c, 0x8fd8); ++ ocp_reg_write(tp, 0xb87e, 0xf600); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_USB_CFG); ++ ocp_data |= EN_XG_LIP | EN_G_LIP; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_USB_CFG, ocp_data); ++ ocp_reg_write(tp, 0xb87c, 0x813d); ++ ocp_reg_write(tp, 0xb87e, 0x390e); ++ ocp_reg_write(tp, 0xb87c, 0x814f); ++ ocp_reg_write(tp, 0xb87e, 0x790e); ++ ocp_reg_write(tp, 0xb87c, 0x80b0); ++ ocp_reg_write(tp, 0xb87e, 0x0f31); ++ data = ocp_reg_read(tp, 0xbf4c); ++ data |= BIT(1); ++ ocp_reg_write(tp, 0xbf4c, data); ++ data = ocp_reg_read(tp, 0xbcca); ++ data |= BIT(9) | BIT(8); ++ ocp_reg_write(tp, 0xbcca, data); ++ ocp_reg_write(tp, 0xb87c, 0x8141); ++ ocp_reg_write(tp, 0xb87e, 0x320e); ++ ocp_reg_write(tp, 0xb87c, 0x8153); ++ ocp_reg_write(tp, 0xb87e, 0x720e); ++ ocp_reg_write(tp, 0xb87c, 0x8529); ++ ocp_reg_write(tp, 0xb87e, 0x050e); ++ data = ocp_reg_read(tp, OCP_EEE_CFG); ++ data &= ~CTAP_SHORT_EN; ++ ocp_reg_write(tp, OCP_EEE_CFG, data); ++ ++ sram_write(tp, 0x816c, 0xc4a0); ++ sram_write(tp, 0x8170, 0xc4a0); ++ sram_write(tp, 0x8174, 0x04a0); ++ sram_write(tp, 0x8178, 0x04a0); ++ sram_write(tp, 0x817c, 0x0719); ++ sram_write(tp, 0x8ff4, 0x0400); ++ sram_write(tp, 0x8ff1, 0x0404); ++ ++ ocp_reg_write(tp, 0xbf4a, 0x001b); ++ ocp_reg_write(tp, 0xb87c, 0x8033); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x8037); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x803b); ++ ocp_reg_write(tp, 0xb87e, 0xfc32); ++ ocp_reg_write(tp, 0xb87c, 0x803f); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x8043); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x8047); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ++ ocp_reg_write(tp, 0xb87c, 0x8145); ++ ocp_reg_write(tp, 0xb87e, 0x370e); ++ ocp_reg_write(tp, 0xb87c, 0x8157); ++ ocp_reg_write(tp, 0xb87e, 0x770e); ++ ocp_reg_write(tp, 0xb87c, 0x8169); ++ ocp_reg_write(tp, 0xb87e, 0x0d0a); ++ ocp_reg_write(tp, 0xb87c, 0x817b); ++ ocp_reg_write(tp, 0xb87e, 0x1d0a); ++ ++ data = sram_read(tp, 0x8217); ++ data &= ~0xff00; ++ data |= 0x5000; ++ sram_write(tp, 0x8217, data); ++ data = sram_read(tp, 0x821a); ++ data &= ~0xff00; ++ data |= 0x5000; ++ sram_write(tp, 0x821a, data); ++ sram_write(tp, 0x80da, 0x0403); ++ data = sram_read(tp, 0x80dc); ++ data &= ~0xff00; ++ data |= 0x1000; ++ sram_write(tp, 0x80dc, data); ++ sram_write(tp, 0x80b3, 0x0384); ++ sram_write(tp, 0x80b7, 0x2007); ++ data = sram_read(tp, 0x80ba); ++ data &= ~0xff00; ++ data |= 0x6c00; ++ sram_write(tp, 0x80ba, data); ++ sram_write(tp, 0x80b5, 0xf009); ++ data = sram_read(tp, 0x80bd); ++ data &= ~0xff00; ++ data |= 0x9f00; ++ sram_write(tp, 0x80bd, data); ++ sram_write(tp, 0x80c7, 0xf083); ++ sram_write(tp, 0x80dd, 0x03f0); ++ data = sram_read(tp, 0x80df); ++ data &= ~0xff00; ++ data |= 0x1000; ++ sram_write(tp, 0x80df, data); ++ sram_write(tp, 0x80cb, 0x2007); ++ data = sram_read(tp, 0x80ce); ++ data &= ~0xff00; ++ data |= 0x6c00; ++ sram_write(tp, 0x80ce, data); ++ sram_write(tp, 0x80c9, 0x8009); ++ data = sram_read(tp, 0x80d1); ++ data &= ~0xff00; ++ data |= 0x8000; ++ sram_write(tp, 0x80d1, data); ++ sram_write(tp, 0x80a3, 0x200a); ++ sram_write(tp, 0x80a5, 0xf0ad); ++ sram_write(tp, 0x809f, 0x6073); ++ sram_write(tp, 0x80a1, 0x000b); ++ data = sram_read(tp, 0x80a9); ++ data &= ~0xff00; ++ data |= 0xc000; ++ sram_write(tp, 0x80a9, data); ++ ++ if (rtl_phy_patch_request(tp, true, true)) ++ return; ++ ++ data = ocp_reg_read(tp, 0xb896); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xb896, data); ++ data = ocp_reg_read(tp, 0xb892); ++ data &= ~0xff00; ++ ocp_reg_write(tp, 0xb892, data); ++ ocp_reg_write(tp, 0xb88e, 0xc23e); ++ ocp_reg_write(tp, 0xb890, 0x0000); ++ ocp_reg_write(tp, 0xb88e, 0xc240); ++ ocp_reg_write(tp, 0xb890, 0x0103); ++ ocp_reg_write(tp, 0xb88e, 0xc242); ++ ocp_reg_write(tp, 0xb890, 0x0507); ++ ocp_reg_write(tp, 0xb88e, 0xc244); ++ ocp_reg_write(tp, 0xb890, 0x090b); ++ ocp_reg_write(tp, 0xb88e, 0xc246); ++ ocp_reg_write(tp, 0xb890, 0x0c0e); ++ ocp_reg_write(tp, 0xb88e, 0xc248); ++ ocp_reg_write(tp, 0xb890, 0x1012); ++ ocp_reg_write(tp, 0xb88e, 0xc24a); ++ ocp_reg_write(tp, 0xb890, 0x1416); ++ data = ocp_reg_read(tp, 0xb896); ++ data |= BIT(0); ++ ocp_reg_write(tp, 0xb896, data); ++ ++ rtl_phy_patch_request(tp, false, true); ++ ++ data = ocp_reg_read(tp, 0xa86a); ++ data |= BIT(0); ++ ocp_reg_write(tp, 0xa86a, data); ++ data = ocp_reg_read(tp, 0xa6f0); ++ data |= BIT(0); ++ ocp_reg_write(tp, 0xa6f0, data); ++ ++ ocp_reg_write(tp, 0xbfa0, 0xd70d); ++ ocp_reg_write(tp, 0xbfa2, 0x4100); ++ ocp_reg_write(tp, 0xbfa4, 0xe868); ++ ocp_reg_write(tp, 0xbfa6, 0xdc59); ++ ocp_reg_write(tp, 0xb54c, 0x3c18); ++ data = ocp_reg_read(tp, 0xbfa4); ++ data &= ~BIT(5); ++ ocp_reg_write(tp, 0xbfa4, data); ++ data = sram_read(tp, 0x817d); ++ data |= BIT(12); ++ sram_write(tp, 0x817d, data); ++ break; ++ case RTL_VER_13: ++ /* 2.5G INRX */ ++ data = ocp_reg_read(tp, 0xac46); ++ data &= ~0x00f0; ++ data |= 0x0090; ++ ocp_reg_write(tp, 0xac46, data); ++ data = ocp_reg_read(tp, 0xad30); ++ data &= ~0x0003; ++ data |= 0x0001; ++ ocp_reg_write(tp, 0xad30, data); ++ fallthrough; ++ case RTL_VER_15: ++ /* EEE parameter */ ++ ocp_reg_write(tp, 0xb87c, 0x80f5); ++ ocp_reg_write(tp, 0xb87e, 0x760e); ++ ocp_reg_write(tp, 0xb87c, 0x8107); ++ ocp_reg_write(tp, 0xb87e, 0x360e); ++ ocp_reg_write(tp, 0xb87c, 0x8551); ++ data = ocp_reg_read(tp, 0xb87e); ++ data &= ~0xff00; ++ data |= 0x0800; ++ ocp_reg_write(tp, 0xb87e, data); ++ ++ /* ADC_PGA parameter */ ++ data = ocp_reg_read(tp, 0xbf00); ++ data &= ~0xe000; ++ data |= 0xa000; ++ ocp_reg_write(tp, 0xbf00, data); ++ data = ocp_reg_read(tp, 0xbf46); ++ data &= ~0x0f00; ++ data |= 0x0300; ++ ocp_reg_write(tp, 0xbf46, data); ++ ++ /* Green Table-PGA, 1G full viterbi */ ++ sram_write(tp, 0x8044, 0x2417); ++ sram_write(tp, 0x804a, 0x2417); ++ sram_write(tp, 0x8050, 0x2417); ++ sram_write(tp, 0x8056, 0x2417); ++ sram_write(tp, 0x805c, 0x2417); ++ sram_write(tp, 0x8062, 0x2417); ++ sram_write(tp, 0x8068, 0x2417); ++ sram_write(tp, 0x806e, 0x2417); ++ sram_write(tp, 0x8074, 0x2417); ++ sram_write(tp, 0x807a, 0x2417); ++ ++ /* XG PLL */ ++ data = ocp_reg_read(tp, 0xbf84); ++ data &= ~0xe000; ++ data |= 0xa000; ++ ocp_reg_write(tp, 0xbf84, data); ++ break; ++ default: ++ break; ++ } ++ ++ if (rtl_phy_patch_request(tp, true, true)) ++ return; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data |= EEE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ data = ocp_reg_read(tp, OCP_DOWN_SPEED); ++ data &= ~(EN_EEE_100 | EN_EEE_1000); ++ data |= EN_10M_CLKDIV; ++ ocp_reg_write(tp, OCP_DOWN_SPEED, data); ++ tp->ups_info._10m_ckdiv = true; ++ tp->ups_info.eee_plloff_100 = false; ++ tp->ups_info.eee_plloff_giga = false; ++ ++ data = ocp_reg_read(tp, OCP_POWER_CFG); ++ data &= ~EEE_CLKDIV_EN; ++ ocp_reg_write(tp, OCP_POWER_CFG, data); ++ tp->ups_info.eee_ckdiv = false; ++ ++ rtl_phy_patch_request(tp, false, true); ++ ++ rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); ++ ++ data = ocp_reg_read(tp, 0xa428); ++ data &= ~BIT(9); ++ ocp_reg_write(tp, 0xa428, data); ++ data = ocp_reg_read(tp, 0xa5ea); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa5ea, data); ++ tp->ups_info.lite_mode = 0; ++ ++ if (tp->eee_en) ++ rtl_eee_enable(tp, true); ++ ++ r8153_aldps_en(tp, true); ++ r8152b_enable_fc(tp); ++ r8153_u2p3en(tp, true); ++ ++ set_bit(PHY_RESET, &tp->flags); ++} ++ ++static void r8156_init(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ int i; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP); ++ ocp_data &= ~EN_ALL_SPEED; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data); ++ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION); ++ ocp_data |= BYPASS_MAC_RESET; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data); ++ ++ r8153b_u1u2en(tp, false); ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ ++ msleep(20); ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ if (data == PHY_STAT_EXT_INIT) { ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ } ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); ++ ++ r8153_u2p3en(tp, false); ++ ++ /* MSC timer = 0xfff * 8ms = 32760 ms */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); ++ ++ /* U1/U2/L1 idle timer. 500 us */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); ++ ++ r8153b_power_cut_en(tp, false); ++ r8156_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++ ++ usb_enable_lpm(tp->udev); ++ ++ r8156_mac_clk_spd(tp, true); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); ++ if (rtl8152_get_speed(tp) & LINK_STATUS) ++ ocp_data |= CUR_LINK_OK; ++ else ++ ocp_data &= ~CUR_LINK_OK; ++ ocp_data |= POLL_LINK_CHG; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); ++ ++ set_bit(GREEN_ETHERNET, &tp->flags); ++ ++ /* rx aggregation */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG); ++ ocp_data |= ACT_ODMA; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); ++ ++ rtl_tally_reset(tp); ++ ++ tp->coalesce = 15000; /* 15 us */ ++} ++ ++static void r8156b_init(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ int i; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP); ++ ocp_data &= ~EN_ALL_SPEED; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data); ++ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION); ++ ocp_data |= BYPASS_MAC_RESET; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); ++ ocp_data |= RX_DETECT8; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); ++ ++ r8153b_u1u2en(tp, false); ++ ++ switch (tp->version) { ++ case RTL_VER_13: ++ case RTL_VER_15: ++ r8156b_wait_loading_flash(tp); ++ break; ++ default: ++ break; ++ } ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ ++ msleep(20); ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ if (data == PHY_STAT_EXT_INIT) { ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ ++ data = ocp_reg_read(tp, 0xa466); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa466, data); ++ } ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ ++ r8153_u2p3en(tp, false); ++ ++ /* MSC timer = 0xfff * 8ms = 32760 ms */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); ++ ++ /* U1/U2/L1 idle timer. 500 us */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); ++ ++ r8153b_power_cut_en(tp, false); ++ r8156_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++ ++ usb_enable_lpm(tp->udev); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data &= ~SLOT_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); ++ ocp_data |= FLOW_CTRL_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); ++ ++ /* enable fc timer and set timer to 600 ms. */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER, ++ CTRL_TIMER_EN | (600 / 8)); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL); ++ if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & DACK_DET_EN)) ++ ocp_data |= FLOW_CTRL_PATCH_2; ++ ocp_data &= ~AUTO_SPEEDUP; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); ++ ocp_data |= FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ ++ r8156_mac_clk_spd(tp, true); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); ++ if (rtl8152_get_speed(tp) & LINK_STATUS) ++ ocp_data |= CUR_LINK_OK; ++ else ++ ocp_data &= ~CUR_LINK_OK; ++ ocp_data |= POLL_LINK_CHG; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); ++ ++ set_bit(GREEN_ETHERNET, &tp->flags); ++ ++ /* rx aggregation */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ rtl_tally_reset(tp); ++ ++ tp->coalesce = 15000; /* 15 us */ ++} ++ + static int rtl8152_pre_reset(struct usb_interface *intf) + { + struct r8152 *tp = usb_get_intfdata(intf); +@@ -6015,6 +7947,22 @@ int rtl8152_get_link_ksettings(struct ne + + mii_ethtool_get_link_ksettings(&tp->mii, cmd); + ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.supported, tp->support_2500full); ++ ++ if (tp->support_2500full) { ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.advertising, ++ ocp_reg_read(tp, OCP_10GBT_CTRL) & MDIO_AN_10GBT_CTRL_ADV2_5G); ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.lp_advertising, ++ ocp_reg_read(tp, OCP_10GBT_STAT) & MDIO_AN_10GBT_STAT_LP2_5G); ++ ++ if (is_speed_2500(rtl8152_get_speed(tp))) ++ cmd->base.speed = SPEED_2500; ++ } ++ + mutex_unlock(&tp->control); + + usb_autopm_put_interface(tp->intf); +@@ -6058,6 +8006,10 @@ static int rtl8152_set_link_ksettings(st + cmd->link_modes.advertising)) + advertising |= RTL_ADVERTISED_1000_FULL; + ++ if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.advertising)) ++ advertising |= RTL_ADVERTISED_2500_FULL; ++ + mutex_lock(&tp->control); + + ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed, +@@ -6647,6 +8599,67 @@ static int rtl_ops_init(struct r8152 *tp + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; + break; + ++ case RTL_VER_11: ++ tp->eee_en = true; ++ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; ++ fallthrough; ++ case RTL_VER_10: ++ ops->init = r8156_init; ++ ops->enable = rtl8156_enable; ++ ops->disable = rtl8153_disable; ++ ops->up = rtl8156_up; ++ ops->down = rtl8156_down; ++ ops->unload = rtl8153_unload; ++ ops->eee_get = r8153_get_eee; ++ ops->eee_set = r8152_set_eee; ++ ops->in_nway = rtl8153_in_nway; ++ ops->hw_phy_cfg = r8156_hw_phy_cfg; ++ ops->autosuspend_en = rtl8156_runtime_enable; ++ ops->change_mtu = rtl8156_change_mtu; ++ tp->rx_buf_sz = 48 * 1024; ++ tp->support_2500full = 1; ++ break; ++ ++ case RTL_VER_12: ++ case RTL_VER_13: ++ tp->support_2500full = 1; ++ fallthrough; ++ case RTL_VER_15: ++ tp->eee_en = true; ++ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; ++ ops->init = r8156b_init; ++ ops->enable = rtl8156b_enable; ++ ops->disable = rtl8153_disable; ++ ops->up = rtl8156_up; ++ ops->down = rtl8156_down; ++ ops->unload = rtl8153_unload; ++ ops->eee_get = r8153_get_eee; ++ ops->eee_set = r8152_set_eee; ++ ops->in_nway = rtl8153_in_nway; ++ ops->hw_phy_cfg = r8156b_hw_phy_cfg; ++ ops->autosuspend_en = rtl8156_runtime_enable; ++ ops->change_mtu = rtl8156_change_mtu; ++ tp->rx_buf_sz = 48 * 1024; ++ break; ++ ++ case RTL_VER_14: ++ ops->init = r8153c_init; ++ ops->enable = rtl8153_enable; ++ ops->disable = rtl8153_disable; ++ ops->up = rtl8153c_up; ++ ops->down = rtl8153b_down; ++ ops->unload = rtl8153_unload; ++ ops->eee_get = r8153_get_eee; ++ ops->eee_set = r8152_set_eee; ++ ops->in_nway = rtl8153_in_nway; ++ ops->hw_phy_cfg = r8153c_hw_phy_cfg; ++ ops->autosuspend_en = rtl8153c_runtime_enable; ++ ops->change_mtu = rtl8153c_change_mtu; ++ tp->rx_buf_sz = 32 * 1024; ++ tp->eee_en = true; ++ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; ++ break; ++ + default: + ret = -ENODEV; + dev_err(&tp->intf->dev, "Unknown Device\n"); +@@ -6660,11 +8673,13 @@ static int rtl_ops_init(struct r8152 *tp + #define FIRMWARE_8153A_3 "rtl_nic/rtl8153a-3.fw" + #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" + #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" ++#define FIRMWARE_8153C_1 "rtl_nic/rtl8153c-1.fw" + + MODULE_FIRMWARE(FIRMWARE_8153A_2); + MODULE_FIRMWARE(FIRMWARE_8153A_3); + MODULE_FIRMWARE(FIRMWARE_8153A_4); + MODULE_FIRMWARE(FIRMWARE_8153B_2); ++MODULE_FIRMWARE(FIRMWARE_8153C_1); + + static int rtl_fw_init(struct r8152 *tp) + { +@@ -6690,6 +8705,11 @@ static int rtl_fw_init(struct r8152 *tp) + rtl_fw->pre_fw = r8153b_pre_firmware_1; + rtl_fw->post_fw = r8153b_post_firmware_1; + break; ++ case RTL_VER_14: ++ rtl_fw->fw_name = FIRMWARE_8153C_1; ++ rtl_fw->pre_fw = r8153b_pre_firmware_1; ++ rtl_fw->post_fw = r8153c_post_firmware_1; ++ break; + default: + break; + } +@@ -6745,6 +8765,27 @@ u8 rtl8152_get_version(struct usb_interf + case 0x6010: + version = RTL_VER_09; + break; ++ case 0x7010: ++ version = RTL_TEST_01; ++ break; ++ case 0x7020: ++ version = RTL_VER_10; ++ break; ++ case 0x7030: ++ version = RTL_VER_11; ++ break; ++ case 0x7400: ++ version = RTL_VER_12; ++ break; ++ case 0x7410: ++ version = RTL_VER_13; ++ break; ++ case 0x6400: ++ version = RTL_VER_14; ++ break; ++ case 0x7420: ++ version = RTL_VER_15; ++ break; + default: + version = RTL_VER_UNKNOWN; + dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data); +@@ -6857,12 +8898,29 @@ static int rtl8152_probe(struct usb_inte + /* MTU range: 68 - 1500 or 9194 */ + netdev->min_mtu = ETH_MIN_MTU; + switch (tp->version) { ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ case RTL_VER_08: ++ case RTL_VER_09: ++ case RTL_VER_14: ++ netdev->max_mtu = size_to_mtu(9 * 1024); ++ break; ++ case RTL_VER_10: ++ case RTL_VER_11: ++ netdev->max_mtu = size_to_mtu(15 * 1024); ++ break; ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ netdev->max_mtu = size_to_mtu(16 * 1024); ++ break; + case RTL_VER_01: + case RTL_VER_02: +- netdev->max_mtu = ETH_DATA_LEN; +- break; ++ case RTL_VER_07: + default: +- netdev->max_mtu = size_to_mtu(9 * 1024); ++ netdev->max_mtu = ETH_DATA_LEN; + break; + } + +@@ -6878,7 +8936,13 @@ static int rtl8152_probe(struct usb_inte + tp->advertising = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | + RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; + if (tp->mii.supports_gmii) { +- tp->speed = SPEED_1000; ++ if (tp->support_2500full && ++ tp->udev->speed >= USB_SPEED_SUPER) { ++ tp->speed = SPEED_2500; ++ tp->advertising |= RTL_ADVERTISED_2500_FULL; ++ } else { ++ tp->speed = SPEED_1000; ++ } + tp->advertising |= RTL_ADVERTISED_1000_FULL; + } + tp->duplex = DUPLEX_FULL; +@@ -6902,7 +8966,11 @@ static int rtl8152_probe(struct usb_inte + set_ethernet_addr(tp); + + usb_set_intfdata(intf, tp); +- netif_napi_add(netdev, &tp->napi, r8152_poll, RTL8152_NAPI_WEIGHT); ++ ++ if (tp->support_2500full) ++ netif_napi_add(netdev, &tp->napi, r8152_poll, 256); ++ else ++ netif_napi_add(netdev, &tp->napi, r8152_poll, 64); + + ret = register_netdev(netdev); + if (ret != 0) { +@@ -6938,7 +9006,8 @@ static void rtl8152_disconnect(struct us + unregister_netdev(tp->netdev); + tasklet_kill(&tp->tx_tl); + cancel_delayed_work_sync(&tp->hw_phy_work); +- tp->rtl_ops.unload(tp); ++ if (tp->rtl_ops.unload) ++ tp->rtl_ops.unload(tp); + rtl8152_release_firmware(tp); + free_netdev(tp->netdev); + } +@@ -6958,13 +9027,28 @@ static void rtl8152_disconnect(struct us + .idProduct = (prod), \ + .bInterfaceClass = USB_CLASS_COMM, \ + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ ++ .bInterfaceProtocol = USB_CDC_PROTO_NONE \ ++}, \ ++{ \ ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | \ ++ USB_DEVICE_ID_MATCH_DEVICE, \ ++ .idVendor = (vend), \ ++ .idProduct = (prod), \ ++ .bInterfaceClass = USB_CLASS_COMM, \ ++ .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, \ + .bInterfaceProtocol = USB_CDC_PROTO_NONE + + /* table of devices that work with this driver */ + static const struct usb_device_id rtl8152_table[] = { ++ /* Realtek */ + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8053)}, + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8155)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8156)}, ++ ++ /* Microsoft */ + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)}, + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)}, + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927)}, diff --git a/target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch b/target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch new file mode 100644 index 0000000000..943c821b82 --- /dev/null +++ b/target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch @@ -0,0 +1,691 @@ +From ca09589a72a0aa17389754fb75a5cd1a5d46818f Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 16 Apr 2021 16:04:36 +0800 +Subject: [PATCH] r8152: support PHY firmware for RTL8156 series + +commit 4a51b0e8a0143b0e83d51d9c58c6416c3818a9f2 upstream. + +Support new firmware type and method for RTL8156 series. + +Signed-off-by: Hayes Wang +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 563 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 561 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -975,8 +975,60 @@ enum rtl8152_fw_flags { + FW_FLAGS_START, + FW_FLAGS_STOP, + FW_FLAGS_NC, ++ FW_FLAGS_NC1, ++ FW_FLAGS_NC2, ++ FW_FLAGS_UC2, ++ FW_FLAGS_UC, ++ FW_FLAGS_SPEED_UP, ++ FW_FLAGS_VER, + }; + ++enum rtl8152_fw_fixup_cmd { ++ FW_FIXUP_AND = 0, ++ FW_FIXUP_OR, ++ FW_FIXUP_NOT, ++ FW_FIXUP_XOR, ++}; ++ ++struct fw_phy_set { ++ __le16 addr; ++ __le16 data; ++} __packed; ++ ++struct fw_phy_speed_up { ++ struct fw_block blk_hdr; ++ __le16 fw_offset; ++ __le16 version; ++ __le16 fw_reg; ++ __le16 reserved; ++ char info[]; ++} __packed; ++ ++struct fw_phy_ver { ++ struct fw_block blk_hdr; ++ struct fw_phy_set ver; ++ __le32 reserved; ++} __packed; ++ ++struct fw_phy_fixup { ++ struct fw_block blk_hdr; ++ struct fw_phy_set setting; ++ __le16 bit_cmd; ++ __le16 reserved; ++} __packed; ++ ++struct fw_phy_union { ++ struct fw_block blk_hdr; ++ __le16 fw_offset; ++ __le16 fw_reg; ++ struct fw_phy_set pre_set[2]; ++ struct fw_phy_set bp[8]; ++ struct fw_phy_set bp_en; ++ u8 pre_num; ++ u8 bp_num; ++ char info[]; ++} __packed; ++ + /** + * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. + * The layout of the firmware block is: +@@ -1081,6 +1133,15 @@ enum rtl_fw_type { + RTL_FW_PHY_START, + RTL_FW_PHY_STOP, + RTL_FW_PHY_NC, ++ RTL_FW_PHY_FIXUP, ++ RTL_FW_PHY_UNION_NC, ++ RTL_FW_PHY_UNION_NC1, ++ RTL_FW_PHY_UNION_NC2, ++ RTL_FW_PHY_UNION_UC2, ++ RTL_FW_PHY_UNION_UC, ++ RTL_FW_PHY_UNION_MISC, ++ RTL_FW_PHY_SPEED_UP, ++ RTL_FW_PHY_VER, + }; + + enum rtl_version { +@@ -4000,6 +4061,162 @@ static int rtl_post_ram_code(struct r815 + return 0; + } + ++static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_up *phy) ++{ ++ u16 fw_offset; ++ u32 length; ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_01: ++ case RTL_VER_02: ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ case RTL_VER_07: ++ case RTL_VER_08: ++ case RTL_VER_09: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_14: ++ goto out; ++ case RTL_VER_13: ++ case RTL_VER_15: ++ default: ++ break; ++ } ++ ++ fw_offset = __le16_to_cpu(phy->fw_offset); ++ length = __le32_to_cpu(phy->blk_hdr.length); ++ if (fw_offset < sizeof(*phy) || length <= fw_offset) { ++ dev_err(&tp->intf->dev, "invalid fw_offset\n"); ++ goto out; ++ } ++ ++ length -= fw_offset; ++ if (length & 3) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (__le16_to_cpu(phy->fw_reg) != 0x9A00) { ++ dev_err(&tp->intf->dev, "invalid register to load firmware\n"); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ ++static bool rtl8152_is_fw_phy_ver_ok(struct r8152 *tp, struct fw_phy_ver *ver) ++{ ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ break; ++ default: ++ goto out; ++ } ++ ++ if (__le32_to_cpu(ver->blk_hdr.length) != sizeof(*ver)) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (__le16_to_cpu(ver->ver.addr) != SRAM_GPHY_FW_VER) { ++ dev_err(&tp->intf->dev, "invalid phy ver addr\n"); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ ++static bool rtl8152_is_fw_phy_fixup_ok(struct r8152 *tp, struct fw_phy_fixup *fix) ++{ ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ break; ++ default: ++ goto out; ++ } ++ ++ if (__le32_to_cpu(fix->blk_hdr.length) != sizeof(*fix)) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (__le16_to_cpu(fix->setting.addr) != OCP_PHY_PATCH_CMD || ++ __le16_to_cpu(fix->setting.data) != BIT(7)) { ++ dev_err(&tp->intf->dev, "invalid phy fixup\n"); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ ++static bool rtl8152_is_fw_phy_union_ok(struct r8152 *tp, struct fw_phy_union *phy) ++{ ++ u16 fw_offset; ++ u32 length; ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ break; ++ default: ++ goto out; ++ } ++ ++ fw_offset = __le16_to_cpu(phy->fw_offset); ++ length = __le32_to_cpu(phy->blk_hdr.length); ++ if (fw_offset < sizeof(*phy) || length <= fw_offset) { ++ dev_err(&tp->intf->dev, "invalid fw_offset\n"); ++ goto out; ++ } ++ ++ length -= fw_offset; ++ if (length & 1) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (phy->pre_num > 2) { ++ dev_err(&tp->intf->dev, "invalid pre_num %d\n", phy->pre_num); ++ goto out; ++ } ++ ++ if (phy->bp_num > 8) { ++ dev_err(&tp->intf->dev, "invalid bp_num %d\n", phy->bp_num); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ + static bool rtl8152_is_fw_phy_nc_ok(struct r8152 *tp, struct fw_phy_nc *phy) + { + u32 length; +@@ -4320,6 +4537,10 @@ static long rtl8152_check_firmware(struc + case RTL_FW_PHY_START: + if (test_bit(FW_FLAGS_START, &fw_flags) || + test_bit(FW_FLAGS_NC, &fw_flags) || ++ test_bit(FW_FLAGS_NC1, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || + test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, + "check PHY_START fail\n"); +@@ -4368,7 +4589,153 @@ static long rtl8152_check_firmware(struc + goto fail; + } + __set_bit(FW_FLAGS_NC, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_NC: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC1, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_NC out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_NC, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY_UNION_NC encountered\n"); ++ goto fail; ++ } + ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_NC failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_NC, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_NC1: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_NC1 out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_NC1, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY NC1 encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_NC1 failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_NC1, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_NC2: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_NC2 out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_NC2, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY NC2 encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_NC2 failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_NC2, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_UC2: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_UC2 out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_UC2, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY UC2 encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_UC2 failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_UC2, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_UC: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_UC out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_UC, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY UC encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_UC failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_UC, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_MISC: ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check RTL_FW_PHY_UNION_MISC failed\n"); ++ goto fail; ++ } ++ break; ++ case RTL_FW_PHY_FIXUP: ++ if (!rtl8152_is_fw_phy_fixup_ok(tp, (struct fw_phy_fixup *)block)) { ++ dev_err(&tp->intf->dev, "check PHY fixup failed\n"); ++ goto fail; ++ } ++ break; ++ case RTL_FW_PHY_SPEED_UP: ++ if (test_bit(FW_FLAGS_SPEED_UP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY firmware encountered"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_speed_up_ok(tp, (struct fw_phy_speed_up *)block)) { ++ dev_err(&tp->intf->dev, "check PHY speed up failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_SPEED_UP, &fw_flags); ++ break; ++ case RTL_FW_PHY_VER: ++ if (test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC, &fw_flags) || ++ test_bit(FW_FLAGS_NC1, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "Invalid order to set PHY version\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_VER, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY version encountered"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_ver_ok(tp, (struct fw_phy_ver *)block)) { ++ dev_err(&tp->intf->dev, "check PHY version failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_VER, &fw_flags); + break; + default: + dev_warn(&tp->intf->dev, "Unknown type %u is found\n", +@@ -4391,6 +4758,143 @@ fail: + return ret; + } + ++static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, bool wait) ++{ ++ u32 len; ++ u8 *data; ++ ++ if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) { ++ dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); ++ return; ++ } ++ ++ len = __le32_to_cpu(phy->blk_hdr.length); ++ len -= __le16_to_cpu(phy->fw_offset); ++ data = (u8 *)phy + __le16_to_cpu(phy->fw_offset); ++ ++ if (rtl_phy_patch_request(tp, true, wait)) ++ return; ++ ++ while (len) { ++ u32 ocp_data, size; ++ int i; ++ ++ if (len < 2048) ++ size = len; ++ else ++ size = 2048; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL); ++ ocp_data |= GPHY_PATCH_DONE | BACKUP_RESTRORE; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL, ocp_data); ++ ++ generic_ocp_write(tp, __le16_to_cpu(phy->fw_reg), 0xff, size, data, MCU_TYPE_USB); ++ ++ data += size; ++ len -= size; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL); ++ ocp_data |= POL_GPHY_PATCH; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL, ocp_data); ++ ++ for (i = 0; i < 1000; i++) { ++ if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & POL_GPHY_PATCH)) ++ break; ++ } ++ ++ if (i == 1000) { ++ dev_err(&tp->intf->dev, "ram code speedup mode timeout\n"); ++ return; ++ } ++ } ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); ++ rtl_phy_patch_request(tp, false, wait); ++ ++ if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version)) ++ dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); ++ else ++ dev_err(&tp->intf->dev, "ram code speedup mode fail\n"); ++} ++ ++static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver) ++{ ++ u16 ver_addr, ver; ++ ++ ver_addr = __le16_to_cpu(phy_ver->ver.addr); ++ ver = __le16_to_cpu(phy_ver->ver.data); ++ ++ if (sram_read(tp, ver_addr) >= ver) { ++ dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); ++ return 0; ++ } ++ ++ sram_write(tp, ver_addr, ver); ++ ++ dev_dbg(&tp->intf->dev, "PHY firmware version %x\n", ver); ++ ++ return ver; ++} ++ ++static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix) ++{ ++ u16 addr, data; ++ ++ addr = __le16_to_cpu(fix->setting.addr); ++ data = ocp_reg_read(tp, addr); ++ ++ switch (__le16_to_cpu(fix->bit_cmd)) { ++ case FW_FIXUP_AND: ++ data &= __le16_to_cpu(fix->setting.data); ++ break; ++ case FW_FIXUP_OR: ++ data |= __le16_to_cpu(fix->setting.data); ++ break; ++ case FW_FIXUP_NOT: ++ data &= ~__le16_to_cpu(fix->setting.data); ++ break; ++ case FW_FIXUP_XOR: ++ data ^= __le16_to_cpu(fix->setting.data); ++ break; ++ default: ++ return; ++ } ++ ++ ocp_reg_write(tp, addr, data); ++ ++ dev_dbg(&tp->intf->dev, "applied ocp %x %x\n", addr, data); ++} ++ ++static void rtl8152_fw_phy_union_apply(struct r8152 *tp, struct fw_phy_union *phy) ++{ ++ __le16 *data; ++ u32 length; ++ int i, num; ++ ++ num = phy->pre_num; ++ for (i = 0; i < num; i++) ++ sram_write(tp, __le16_to_cpu(phy->pre_set[i].addr), ++ __le16_to_cpu(phy->pre_set[i].data)); ++ ++ length = __le32_to_cpu(phy->blk_hdr.length); ++ length -= __le16_to_cpu(phy->fw_offset); ++ num = length / 2; ++ data = (__le16 *)((u8 *)phy + __le16_to_cpu(phy->fw_offset)); ++ ++ ocp_reg_write(tp, OCP_SRAM_ADDR, __le16_to_cpu(phy->fw_reg)); ++ for (i = 0; i < num; i++) ++ ocp_reg_write(tp, OCP_SRAM_DATA, __le16_to_cpu(data[i])); ++ ++ num = phy->bp_num; ++ for (i = 0; i < num; i++) ++ sram_write(tp, __le16_to_cpu(phy->bp[i].addr), __le16_to_cpu(phy->bp[i].data)); ++ ++ if (phy->bp_num && phy->bp_en.addr) ++ sram_write(tp, __le16_to_cpu(phy->bp_en.addr), __le16_to_cpu(phy->bp_en.data)); ++ ++ dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); ++} ++ + static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy) + { + u16 mode_reg, bp_index; +@@ -4444,6 +4948,12 @@ static void rtl8152_fw_mac_apply(struct + return; + } + ++ fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg); ++ if (fw_ver_reg && ocp_read_byte(tp, MCU_TYPE_USB, fw_ver_reg) >= mac->fw_ver_data) { ++ dev_dbg(&tp->intf->dev, "%s firmware has been the newest\n", type ? "PLA" : "USB"); ++ return; ++ } ++ + rtl_clear_bp(tp, type); + + /* Enable backup/restore of MACDBG. This is required after clearing PLA +@@ -4479,7 +4989,6 @@ static void rtl8152_fw_mac_apply(struct + ocp_write_word(tp, type, bp_en_addr, + __le16_to_cpu(mac->bp_en_value)); + +- fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg); + if (fw_ver_reg) + ocp_write_byte(tp, MCU_TYPE_USB, fw_ver_reg, + mac->fw_ver_data); +@@ -4494,7 +5003,7 @@ static void rtl8152_apply_firmware(struc + struct fw_header *fw_hdr; + struct fw_phy_patch_key *key; + u16 key_addr = 0; +- int i; ++ int i, patch_phy = 1; + + if (IS_ERR_OR_NULL(rtl_fw->fw)) + return; +@@ -4516,17 +5025,40 @@ static void rtl8152_apply_firmware(struc + rtl8152_fw_mac_apply(tp, (struct fw_mac *)block); + break; + case RTL_FW_PHY_START: ++ if (!patch_phy) ++ break; + key = (struct fw_phy_patch_key *)block; + key_addr = __le16_to_cpu(key->key_reg); + rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); + break; + case RTL_FW_PHY_STOP: ++ if (!patch_phy) ++ break; + WARN_ON(!key_addr); + rtl_post_ram_code(tp, key_addr, !power_cut); + break; + case RTL_FW_PHY_NC: + rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); + break; ++ case RTL_FW_PHY_VER: ++ patch_phy = rtl8152_fw_phy_ver(tp, (struct fw_phy_ver *)block); ++ break; ++ case RTL_FW_PHY_UNION_NC: ++ case RTL_FW_PHY_UNION_NC1: ++ case RTL_FW_PHY_UNION_NC2: ++ case RTL_FW_PHY_UNION_UC2: ++ case RTL_FW_PHY_UNION_UC: ++ case RTL_FW_PHY_UNION_MISC: ++ if (patch_phy) ++ rtl8152_fw_phy_union_apply(tp, (struct fw_phy_union *)block); ++ break; ++ case RTL_FW_PHY_FIXUP: ++ if (patch_phy) ++ rtl8152_fw_phy_fixup(tp, (struct fw_phy_fixup *)block); ++ break; ++ case RTL_FW_PHY_SPEED_UP: ++ rtl_ram_code_speed_up(tp, (struct fw_phy_speed_up *)block, !power_cut); ++ break; + default: + break; + } +@@ -5034,6 +5566,21 @@ static int r8153c_post_firmware_1(struct + return 0; + } + ++static int r8156a_post_firmware_1(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1); ++ ocp_data |= FW_IP_RESET_EN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1, ocp_data); ++ ++ /* Modify U3PHY parameter for compatibility issue */ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPHY3_MDCMDIO, 0x4026840e); ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPHY3_MDCMDIO, 0x4001acc9); ++ ++ return 0; ++} ++ + static void r8153_aldps_en(struct r8152 *tp, bool enable) + { + u16 data; +@@ -8674,12 +9221,16 @@ static int rtl_ops_init(struct r8152 *tp + #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" + #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" + #define FIRMWARE_8153C_1 "rtl_nic/rtl8153c-1.fw" ++#define FIRMWARE_8156A_2 "rtl_nic/rtl8156a-2.fw" ++#define FIRMWARE_8156B_2 "rtl_nic/rtl8156b-2.fw" + + MODULE_FIRMWARE(FIRMWARE_8153A_2); + MODULE_FIRMWARE(FIRMWARE_8153A_3); + MODULE_FIRMWARE(FIRMWARE_8153A_4); + MODULE_FIRMWARE(FIRMWARE_8153B_2); + MODULE_FIRMWARE(FIRMWARE_8153C_1); ++MODULE_FIRMWARE(FIRMWARE_8156A_2); ++MODULE_FIRMWARE(FIRMWARE_8156B_2); + + static int rtl_fw_init(struct r8152 *tp) + { +@@ -8705,6 +9256,14 @@ static int rtl_fw_init(struct r8152 *tp) + rtl_fw->pre_fw = r8153b_pre_firmware_1; + rtl_fw->post_fw = r8153b_post_firmware_1; + break; ++ case RTL_VER_11: ++ rtl_fw->fw_name = FIRMWARE_8156A_2; ++ rtl_fw->post_fw = r8156a_post_firmware_1; ++ break; ++ case RTL_VER_13: ++ case RTL_VER_15: ++ rtl_fw->fw_name = FIRMWARE_8156B_2; ++ break; + case RTL_VER_14: + rtl_fw->fw_name = FIRMWARE_8153C_1; + rtl_fw->pre_fw = r8153b_pre_firmware_1; diff --git a/target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch b/target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch new file mode 100644 index 0000000000..9ce0e778cf --- /dev/null +++ b/target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch @@ -0,0 +1,79 @@ +From 579f58dd2819910354753bc5489fc1588fe9cfe2 Mon Sep 17 00:00:00 2001 +From: Hayes Wang +Date: Fri, 16 Apr 2021 16:04:37 +0800 +Subject: [PATCH] r8152: search the configuration of vendor mode + +commit c2198943e33b100ed21dfb636c8fa6baef841e9d upstream. + +The vendor mode is not always at config #1, so it is necessary to +set the correct configuration number. + +Signed-off-by: Hayes Wang +Signed-off-by: David S. Miller +--- + drivers/net/usb/r8152.c | 39 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 35 insertions(+), 4 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -30,7 +30,7 @@ + #include + + /* Information for net-next */ +-#define NETNEXT_VERSION "11" ++#define NETNEXT_VERSION "12" + + /* Information for net */ + #define NET_VERSION "11" +@@ -8131,6 +8131,39 @@ static void r8156b_init(struct r8152 *tp + tp->coalesce = 15000; /* 15 us */ + } + ++static bool rtl_vendor_mode(struct usb_interface *intf) ++{ ++ struct usb_host_interface *alt = intf->cur_altsetting; ++ struct usb_device *udev; ++ struct usb_host_config *c; ++ int i, num_configs; ++ ++ if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) ++ return true; ++ ++ /* The vendor mode is not always config #1, so to find it out. */ ++ udev = interface_to_usbdev(intf); ++ c = udev->config; ++ num_configs = udev->descriptor.bNumConfigurations; ++ for (i = 0; i < num_configs; (i++, c++)) { ++ struct usb_interface_descriptor *desc = NULL; ++ ++ if (c->desc.bNumInterfaces > 0) ++ desc = &c->intf_cache[0]->altsetting->desc; ++ else ++ continue; ++ ++ if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) { ++ usb_driver_set_configuration(udev, c->desc.bConfigurationValue); ++ break; ++ } ++ } ++ ++ WARN_ON_ONCE(i == num_configs); ++ ++ return false; ++} ++ + static int rtl8152_pre_reset(struct usb_interface *intf) + { + struct r8152 *tp = usb_get_intfdata(intf); +@@ -9369,10 +9402,8 @@ static int rtl8152_probe(struct usb_inte + if (version == RTL_VER_UNKNOWN) + return -ENODEV; + +- if (udev->actconfig->desc.bConfigurationValue != 1) { +- usb_driver_set_configuration(udev, 1); ++ if (!rtl_vendor_mode(intf)) + return -ENODEV; +- } + + if (intf->cur_altsetting->desc.bNumEndpoints < 3) + return -ENODEV; diff --git a/target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch b/target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch new file mode 100644 index 0000000000..19938704b7 --- /dev/null +++ b/target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch @@ -0,0 +1,80 @@ +From fb009cbdd0693bd633f11e99526617b3d392cfad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Mar 2021 10:03:16 +0100 +Subject: [PATCH] firmware: bcm47xx_nvram: rename finding function and its + variables +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Use "bcm47xx_" function name prefix for consistency +2. It takes flash start as argument so s/iobase/flash_start/ +3. "off" was used for finding flash end so just call it "flash_size" + +Signed-off-by: Rafał Miłecki +Signed-off-by: Thomas Bogendoerfer +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 24 ++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -48,11 +48,13 @@ static u32 find_nvram_size(void __iomem + return 0; + } + +-/* Probe for NVRAM header */ +-static int nvram_find_and_copy(void __iomem *iobase, u32 lim) ++/** ++ * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it ++ */ ++static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size) + { + struct nvram_header __iomem *header; +- u32 off; ++ size_t flash_size; + u32 size; + + if (nvram_len) { +@@ -61,25 +63,25 @@ static int nvram_find_and_copy(void __io + } + + /* TODO: when nvram is on nand flash check for bad blocks first. */ +- off = FLASH_MIN; +- while (off <= lim) { ++ flash_size = FLASH_MIN; ++ while (flash_size <= res_size) { + /* Windowed flash access */ +- size = find_nvram_size(iobase + off); ++ size = find_nvram_size(flash_start + flash_size); + if (size) { +- header = (struct nvram_header *)(iobase + off - size); ++ header = (struct nvram_header *)(flash_start + flash_size - size); + goto found; + } +- off <<= 1; ++ flash_size <<= 1; + } + + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ +- header = (struct nvram_header *)(iobase + 4096); ++ header = (struct nvram_header *)(flash_start + 4096); + if (header->magic == NVRAM_MAGIC) { + size = NVRAM_SPACE; + goto found; + } + +- header = (struct nvram_header *)(iobase + 1024); ++ header = (struct nvram_header *)(flash_start + 1024); + if (header->magic == NVRAM_MAGIC) { + size = NVRAM_SPACE; + goto found; +@@ -124,7 +126,7 @@ int bcm47xx_nvram_init_from_mem(u32 base + if (!iobase) + return -ENOMEM; + +- err = nvram_find_and_copy(iobase, lim); ++ err = bcm47xx_nvram_find_and_copy(iobase, lim); + + iounmap(iobase); + diff --git a/target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch b/target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch new file mode 100644 index 0000000000..6ab072883d --- /dev/null +++ b/target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch @@ -0,0 +1,90 @@ +From 0a24b51a3264a3f942a75025ea5ff6133c8989b0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Mar 2021 10:03:17 +0100 +Subject: [PATCH] firmware: bcm47xx_nvram: add helper checking for NVRAM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This avoids duplicating code doing casting and checking for NVRAM magic. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Thomas Bogendoerfer +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 30 ++++++++++++++--------- + 1 file changed, 18 insertions(+), 12 deletions(-) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -34,14 +34,20 @@ static char nvram_buf[NVRAM_SPACE]; + static size_t nvram_len; + static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; + ++/** ++ * bcm47xx_nvram_is_valid - check for a valid NVRAM at specified memory ++ */ ++static bool bcm47xx_nvram_is_valid(void __iomem *nvram) ++{ ++ return ((struct nvram_header *)nvram)->magic == NVRAM_MAGIC; ++} ++ + static u32 find_nvram_size(void __iomem *end) + { +- struct nvram_header __iomem *header; + int i; + + for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { +- header = (struct nvram_header *)(end - nvram_sizes[i]); +- if (header->magic == NVRAM_MAGIC) ++ if (bcm47xx_nvram_is_valid(end - nvram_sizes[i])) + return nvram_sizes[i]; + } + +@@ -55,6 +61,7 @@ static int bcm47xx_nvram_find_and_copy(v + { + struct nvram_header __iomem *header; + size_t flash_size; ++ size_t offset; + u32 size; + + if (nvram_len) { +@@ -68,31 +75,30 @@ static int bcm47xx_nvram_find_and_copy(v + /* Windowed flash access */ + size = find_nvram_size(flash_start + flash_size); + if (size) { +- header = (struct nvram_header *)(flash_start + flash_size - size); ++ offset = flash_size - size; + goto found; + } + flash_size <<= 1; + } + + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ +- header = (struct nvram_header *)(flash_start + 4096); +- if (header->magic == NVRAM_MAGIC) { +- size = NVRAM_SPACE; ++ ++ offset = 4096; ++ if (bcm47xx_nvram_is_valid(flash_start + offset)) + goto found; +- } + +- header = (struct nvram_header *)(flash_start + 1024); +- if (header->magic == NVRAM_MAGIC) { +- size = NVRAM_SPACE; ++ offset = 1024; ++ if (bcm47xx_nvram_is_valid(flash_start + offset)) + goto found; +- } + + pr_err("no nvram found\n"); + return -ENXIO; + + found: ++ header = (struct nvram_header *)(flash_start + offset); + __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); + nvram_len = ((struct nvram_header *)(nvram_buf))->len; ++ size = res_size - offset; + if (nvram_len > size) { + pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); + nvram_len = size; diff --git a/target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch b/target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch new file mode 100644 index 0000000000..a1351f1197 --- /dev/null +++ b/target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch @@ -0,0 +1,80 @@ +From 298923cf999cecd2ef06df126f85a3d68da8c4d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Mar 2021 10:03:18 +0100 +Subject: [PATCH] firmware: bcm47xx_nvram: extract code copying NVRAM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This simplifies function finding NVRAM. It doesn't directly deal with +NVRAM structure anymore and is a bit smaller. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Thomas Bogendoerfer +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 43 +++++++++++++---------- + 1 file changed, 25 insertions(+), 18 deletions(-) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -55,11 +55,34 @@ static u32 find_nvram_size(void __iomem + } + + /** ++ * bcm47xx_nvram_copy - copy NVRAM to internal buffer ++ */ ++static void bcm47xx_nvram_copy(void __iomem *nvram_start, size_t res_size) ++{ ++ struct nvram_header __iomem *header = nvram_start; ++ size_t copy_size; ++ ++ copy_size = header->len; ++ if (copy_size > res_size) { ++ pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); ++ copy_size = res_size; ++ } ++ if (copy_size >= NVRAM_SPACE) { ++ pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", ++ copy_size, NVRAM_SPACE - 1); ++ copy_size = NVRAM_SPACE - 1; ++ } ++ ++ __ioread32_copy(nvram_buf, nvram_start, DIV_ROUND_UP(copy_size, 4)); ++ nvram_buf[NVRAM_SPACE - 1] = '\0'; ++ nvram_len = copy_size; ++} ++ ++/** + * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it + */ + static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size) + { +- struct nvram_header __iomem *header; + size_t flash_size; + size_t offset; + u32 size; +@@ -95,23 +118,7 @@ static int bcm47xx_nvram_find_and_copy(v + return -ENXIO; + + found: +- header = (struct nvram_header *)(flash_start + offset); +- __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); +- nvram_len = ((struct nvram_header *)(nvram_buf))->len; +- size = res_size - offset; +- if (nvram_len > size) { +- pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); +- nvram_len = size; +- } +- if (nvram_len >= NVRAM_SPACE) { +- pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", +- nvram_len, NVRAM_SPACE - 1); +- nvram_len = NVRAM_SPACE - 1; +- } +- /* proceed reading data after header */ +- __ioread32_copy(nvram_buf + sizeof(*header), header + 1, +- DIV_ROUND_UP(nvram_len, 4)); +- nvram_buf[NVRAM_SPACE - 1] = '\0'; ++ bcm47xx_nvram_copy(flash_start + offset, res_size - offset); + + return 0; + } diff --git a/target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch b/target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch new file mode 100644 index 0000000000..059a13220b --- /dev/null +++ b/target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch @@ -0,0 +1,37 @@ +From 98b68324f67236e8c9152976535dc1f27fb67ba8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Mar 2021 10:03:19 +0100 +Subject: [PATCH] firmware: bcm47xx_nvram: look for NVRAM with for instead of + while +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This loop requires variable initialization, stop condition and post +iteration increment. It's pretty much a for loop definition. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Thomas Bogendoerfer +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -93,15 +93,13 @@ static int bcm47xx_nvram_find_and_copy(v + } + + /* TODO: when nvram is on nand flash check for bad blocks first. */ +- flash_size = FLASH_MIN; +- while (flash_size <= res_size) { ++ for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { + /* Windowed flash access */ + size = find_nvram_size(flash_start + flash_size); + if (size) { + offset = flash_size - size; + goto found; + } +- flash_size <<= 1; + } + + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ diff --git a/target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch b/target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch new file mode 100644 index 0000000000..21d250049e --- /dev/null +++ b/target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch @@ -0,0 +1,70 @@ +From f52da4ccfec9192e17f5c16260dfdd6d3ea76f65 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Mar 2021 10:03:20 +0100 +Subject: [PATCH] firmware: bcm47xx_nvram: inline code checking NVRAM size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Separated function was not improving code quality much (or at all). +Moreover it expected possible flash end address as argument and it was +returning NVRAM size. + +The new code always operates on offsets which means less logic and less +calculations. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Thomas Bogendoerfer +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 25 +++++++---------------- + 1 file changed, 7 insertions(+), 18 deletions(-) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -42,18 +42,6 @@ static bool bcm47xx_nvram_is_valid(void + return ((struct nvram_header *)nvram)->magic == NVRAM_MAGIC; + } + +-static u32 find_nvram_size(void __iomem *end) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { +- if (bcm47xx_nvram_is_valid(end - nvram_sizes[i])) +- return nvram_sizes[i]; +- } +- +- return 0; +-} +- + /** + * bcm47xx_nvram_copy - copy NVRAM to internal buffer + */ +@@ -85,7 +73,7 @@ static int bcm47xx_nvram_find_and_copy(v + { + size_t flash_size; + size_t offset; +- u32 size; ++ int i; + + if (nvram_len) { + pr_warn("nvram already initialized\n"); +@@ -93,12 +81,13 @@ static int bcm47xx_nvram_find_and_copy(v + } + + /* TODO: when nvram is on nand flash check for bad blocks first. */ ++ ++ /* Try every possible flash size and check for NVRAM at its end */ + for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { +- /* Windowed flash access */ +- size = find_nvram_size(flash_start + flash_size); +- if (size) { +- offset = flash_size - size; +- goto found; ++ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { ++ offset = flash_size - nvram_sizes[i]; ++ if (bcm47xx_nvram_is_valid(flash_start + offset)) ++ goto found; + } + } + diff --git a/target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch b/target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch new file mode 100644 index 0000000000..6b75b08717 --- /dev/null +++ b/target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch @@ -0,0 +1,88 @@ +From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Tue, 23 Feb 2021 18:44:53 +0100 +Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent + checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds an ignore_oc flag which can be set by EHCI controller +not supporting or wanting to disable overcurrent checking. The EHCI +platform data in include/linux/usb/ehci_pdriver.h is also augmented to +take advantage of this new flag. + +Signed-off-by: Florian Fainelli +Signed-off-by: Álvaro Fernández Rojas +Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/ehci-hcd.c | 2 +- + drivers/usb/host/ehci-hub.c | 4 ++-- + drivers/usb/host/ehci-platform.c | 2 ++ + drivers/usb/host/ehci.h | 1 + + include/linux/usb/ehci_pdriver.h | 1 + + 5 files changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -660,7 +660,7 @@ static int ehci_run (struct usb_hcd *hcd + "USB %x.%x started, EHCI %x.%02x%s\n", + ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), + temp >> 8, temp & 0xff, +- ignore_oc ? ", overcurrent ignored" : ""); ++ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : ""); + + ehci_writel(ehci, INTR_MASK, + &ehci->regs->intr_enable); /* Turn On Interrupts */ +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -643,7 +643,7 @@ ehci_hub_status_data (struct usb_hcd *hc + * always set, seem to clear PORT_OCC and PORT_CSC when writing to + * PORT_POWER; that's surprising, but maybe within-spec. + */ +- if (!ignore_oc) ++ if (!ignore_oc && !ehci->spurious_oc) + mask = PORT_CSC | PORT_PEC | PORT_OCC; + else + mask = PORT_CSC | PORT_PEC; +@@ -1013,7 +1013,7 @@ int ehci_hub_control( + if (temp & PORT_PEC) + status |= USB_PORT_STAT_C_ENABLE << 16; + +- if ((temp & PORT_OCC) && !ignore_oc){ ++ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){ + status |= USB_PORT_STAT_C_OVERCURRENT << 16; + + /* +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -333,6 +333,8 @@ static int ehci_platform_probe(struct pl + hcd->has_tt = 1; + if (pdata->reset_on_resume) + priv->reset_on_resume = true; ++ if (pdata->spurious_oc) ++ ehci->spurious_oc = 1; + + #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO + if (ehci->big_endian_mmio) { +--- a/drivers/usb/host/ehci.h ++++ b/drivers/usb/host/ehci.h +@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controlle + unsigned need_oc_pp_cycle:1; /* MPC834X port power */ + unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ + unsigned is_aspeed:1; ++ unsigned spurious_oc:1; + + /* required for usb32 quirk */ + #define OHCI_CTRL_HCFS (3 << 6) +--- a/include/linux/usb/ehci_pdriver.h ++++ b/include/linux/usb/ehci_pdriver.h +@@ -50,6 +50,7 @@ struct usb_ehci_pdata { + unsigned no_io_watchdog:1; + unsigned reset_on_resume:1; + unsigned dma_mask_64:1; ++ unsigned spurious_oc:1; + + /* Turn on all power and clocks */ + int (*power_on)(struct platform_device *pdev); diff --git a/target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch b/target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch new file mode 100644 index 0000000000..0094d47718 --- /dev/null +++ b/target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch @@ -0,0 +1,31 @@ +From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Tue, 23 Feb 2021 18:44:55 +0100 +Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Over-current reporting isn't supported on some platforms such as bcm63xx. +These devices will incorrectly report over-current if this flag isn't properly +activated. + +Signed-off-by: Álvaro Fernández Rojas +Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/ehci-platform.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl + if (of_property_read_bool(dev->dev.of_node, "big-endian")) + ehci->big_endian_mmio = ehci->big_endian_desc = 1; + ++ if (of_property_read_bool(dev->dev.of_node, "spurious-oc")) ++ ehci->spurious_oc = 1; ++ + if (of_property_read_bool(dev->dev.of_node, + "needs-reset-on-resume")) + priv->reset_on_resume = true; diff --git a/target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch b/target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch new file mode 100644 index 0000000000..8ca2b78f74 --- /dev/null +++ b/target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch @@ -0,0 +1,34 @@ +From 9ec37efb87832b578d7972fc80b04d94f5d2bbe3 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Tue, 30 Mar 2021 16:11:42 +0100 +Subject: PCI/MSI: Make pci_host_common_probe() declare its reliance on MSI + domains + +The generic PCI host driver relies on MSI domains for MSIs to +be provided to its end-points. Make this dependency explicit. + +This cures the warnings occuring on arm/arm64 VMs when booted +with PCI virtio devices and no MSI controller (no GICv3 ITS, +for example). + +It is likely that other drivers will need to express the same +dependency. + +Link: https://lore.kernel.org/r/20210330151145.997953-12-maz@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Lorenzo Pieralisi +Acked-by: Bjorn Helgaas +--- + drivers/pci/controller/pci-host-common.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/pci/controller/pci-host-common.c ++++ b/drivers/pci/controller/pci-host-common.c +@@ -77,6 +77,7 @@ int pci_host_common_probe(struct platfor + + bridge->sysdata = cfg; + bridge->ops = (struct pci_ops *)&ops->pci_ops; ++ bridge->msi_domain = true; + + platform_set_drvdata(pdev, bridge); + diff --git a/target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch b/target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch new file mode 100644 index 0000000000..854dc34c42 --- /dev/null +++ b/target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch @@ -0,0 +1,44 @@ +From 94e89b145371b68fa0ea294855adebcd03e0522e Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Tue, 30 Mar 2021 16:11:41 +0100 +Subject: PCI/MSI: Let PCI host bridges declare their reliance on MSI domains + +There is a whole class of host bridges that cannot know whether +MSIs will be provided or not, as they rely on other blocks +to provide the MSI functionnality, using MSI domains. This is +the case for example on systems that use the ARM GIC architecture. + +Introduce a new attribute ('msi_domain') indicating that implicit +dependency, and use this property to set the NO_MSI flag when +no MSI domain is found at probe time. + +Link: https://lore.kernel.org/r/20210330151145.997953-11-maz@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Lorenzo Pieralisi +Acked-by: Bjorn Helgaas +--- + drivers/pci/probe.c | 2 ++ + include/linux/pci.h | 1 + + 2 files changed, 3 insertions(+) + +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -925,6 +925,8 @@ static int pci_register_host_bridge(stru + device_enable_async_suspend(bus->bridge); + pci_set_bus_of_node(bus); + pci_set_bus_msi_domain(bus); ++ if (bridge->msi_domain && !dev_get_msi_domain(&bus->dev)) ++ bus->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + + if (!parent) + set_dev_node(bus->bridge, pcibus_to_node(bus)); +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -547,6 +547,7 @@ struct pci_host_bridge { + unsigned int native_dpc:1; /* OS may use PCIe DPC */ + unsigned int preserve_config:1; /* Preserve FW resource setup */ + unsigned int size_windows:1; /* Enable root bus sizing */ ++ unsigned int msi_domain:1; /* Bridge wants MSI domain */ + + /* Resource alignment requirements */ + resource_size_t (*align_resource)(struct pci_dev *dev, diff --git a/target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch b/target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch new file mode 100644 index 0000000000..c11aedd814 --- /dev/null +++ b/target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch @@ -0,0 +1,59 @@ +From 645e9c38383d7fcde2784ee537fa18ec9bed54d9 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 30 Mar 2021 16:11:43 +0100 +Subject: PCI: mediatek: Advertise lack of built-in MSI handling + +Some Mediatek host bridges cannot handle MSIs, which is sad. +This also results in an ugly warning at device probe time, +as the core PCI code wasn't told that MSIs were not available. + +Advertise this fact to the rest of the core PCI code by +using the 'msi_domain' attribute, which still opens the possibility +for another block to provide the MSI functionnality. + +[maz: commit message, switched over to msi_domain attribute] + +Link: https://lore.kernel.org/r/20210330151145.997953-13-maz@kernel.org +Reported-by: Frank Wunderlich +Signed-off-by: Thomas Gleixner +Signed-off-by: Marc Zyngier +Signed-off-by: Lorenzo Pieralisi +Acked-by: Bjorn Helgaas +--- + drivers/pci/controller/pcie-mediatek.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -143,6 +143,7 @@ struct mtk_pcie_port; + * struct mtk_pcie_soc - differentiate between host generations + * @need_fix_class_id: whether this host's class ID needed to be fixed or not + * @need_fix_device_id: whether this host's device ID needed to be fixed or not ++ * @no_msi: Bridge has no MSI support, and relies on an external block + * @device_id: device ID which this host need to be fixed + * @ops: pointer to configuration access functions + * @startup: pointer to controller setting functions +@@ -151,6 +152,7 @@ struct mtk_pcie_port; + struct mtk_pcie_soc { + bool need_fix_class_id; + bool need_fix_device_id; ++ bool no_msi; + unsigned int device_id; + struct pci_ops *ops; + int (*startup)(struct mtk_pcie_port *port); +@@ -1087,6 +1089,7 @@ static int mtk_pcie_probe(struct platfor + + host->ops = pcie->soc->ops; + host->sysdata = pcie; ++ host->msi_domain = pcie->soc->no_msi; + + err = pci_host_probe(host); + if (err) +@@ -1176,6 +1179,7 @@ static const struct dev_pm_ops mtk_pcie_ + }; + + static const struct mtk_pcie_soc mtk_pcie_soc_v1 = { ++ .no_msi = true, + .ops = &mtk_pcie_ops, + .startup = mtk_pcie_startup_port, + }; diff --git a/target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch b/target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch new file mode 100644 index 0000000000..75b9947392 --- /dev/null +++ b/target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch @@ -0,0 +1,28 @@ +From a5d3d1adc95f4ac5968b7a77ee95a3abbbb96f49 Mon Sep 17 00:00:00 2001 +From: Doug Zobel +Date: Mon, 10 May 2021 15:40:00 -0500 +Subject: [PATCH] leds: lp55xx: Initialize enable GPIO direction to output + +The "Convert to use GPIO descriptors" commit changed the +initialization of the enable GPIO from GPIOF_DIR_OUT to +GPIOD_ASIS. This breaks systems where the GPIO does not +default to output. Changing the enable initialization +to GPIOD_OUT_LOW. + +Signed-off-by: Doug Zobel +Signed-off-by: Pavel Machek +--- + drivers/leds/leds-lp55xx-common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/leds/leds-lp55xx-common.c ++++ b/drivers/leds/leds-lp55xx-common.c +@@ -694,7 +694,7 @@ struct lp55xx_platform_data *lp55xx_of_p + of_property_read_u8(np, "clock-mode", &pdata->clock_mode); + + pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable", +- GPIOD_ASIS); ++ GPIOD_OUT_LOW); + if (IS_ERR(pdata->enable_gpiod)) + return ERR_CAST(pdata->enable_gpiod); + diff --git a/target/linux/generic/backport-5.15/850-v5.17-0001-PCI-pci-bridge-emul-Add-description-for-class_revisi.patch b/target/linux/generic/backport-5.15/850-v5.17-0001-PCI-pci-bridge-emul-Add-description-for-class_revisi.patch new file mode 100644 index 0000000000..19a4be2a9d --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0001-PCI-pci-bridge-emul-Add-description-for-class_revisi.patch @@ -0,0 +1,44 @@ +From 9319230ac147067652b58fe849ffe0ceec098665 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:03 +0100 +Subject: [PATCH] PCI: pci-bridge-emul: Add description for class_revision + field +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The current assignment to the class_revision member + + class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16); + +can make the reader think that class is at high 16 bits of the member and +revision at low 16 bits. + +In reality, class is at high 24 bits, but the class for PCI Bridge Normal +Decode is PCI_CLASS_BRIDGE_PCI << 8. + +Change the assignment and add a comment to make this clearer. + +Link: https://lore.kernel.org/r/20211130172913.9727-2-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/pci-bridge-emul.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/pci/pci-bridge-emul.c ++++ b/drivers/pci/pci-bridge-emul.c +@@ -284,7 +284,11 @@ int pci_bridge_emul_init(struct pci_brid + { + BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END); + +- bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16); ++ /* ++ * class_revision: Class is high 24 bits and revision is low 8 bit of this member, ++ * while class for PCI Bridge Normal Decode has the 24-bit value: PCI_CLASS_BRIDGE_PCI << 8 ++ */ ++ bridge->conf.class_revision |= cpu_to_le32((PCI_CLASS_BRIDGE_PCI << 8) << 8); + bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; + bridge->conf.cache_line_size = 0x10; + bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0002-PCI-pci-bridge-emul-Add-definitions-for-missing-capa.patch b/target/linux/generic/backport-5.15/850-v5.17-0002-PCI-pci-bridge-emul-Add-definitions-for-missing-capa.patch new file mode 100644 index 0000000000..3dd82710e6 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0002-PCI-pci-bridge-emul-Add-definitions-for-missing-capa.patch @@ -0,0 +1,73 @@ +From 8ea673a8b30b4a32516b8adabb15e2a68ff02ec8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:04 +0100 +Subject: [PATCH] PCI: pci-bridge-emul: Add definitions for missing + capabilities registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +pci-bridge-emul driver already allocates buffer for capabilities up to the +PCI_EXP_SLTSTA2 register, but does not define bit access behavior for these +registers. Add these missing definitions. + +Link: https://lore.kernel.org/r/20211130172913.9727-3-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/pci-bridge-emul.c | 43 +++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +--- a/drivers/pci/pci-bridge-emul.c ++++ b/drivers/pci/pci-bridge-emul.c +@@ -270,6 +270,49 @@ struct pci_bridge_reg_behavior pcie_cap_ + .ro = GENMASK(15, 0) | PCI_EXP_RTSTA_PENDING, + .w1c = PCI_EXP_RTSTA_PME, + }, ++ ++ [PCI_EXP_DEVCAP2 / 4] = { ++ /* ++ * Device capabilities 2 register has reserved bits [30:27]. ++ * Also bits [26:24] are reserved for non-upstream ports. ++ */ ++ .ro = BIT(31) | GENMASK(23, 0), ++ }, ++ ++ [PCI_EXP_DEVCTL2 / 4] = { ++ /* ++ * Device control 2 register is RW. Bit 11 is reserved for ++ * non-upstream ports. ++ * ++ * Device status 2 register is reserved. ++ */ ++ .rw = GENMASK(15, 12) | GENMASK(10, 0), ++ }, ++ ++ [PCI_EXP_LNKCAP2 / 4] = { ++ /* Link capabilities 2 register has reserved bits [30:25] and 0. */ ++ .ro = BIT(31) | GENMASK(24, 1), ++ }, ++ ++ [PCI_EXP_LNKCTL2 / 4] = { ++ /* ++ * Link control 2 register is RW. ++ * ++ * Link status 2 register has bits 5, 15 W1C; ++ * bits 10, 11 reserved and others are RO. ++ */ ++ .rw = GENMASK(15, 0), ++ .w1c = (BIT(15) | BIT(5)) << 16, ++ .ro = (GENMASK(14, 12) | GENMASK(9, 6) | GENMASK(4, 0)) << 16, ++ }, ++ ++ [PCI_EXP_SLTCAP2 / 4] = { ++ /* Slot capabilities 2 register is reserved. */ ++ }, ++ ++ [PCI_EXP_SLTCTL2 / 4] = { ++ /* Both Slot control 2 and Slot status 2 registers are reserved. */ ++ }, + }; + + /* diff --git a/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch b/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch new file mode 100644 index 0000000000..ce38719009 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch @@ -0,0 +1,61 @@ +From 1d3e170344dff2cef8827db6c09909b78cbc11d7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:05 +0100 +Subject: [PATCH] PCI: aardvark: Add support for DEVCAP2, DEVCTL2, LNKCAP2 and + LNKCTL2 registers on emulated bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +PCI aardvark hardware supports access to DEVCAP2, DEVCTL2, LNKCAP2 and +LNKCTL2 configuration registers of PCIe core via PCIE_CORE_PCIEXP_CAP. +Export them via emulated software root bridge. + +Link: https://lore.kernel.org/r/20211130172913.9727-4-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -881,8 +881,13 @@ advk_pci_bridge_emul_pcie_conf_read(stru + + case PCI_EXP_DEVCAP: + case PCI_EXP_DEVCTL: ++ case PCI_EXP_DEVCAP2: ++ case PCI_EXP_DEVCTL2: ++ case PCI_EXP_LNKCAP2: ++ case PCI_EXP_LNKCTL2: + *value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); + return PCI_BRIDGE_EMUL_HANDLED; ++ + default: + return PCI_BRIDGE_EMUL_NOT_HANDLED; + } +@@ -896,10 +901,6 @@ advk_pci_bridge_emul_pcie_conf_write(str + struct advk_pcie *pcie = bridge->data; + + switch (reg) { +- case PCI_EXP_DEVCTL: +- advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); +- break; +- + case PCI_EXP_LNKCTL: + advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); + if (new & PCI_EXP_LNKCTL_RL) +@@ -921,6 +922,12 @@ advk_pci_bridge_emul_pcie_conf_write(str + advk_writel(pcie, new, PCIE_ISR0_REG); + break; + ++ case PCI_EXP_DEVCTL: ++ case PCI_EXP_DEVCTL2: ++ case PCI_EXP_LNKCTL2: ++ advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); ++ break; ++ + default: + break; + } diff --git a/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch b/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch new file mode 100644 index 0000000000..66c7e60202 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch @@ -0,0 +1,59 @@ +From 7d8dc1f7cd007a7ce94c5b4c20d63a8b8d6d7751 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:06 +0100 +Subject: [PATCH] PCI: aardvark: Clear all MSIs at setup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We already clear all the other interrupts (ISR0, ISR1, HOST_CTRL_INT). + +Define a new macro PCIE_MSI_ALL_MASK and do the same clearing for MSIs, +to ensure that we don't start receiving spurious interrupts. + +Use this new mask in advk_pcie_handle_msi(); + +Link: https://lore.kernel.org/r/20211130172913.9727-5-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -114,6 +114,7 @@ + #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) + #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) + #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) ++#define PCIE_MSI_ALL_MASK GENMASK(31, 0) + #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) + #define PCIE_MSI_DATA_MASK GENMASK(15, 0) + +@@ -577,6 +578,7 @@ static void advk_pcie_setup_hw(struct ad + advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); + + /* Clear all interrupts */ ++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG); + advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG); + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); +@@ -589,7 +591,7 @@ static void advk_pcie_setup_hw(struct ad + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); + + /* Unmask all MSIs */ +- advk_writel(pcie, 0, PCIE_MSI_MASK_REG); ++ advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); + + /* Enable summary interrupt for GIC SPI source */ + reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); +@@ -1399,7 +1401,7 @@ static void advk_pcie_handle_msi(struct + + msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG); + msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG); +- msi_status = msi_val & ~msi_mask; ++ msi_status = msi_val & ((~msi_mask) & PCIE_MSI_ALL_MASK); + + for (msi_idx = 0; msi_idx < MSI_IRQ_NUM; msi_idx++) { + if (!(BIT(msi_idx) & msi_status)) diff --git a/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch b/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch new file mode 100644 index 0000000000..8870e47b40 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch @@ -0,0 +1,34 @@ +From a4ca7948e1d47275f8f3e5023243440c40561916 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:07 +0100 +Subject: [PATCH] PCI: aardvark: Comment actions in driver remove method +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add two more comments into the advk_pcie_remove() method. + +Link: https://lore.kernel.org/r/20211130172913.9727-6-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1698,11 +1698,13 @@ static int advk_pcie_remove(struct platf + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); + int i; + ++ /* Remove PCI bus with all devices */ + pci_lock_rescan_remove(); + pci_stop_root_bus(bridge->bus); + pci_remove_root_bus(bridge->bus); + pci_unlock_rescan_remove(); + ++ /* Remove IRQ domains */ + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + diff --git a/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch b/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch new file mode 100644 index 0000000000..f1c3f3bb13 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch @@ -0,0 +1,41 @@ +From a46f2f6dd4093438d9615dfbf5c0fea2a9835dba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:08 +0100 +Subject: [PATCH] PCI: aardvark: Disable bus mastering when unbinding driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ensure that after driver unbind PCIe cards are not able to forward +memory and I/O requests in the upstream direction. + +Link: https://lore.kernel.org/r/20211130172913.9727-7-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1696,6 +1696,7 @@ static int advk_pcie_remove(struct platf + { + struct advk_pcie *pcie = platform_get_drvdata(pdev); + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); ++ u32 val; + int i; + + /* Remove PCI bus with all devices */ +@@ -1704,6 +1705,11 @@ static int advk_pcie_remove(struct platf + pci_remove_root_bus(bridge->bus); + pci_unlock_rescan_remove(); + ++ /* Disable Root Bridge I/O space, memory space and bus mastering */ ++ val = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); ++ val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); ++ advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG); ++ + /* Remove IRQ domains */ + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch b/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch new file mode 100644 index 0000000000..7add045cab --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch @@ -0,0 +1,48 @@ +From 13bcdf07cb2ecff5d45d2c141df2539b15211448 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:09 +0100 +Subject: [PATCH] PCI: aardvark: Mask all interrupts when unbinding driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ensure that no interrupt can be triggered after driver unbind. + +Link: https://lore.kernel.org/r/20211130172913.9727-8-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1710,6 +1710,27 @@ static int advk_pcie_remove(struct platf + val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG); + ++ /* Disable MSI */ ++ val = advk_readl(pcie, PCIE_CORE_CTRL2_REG); ++ val &= ~PCIE_CORE_CTRL2_MSI_ENABLE; ++ advk_writel(pcie, val, PCIE_CORE_CTRL2_REG); ++ ++ /* Clear MSI address */ ++ advk_writel(pcie, 0, PCIE_MSI_ADDR_LOW_REG); ++ advk_writel(pcie, 0, PCIE_MSI_ADDR_HIGH_REG); ++ ++ /* Mask all interrupts */ ++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); ++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG); ++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); ++ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_MASK_REG); ++ ++ /* Clear all interrupts */ ++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG); ++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG); ++ advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); ++ advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); ++ + /* Remove IRQ domains */ + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch b/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch new file mode 100644 index 0000000000..f86d2bd61f --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch @@ -0,0 +1,33 @@ +From 2f040a17f5061457ae95035326d3159eddc1e5cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:10 +0100 +Subject: [PATCH] PCI: aardvark: Fix memory leak in driver unbind +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Free config space for emulated root bridge when unbinding driver to fix +memory leak. Do it after disabling and masking all interrupts, since +aardvark interrupt handler accesses config space of emulated root +bridge. + +Link: https://lore.kernel.org/r/20211130172913.9727-9-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1735,6 +1735,9 @@ static int advk_pcie_remove(struct platf + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + ++ /* Free config space for emulated root bridge */ ++ pci_bridge_emul_cleanup(&pcie->bridge); ++ + /* Disable outbound address windows mapping */ + for (i = 0; i < OB_WIN_COUNT; i++) + advk_pcie_disable_ob_win(pcie, i); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch b/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch new file mode 100644 index 0000000000..1e9e74136c --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch @@ -0,0 +1,33 @@ +From 1f54391be8ce0c981d312cb93acdc5608def576a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:11 +0100 +Subject: [PATCH] PCI: aardvark: Assert PERST# when unbinding driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Put the PCIe card into reset by asserting PERST# signal when unbinding +driver. It doesn't make sense to leave the card working if it can't +communicate with the host. This should also save some power. + +Link: https://lore.kernel.org/r/20211130172913.9727-10-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1738,6 +1738,10 @@ static int advk_pcie_remove(struct platf + /* Free config space for emulated root bridge */ + pci_bridge_emul_cleanup(&pcie->bridge); + ++ /* Assert PERST# signal which prepares PCIe card for power down */ ++ if (pcie->reset_gpio) ++ gpiod_set_value_cansleep(pcie->reset_gpio, 1); ++ + /* Disable outbound address windows mapping */ + for (i = 0; i < OB_WIN_COUNT; i++) + advk_pcie_disable_ob_win(pcie, i); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch b/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch new file mode 100644 index 0000000000..3b531deae0 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch @@ -0,0 +1,34 @@ +From 759dec2e3dfdbd261c41d2279f04f2351c971a49 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:12 +0100 +Subject: [PATCH] PCI: aardvark: Disable link training when unbinding driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Disable link training circuit in driver unbind sequence. We want to +leave link training in the same state as it was before the driver was +probed. + +Link: https://lore.kernel.org/r/20211130172913.9727-11-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1742,6 +1742,11 @@ static int advk_pcie_remove(struct platf + if (pcie->reset_gpio) + gpiod_set_value_cansleep(pcie->reset_gpio, 1); + ++ /* Disable link training */ ++ val = advk_readl(pcie, PCIE_CORE_CTRL0_REG); ++ val &= ~LINK_TRAINING_EN; ++ advk_writel(pcie, val, PCIE_CORE_CTRL0_REG); ++ + /* Disable outbound address windows mapping */ + for (i = 0; i < OB_WIN_COUNT; i++) + advk_pcie_disable_ob_win(pcie, i); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch b/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch new file mode 100644 index 0000000000..6caa6eb362 --- /dev/null +++ b/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch @@ -0,0 +1,30 @@ +From fdbbe242c15a8f2cd0e3ad8a56cd0a447b771d0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Tue, 30 Nov 2021 18:29:13 +0100 +Subject: [PATCH] PCI: aardvark: Disable common PHY when unbinding driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Disable the PCIe PHY when unbinding driver. This should save some power. + +Link: https://lore.kernel.org/r/20211130172913.9727-12-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +--- + drivers/pci/controller/pci-aardvark.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1751,6 +1751,9 @@ static int advk_pcie_remove(struct platf + for (i = 0; i < OB_WIN_COUNT; i++) + advk_pcie_disable_ob_win(pcie, i); + ++ /* Disable phy */ ++ advk_pcie_disable_phy(pcie); ++ + return 0; + } + diff --git a/target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch b/target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch new file mode 100644 index 0000000000..4f867724ac --- /dev/null +++ b/target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch @@ -0,0 +1,67 @@ +From 40da06da15c1718b02072687bbfb2d08f5eb9399 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 27 Aug 2021 11:27:52 +0200 +Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Rename HS-SGMMI to + 2500Base-X +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Comphy phy mode 0x3 is incorrectly named. It is not SGMII but rather +2500Base-X mode which runs at 3.125 Gbps speed. + +Rename macro names and comments to 2500Base-X. + +Signed-off-by: Pali Rohár +Fixes: 9695375a3f4a ("phy: add A3700 COMPHY support") +Signed-off-by: David S. Miller +--- + drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -29,7 +29,7 @@ + + #define COMPHY_FW_MODE_SATA 0x1 + #define COMPHY_FW_MODE_SGMII 0x2 +-#define COMPHY_FW_MODE_HS_SGMII 0x3 ++#define COMPHY_FW_MODE_2500BASEX 0x3 + #define COMPHY_FW_MODE_USB3H 0x4 + #define COMPHY_FW_MODE_USB3D 0x5 + #define COMPHY_FW_MODE_PCIE 0x6 +@@ -40,7 +40,7 @@ + + #define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ + #define COMPHY_FW_SPEED_2_5G 1 +-#define COMPHY_FW_SPEED_3_125G 2 /* SGMII 2.5G */ ++#define COMPHY_FW_SPEED_3_125G 2 /* 2500BASE-X */ + #define COMPHY_FW_SPEED_5G 3 + #define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */ + #define COMPHY_FW_SPEED_6G 5 +@@ -84,14 +84,14 @@ static const struct mvebu_a3700_comphy_c + MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1, + COMPHY_FW_MODE_SGMII), + MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1, +- COMPHY_FW_MODE_HS_SGMII), ++ COMPHY_FW_MODE_2500BASEX), + /* lane 1 */ + MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0, + COMPHY_FW_MODE_PCIE), + MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0, + COMPHY_FW_MODE_SGMII), + MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0, +- COMPHY_FW_MODE_HS_SGMII), ++ COMPHY_FW_MODE_2500BASEX), + /* lane 2 */ + MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0, + COMPHY_FW_MODE_SATA), +@@ -205,7 +205,7 @@ static int mvebu_a3700_comphy_power_on(s + COMPHY_FW_SPEED_1_25G); + break; + case PHY_INTERFACE_MODE_2500BASEX: +- dev_dbg(lane->dev, "set lane %d to HS SGMII mode\n", ++ dev_dbg(lane->dev, "set lane %d to 2500BASEX mode\n", + lane->id); + fw_param = COMPHY_FW_NET(fw_mode, lane->port, + COMPHY_FW_SPEED_3_125G); diff --git a/target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch b/target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch new file mode 100644 index 0000000000..99f56f1c57 --- /dev/null +++ b/target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch @@ -0,0 +1,40 @@ +From e1dbe9ecf621b6f71f3d2df3e50731d583f3d27f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 27 Aug 2021 11:27:53 +0200 +Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Remove unsupported + modes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Armada 3700 does not support RXAUI, XFI and neither SFI. Remove unused +macros for these unsupported modes. + +Signed-off-by: Pali Rohár +Fixes: 9695375a3f4a ("phy: add A3700 COMPHY support") +Signed-off-by: David S. Miller +--- + drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -33,18 +33,12 @@ + #define COMPHY_FW_MODE_USB3H 0x4 + #define COMPHY_FW_MODE_USB3D 0x5 + #define COMPHY_FW_MODE_PCIE 0x6 +-#define COMPHY_FW_MODE_RXAUI 0x7 +-#define COMPHY_FW_MODE_XFI 0x8 +-#define COMPHY_FW_MODE_SFI 0x9 + #define COMPHY_FW_MODE_USB3 0xa + + #define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ + #define COMPHY_FW_SPEED_2_5G 1 + #define COMPHY_FW_SPEED_3_125G 2 /* 2500BASE-X */ + #define COMPHY_FW_SPEED_5G 3 +-#define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */ +-#define COMPHY_FW_SPEED_6G 5 +-#define COMPHY_FW_SPEED_10_3125G 6 /* XFI 10G */ + #define COMPHY_FW_SPEED_MAX 0x3F + + #define COMPHY_FW_MODE(mode) ((mode) << 12) diff --git a/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch b/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch new file mode 100644 index 0000000000..971562a8f7 --- /dev/null +++ b/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch @@ -0,0 +1,49 @@ +From d3115128bdafb62628ab41861a4f06f6d02ac320 Mon Sep 17 00:00:00 2001 +From: Lech Perczak +Date: Mon, 10 Jan 2022 23:48:44 +0100 +Subject: MIPS: ath79: drop _machine_restart again + +Commit 81424d0ad0d4 ("MIPS: ath79: Use the reset controller to restart +OF machines") removed setup of _machine_restart on OF machines to use +reset handler in reset controller driver. +While removing remnants of non-OF machines in commit 3a77e0d75eed +("MIPS: ath79: drop machfiles"), this was introduced again, making it +impossible to use additional restart handlers registered through device +tree. Drop setting _machine_restart altogether, and ath79_restart +function, which is no longer used after this. + +Fixes: 3a77e0d75eed ("MIPS: ath79: drop machfiles") +Cc: John Crispin +Cc: Florian Fainelli +Signed-off-by: Lech Perczak +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/ath79/setup.c | 10 ---------- + 1 file changed, 10 deletions(-) + +--- a/arch/mips/ath79/setup.c ++++ b/arch/mips/ath79/setup.c +@@ -34,15 +34,6 @@ + + static char ath79_sys_type[ATH79_SYS_TYPE_LEN]; + +-static void ath79_restart(char *command) +-{ +- local_irq_disable(); +- ath79_device_reset_set(AR71XX_RESET_FULL_CHIP); +- for (;;) +- if (cpu_wait) +- cpu_wait(); +-} +- + static void ath79_halt(void) + { + while (1) +@@ -233,7 +224,6 @@ void __init plat_mem_setup(void) + + detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); + +- _machine_restart = ath79_restart; + _machine_halt = ath79_halt; + pm_power_off = ath79_halt; + } diff --git a/target/linux/generic/backport-5.15/870-hwmon-next-hwmon-lm70-Add-ti-tmp125-support.patch b/target/linux/generic/backport-5.15/870-hwmon-next-hwmon-lm70-Add-ti-tmp125-support.patch new file mode 100644 index 0000000000..fabf177628 --- /dev/null +++ b/target/linux/generic/backport-5.15/870-hwmon-next-hwmon-lm70-Add-ti-tmp125-support.patch @@ -0,0 +1,71 @@ +From 31d8f414e1596ba54a4315418e4c0086fda9e428 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 18 Feb 2022 10:06:43 +0100 +Subject: hwmon: (lm70) Add ti,tmp125 support + +The TMP125 is a 2 degree Celsius accurate Digital +Temperature Sensor with a SPI interface. + +The temperature register is a 16-bit, read-only register. +The MSB (Bit 15) is a leading zero and never set. Bits 14 +to 5 are the 1+9 temperature data bits in a two's +complement format. Bits 4 to 0 are useless copies of +Bit 5 value and therefore ignored. + +Signed-off-by: Christian Lamparter +Link: https://lore.kernel.org/r/43b19cbd4e7f51e9509e561b02b5d8d0e7079fac.1645175187.git.chunkeey@gmail.com +Signed-off-by: Guenter Roeck +--- +--- a/drivers/hwmon/lm70.c ++++ b/drivers/hwmon/lm70.c +@@ -34,6 +34,7 @@ + #define LM70_CHIP_LM71 2 /* NS LM71 */ + #define LM70_CHIP_LM74 3 /* NS LM74 */ + #define LM70_CHIP_TMP122 4 /* TI TMP122/TMP124 */ ++#define LM70_CHIP_TMP125 5 /* TI TMP125 */ + + struct lm70 { + struct spi_device *spi; +@@ -87,6 +88,12 @@ static ssize_t temp1_input_show(struct d + * LM71: + * 14 bits of 2's complement data, discard LSB 2 bits, + * resolution 0.0312 degrees celsius. ++ * ++ * TMP125: ++ * MSB/D15 is a leading zero. D14 is the sign-bit. This is ++ * followed by 9 temperature bits (D13..D5) in 2's complement ++ * data format with a resolution of 0.25 degrees celsius per unit. ++ * LSB 5 bits (D4..D0) share the same value as D5 and get discarded. + */ + switch (p_lm70->chip) { + case LM70_CHIP_LM70: +@@ -102,6 +109,10 @@ static ssize_t temp1_input_show(struct d + case LM70_CHIP_LM71: + val = ((int)raw / 4) * 3125 / 100; + break; ++ ++ case LM70_CHIP_TMP125: ++ val = (sign_extend32(raw, 14) / 32) * 250; ++ break; + } + + status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ +@@ -136,6 +147,10 @@ static const struct of_device_id lm70_of + .data = (void *) LM70_CHIP_TMP122, + }, + { ++ .compatible = "ti,tmp125", ++ .data = (void *) LM70_CHIP_TMP125, ++ }, ++ { + .compatible = "ti,lm71", + .data = (void *) LM70_CHIP_LM71, + }, +@@ -184,6 +199,7 @@ static const struct spi_device_id lm70_i + { "lm70", LM70_CHIP_LM70 }, + { "tmp121", LM70_CHIP_TMP121 }, + { "tmp122", LM70_CHIP_TMP122 }, ++ { "tmp125", LM70_CHIP_TMP125 }, + { "lm71", LM70_CHIP_LM71 }, + { "lm74", LM70_CHIP_LM74 }, + { }, diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 new file mode 100644 index 0000000000..578b8be764 --- /dev/null +++ b/target/linux/generic/config-5.15 @@ -0,0 +1,7179 @@ +# CONFIG_104_QUAD_8 is not set +CONFIG_32BIT=y +CONFIG_64BIT_TIME=y +# CONFIG_6LOWPAN is not set +# CONFIG_6LOWPAN_DEBUGFS is not set +# CONFIG_6PACK is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_9P_FS is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_AB8500_CORE is not set +# CONFIG_ABP060MG is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_ACENIC is not set +# CONFIG_ACERHDF is not set +# CONFIG_ACER_WIRELESS is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_ACPI_ALS is not set +# CONFIG_ACPI_APEI is not set +# CONFIG_ACPI_BUTTON is not set +# CONFIG_ACPI_CONFIGFS is not set +# CONFIG_ACPI_CUSTOM_METHOD is not set +# CONFIG_ACPI_EXTLOG is not set +# CONFIG_ACPI_HED is not set +# CONFIG_ACPI_NFIT is not set +# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set +# CONFIG_ACPI_TABLE_UPGRADE is not set +# CONFIG_ACPI_VIDEO is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD5064 is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_AD5272 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5593R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5696_I2C is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5933 is not set +# CONFIG_AD7091R5 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD7606_IFACE_PARALLEL is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7746 is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD799X is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9467 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_ADE7854 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADIN_PHY is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADI_AXI_ADC is not set +# CONFIG_ADJD_S311 is not set +# CONFIG_ADM6996_PHY is not set +# CONFIG_ADM8211 is not set +# CONFIG_ADT7316 is not set +# CONFIG_ADUX1020 is not set +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_ADXL345_I2C is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL372_I2C is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +CONFIG_AEABI=y +# CONFIG_AFE4403 is not set +# CONFIG_AFE4404 is not set +# CONFIG_AFFS_FS is not set +# CONFIG_AFS_DEBUG_CURSOR is not set +# CONFIG_AFS_FS is not set +# CONFIG_AF_KCM is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_RXRPC_INJECT_LOSS is not set +# CONFIG_AF_RXRPC_IPV6 is not set +# CONFIG_AGP is not set +# CONFIG_AHCI_CEVA is not set +# CONFIG_AHCI_IMX is not set +# CONFIG_AHCI_MVEBU is not set +# CONFIG_AHCI_QORIQ is not set +# CONFIG_AHCI_XGENE is not set +CONFIG_AIO=y +# CONFIG_AIRO is not set +# CONFIG_AIRO_CS is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_AK09911 is not set +# CONFIG_AK8974 is not set +# CONFIG_AK8975 is not set +# CONFIG_AL3010 is not set +# CONFIG_AL3320A is not set +# CONFIG_ALIM7101_WDT is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_ALTERA_MBOX is not set +# CONFIG_ALTERA_MSGDMA is not set +# CONFIG_ALTERA_STAPL is not set +# CONFIG_ALTERA_TSE is not set +# CONFIG_ALX is not set +# CONFIG_AL_FIC is not set +# CONFIG_AM2315 is not set +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_AMBA_PL08X is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_AMD_MEM_ENCRYPT is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_AMD_XGBE_HAVE_ECC is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_AMILO_RFKILL is not set +# CONFIG_ANDROID is not set +CONFIG_ANON_INODES=y +# CONFIG_APDS9300 is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_APDS9960 is not set +# CONFIG_APM8018X is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_APPLE_GMUX is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_APPLE_PROPERTIES is not set +# CONFIG_APPLICOM is not set +# CONFIG_AQTION is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AR5523 is not set +# CONFIG_AR7 is not set +# CONFIG_AR8216_PHY is not set +# CONFIG_AR8216_PHY_LEDS is not set +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AGILEX is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_ARTPEC is not set +# CONFIG_ARCH_ASPEED is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_AXXIA is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM_21664 is not set +# CONFIG_ARCH_BCM_23550 is not set +# CONFIG_ARCH_BCM_281XX is not set +# CONFIG_ARCH_BCM_5301X is not set +# CONFIG_ARCH_BCM_53573 is not set +# CONFIG_ARCH_BCM_63XX is not set +# CONFIG_ARCH_BCM_CYGNUS is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BCM_NSP is not set +# CONFIG_ARCH_BERLIN is not set +CONFIG_ARCH_BINFMT_ELF_STATE=y +# CONFIG_ARCH_BITMAIN is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_DIGICOLOR is not set +# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_EXYNOS is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_HI3xxx is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MILBEAUT is not set +CONFIG_ARCH_MMAP_RND_BITS=8 +CONFIG_ARCH_MMAP_RND_BITS_MAX=16 +CONFIG_ARCH_MMAP_RND_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_MSTARV7 is not set +# CONFIG_ARCH_MULTIPLATFORM is not set +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_NSPIRE is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +# CONFIG_ARCH_OMAP2PLUS is not set +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_OXNAS is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_RANDOM is not set +# CONFIG_ARCH_RDA is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_S32 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TANGO is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_VULCAN is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_WANTS_THP_SWAP is not set +# CONFIG_ARCH_WM8505 is not set +# CONFIG_ARCH_WM8750 is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQ is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_ARCNET is not set +# CONFIG_ARC_EMAC is not set +# CONFIG_ARC_IRQ_NO_AUTOSAVE is not set +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_AMU_EXTN is not set +# CONFIG_ARM64_BTI is not set +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_ARM64_E0PD is not set +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_ARM64_ERRATUM_1165522 is not set +# CONFIG_ARM64_ERRATUM_1286807 is not set +# CONFIG_ARM64_ERRATUM_1319367 is not set +# CONFIG_ARM64_ERRATUM_1418040 is not set +# CONFIG_ARM64_ERRATUM_1463225 is not set +# CONFIG_ARM64_ERRATUM_1508412 is not set +# CONFIG_ARM64_ERRATUM_1530923 is not set +# CONFIG_ARM64_ERRATUM_1542419 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_834220 is not set +# CONFIG_ARM64_ERRATUM_843419 is not set +# CONFIG_ARM64_ERRATUM_845719 is not set +# CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_LSE_ATOMICS is not set +# CONFIG_ARM64_MODULE_PLTS is not set +# CONFIG_ARM64_MTE is not set +# CONFIG_ARM64_PAN is not set +# CONFIG_ARM64_PMEM is not set +# CONFIG_ARM64_PSEUDO_NMI is not set +# CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_ARM64_RAS_EXTN is not set +# CONFIG_ARM64_RELOC_TEST is not set +CONFIG_ARM64_SW_TTBR0_PAN=y +# CONFIG_ARM64_TLB_RANGE is not set +# CONFIG_ARM64_UAO is not set +# CONFIG_ARM64_USE_LSE_ATOMICS is not set +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VHE is not set +# CONFIG_ARM_APPENDED_DTB is not set +# CONFIG_ARM_ARCH_TIMER is not set +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_CCI is not set +# CONFIG_ARM_CCI400_PMU is not set +# CONFIG_ARM_CCI5xx_PMU is not set +# CONFIG_ARM_CCI_PMU is not set +# CONFIG_ARM_CCN is not set +# CONFIG_ARM_CMN is not set +# CONFIG_ARM_CPUIDLE is not set +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_ARM_CRYPTO is not set +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +# CONFIG_ARM_DSU_PMU is not set +# CONFIG_ARM_ERRATA_326103 is not set +# CONFIG_ARM_ERRATA_364296 is not set +# CONFIG_ARM_ERRATA_411920 is not set +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_ARM_ERRATA_773022 is not set +# CONFIG_ARM_ERRATA_775420 is not set +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_814220 is not set +# CONFIG_ARM_ERRATA_818325_852422 is not set +# CONFIG_ARM_ERRATA_821420 is not set +# CONFIG_ARM_ERRATA_825619 is not set +# CONFIG_ARM_ERRATA_852421 is not set +# CONFIG_ARM_ERRATA_852423 is not set +# CONFIG_ARM_ERRATA_857271 is not set +# CONFIG_ARM_ERRATA_857272 is not set +CONFIG_ARM_GIC_MAX_NR=1 +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_ARM_LPAE is not set +# CONFIG_ARM_MHU is not set +# CONFIG_ARM_MODULE_PLTS is not set +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +# CONFIG_ARM_PSCI is not set +# CONFIG_ARM_PSCI_CHECKER is not set +# CONFIG_ARM_PSCI_CPUIDLE is not set +# CONFIG_ARM_PTDUMP_DEBUGFS is not set +# CONFIG_ARM_SBSA_WATCHDOG is not set +# CONFIG_ARM_SCMI_PROTOCOL is not set +# CONFIG_ARM_SCPI_PROTOCOL is not set +# CONFIG_ARM_SDE_INTERFACE is not set +# CONFIG_ARM_SMCCC_SOC_ID is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_ARM_SPE_PMU is not set +# CONFIG_ARM_THUMBEE is not set +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_ARM_VIRT_EXT is not set +# CONFIG_AS3935 is not set +# CONFIG_AS73211 is not set +# CONFIG_ASM9260_TIMER is not set +# CONFIG_ASN1 is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_ASUS_WIRELESS is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_AT91_SAMA5D2_ADC is not set +# CONFIG_ATA is not set +# CONFIG_ATAGS is not set +CONFIG_ATAGS_PROC=y +# CONFIG_ATALK is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_ATA_ACPI is not set +CONFIG_ATA_BMDMA=y +# CONFIG_ATA_FORCE is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_ATA_LEDS is not set +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_ATA_PIIX is not set +CONFIG_ATA_SFF=y +# CONFIG_ATA_VERBOSE_ERROR is not set +# CONFIG_ATH10K is not set +# CONFIG_ATH25 is not set +# CONFIG_ATH5K is not set +# CONFIG_ATH6KL is not set +# CONFIG_ATH79 is not set +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1C is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL2 is not set +# CONFIG_ATLAS_EZO_SENSOR is not set +# CONFIG_ATLAS_PH_SENSOR is not set +# CONFIG_ATM is not set +# CONFIG_ATMEL is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_ATMEL_SSC is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_BR2684 is not set +CONFIG_ATM_BR2684_IPFILTER=y +# CONFIG_ATM_CLIP is not set +CONFIG_ATM_CLIP_NO_ICMP=y +# CONFIG_ATM_DRIVERS is not set +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_FORE200E is not set +# CONFIG_ATM_HE is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_LANE is not set +# CONFIG_ATM_MPOA is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_SOLOS is not set +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ATP is not set +# CONFIG_AUDIT is not set +# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set +# CONFIG_AURORA_NB8800 is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTO_ZRELADDR is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_AX25 is not set +# CONFIG_AX25_DAMA_SLAVE is not set +# CONFIG_AX88796 is not set +# CONFIG_AX88796B_PHY is not set +# CONFIG_AXP20X_ADC is not set +# CONFIG_AXP20X_POWER is not set +# CONFIG_AXP288_ADC is not set +# CONFIG_AXP288_FUEL_GAUGE is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_B44 is not set +# CONFIG_B53 is not set +# CONFIG_B53_MDIO_DRIVER is not set +# CONFIG_B53_MMAP_DRIVER is not set +# CONFIG_B53_SERDES is not set +# CONFIG_B53_SPI_DRIVER is not set +# CONFIG_B53_SRAB_DRIVER is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_APPLE is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_BACKLIGHT_LED is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_PANDORA is not set +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BACKLIGHT_RPI is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BAREUDP is not set +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 +# CONFIG_BATMAN_ADV is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_BQ27XXX_HDQ is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_GOLDFISH is not set +# CONFIG_BATTERY_LEGO_EV3 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_MAX1721X is not set +# CONFIG_BATTERY_RT5033 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BAYCOM_EPP is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BCACHE is not set +# CONFIG_BCM47XX is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_BCM63XX is not set +# CONFIG_BCM63XX_PHY is not set +# CONFIG_BCM7038_WDT is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM84881_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_BCMA is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMGENET is not set +# CONFIG_BCM_IPROC_ADC is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_BCM_SBA_RAID is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BE2NET is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_BGMAC is not set +# CONFIG_BH1750 is not set +# CONFIG_BH1780 is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_BIG_LITTLE is not set +# CONFIG_BINARY_PRINTF is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_ELF_FDPIC is not set +# CONFIG_BINFMT_FLAT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_SCRIPT=y +CONFIG_BITREVERSE=y +# CONFIG_BLK_CGROUP_IOCOST is not set +# CONFIG_BLK_CGROUP_IOLATENCY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set +# CONFIG_BLK_DEBUG_FS is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_BLK_DEV_4DRIVES is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI14XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_ATIIXP is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_CS5535 is not set +# CONFIG_BLK_DEV_CS5536 is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_DELKIN is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_DTC2278 is not set +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_HT6560B is not set +# CONFIG_BLK_DEV_IDEACPI is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEPNP is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDE_AU1XXX is not set +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_IT8172 is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_PLATFORM is not set +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_BLK_DEV_QD65XX is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set +# CONFIG_BLK_DEV_RZ1000 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_SD is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_BLK_DEV_THROTTLING is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_UMC8672 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_INLINE_ENCRYPTION is not set +# CONFIG_BLK_SED_OPAL is not set +# CONFIG_BLK_WBT is not set +CONFIG_BLOCK=y +# CONFIG_BMA180 is not set +# CONFIG_BMA220 is not set +# CONFIG_BMA400 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_BMC150_MAGN is not set +# CONFIG_BMC150_MAGN_I2C is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BME680 is not set +# CONFIG_BMG160 is not set +# CONFIG_BMI160_I2C is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_BMIPS_GENERIC is not set +# CONFIG_BMP280 is not set +# CONFIG_BNA is not set +# CONFIG_BNX2 is not set +# CONFIG_BNX2X is not set +# CONFIG_BNX2X_SRIOV is not set +# CONFIG_BNXT is not set +# CONFIG_BONDING is not set +# CONFIG_BOOKE_WDT is not set +CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=3 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +# CONFIG_BOOTTIME_TRACING is not set +# CONFIG_BOOT_CONFIG is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BOOT_RAW=y +# CONFIG_BOUNCE is not set +CONFIG_BPF=y +# CONFIG_BPFILTER is not set +CONFIG_BPF_JIT=y +# CONFIG_BPF_JIT_ALWAYS_ON is not set +CONFIG_BPF_JIT_DEFAULT_ON=y +# CONFIG_BPF_PRELOAD is not set +# CONFIG_BPF_STREAM_PARSER is not set +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_UNPRIV_DEFAULT_OFF=y +# CONFIG_BPQETHER is not set +CONFIG_BQL=y +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_BRCMFMAC is not set +# CONFIG_BRCMSMAC is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +CONFIG_BRIDGE=y +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_BROUTE is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +# CONFIG_BRIDGE_EBT_IP is not set +# CONFIG_BRIDGE_EBT_IP6 is not set +# CONFIG_BRIDGE_EBT_LIMIT is not set +# CONFIG_BRIDGE_EBT_LOG is not set +# CONFIG_BRIDGE_EBT_MARK is not set +# CONFIG_BRIDGE_EBT_MARK_T is not set +# CONFIG_BRIDGE_EBT_NFLOG is not set +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +# CONFIG_BRIDGE_EBT_STP is not set +# CONFIG_BRIDGE_EBT_T_FILTER is not set +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_VLAN is not set +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_MRP is not set +# CONFIG_BRIDGE_NETFILTER is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +CONFIG_BRIDGE_VLAN_FILTERING=y +# CONFIG_BROADCOM_PHY is not set +CONFIG_BROKEN_ON_SMP=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_BT is not set +# CONFIG_BTRFS_ASSERT is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_BTRFS_FS_POSIX_ACL is not set +# CONFIG_BTRFS_FS_REF_VERIFY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +# CONFIG_BT_BREDR is not set +# CONFIG_BT_CMTP is not set +# CONFIG_BT_FEATURE_DEBUG is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIBLUECARD is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBT3C is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set +# CONFIG_BT_HCIBTUSB_MTK is not set +# CONFIG_BT_HCIBTUSB_RTL is not set +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_AG6XX is not set +# CONFIG_BT_HCIUART_ATH3K is not set +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_HCIUART_QCA is not set +# CONFIG_BT_HCIUART_RTL is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_HIDP is not set +# CONFIG_BT_HS is not set +# CONFIG_BT_LE is not set +# CONFIG_BT_LEDS is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_MSFTEXT is not set +# CONFIG_BT_MTKSDIO is not set +# CONFIG_BT_MTKUART is not set +# CONFIG_BT_RFCOMM is not set +CONFIG_BT_RFCOMM_TTY=y +# CONFIG_BT_SELFTEST is not set +CONFIG_BUG=y +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_BUILDTIME_TABLE_SORT=y +# CONFIG_BUILD_BIN2C is not set +CONFIG_BUILD_SALT="" +# CONFIG_C2PORT is not set +CONFIG_CACHE_L2X0_PMU=y +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_CAIF is not set +# CONFIG_CAN is not set +# CONFIG_CAN_BCM is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +# CONFIG_CAN_DEV is not set +# CONFIG_CAN_GS_USB is not set +# CONFIG_CAN_GW is not set +# CONFIG_CAN_HI311X is not set +# CONFIG_CAN_IFI_CANFD is not set +# CONFIG_CAN_ISOTP is not set +# CONFIG_CAN_J1939 is not set +# CONFIG_CAN_KVASER_PCIEFD is not set +# CONFIG_CAN_MCBA_USB is not set +# CONFIG_CAN_MCP251XFD is not set +# CONFIG_CAN_M_CAN is not set +# CONFIG_CAN_PEAK_PCIEFD is not set +# CONFIG_CAN_RAW is not set +# CONFIG_CAN_RCAR is not set +# CONFIG_CAN_RCAR_CANFD is not set +# CONFIG_CAN_SLCAN is not set +# CONFIG_CAN_SUN4I is not set +# CONFIG_CAN_UCAN is not set +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_VXCAN is not set +# CONFIG_CAPI_AVM is not set +# CONFIG_CAPI_EICON is not set +# CONFIG_CAPI_TRACE is not set +CONFIG_CARDBUS=y +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_CARL9170 is not set +# CONFIG_CASSINI is not set +# CONFIG_CAVIUM_CPT is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23144 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_CAVIUM_OCTEON_SOC is not set +# CONFIG_CAVIUM_PTP is not set +# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set +# CONFIG_CB710_CORE is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_CCS811 is not set +CONFIG_CC_CAN_LINK=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_CFG80211 is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +# CONFIG_CGROUPS is not set +# CONFIG_CHARGER_ADP5061 is not set +# CONFIG_CHARGER_BD99954 is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ2515X is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_CHARGER_DETECTOR_MAX14656 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_LT3651 is not set +# CONFIG_CHARGER_LTC3651 is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_CHARGER_SBS is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_TWL4030 is not set +# CONFIG_CHARGER_UCS1002 is not set +# CONFIG_CHASH_SELFTEST is not set +# CONFIG_CHASH_STATS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_ACL is not set +CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y +# CONFIG_CIFS_DEBUG is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_FSCACHE is not set +# CONFIG_CIFS_NFSD_EXPORT is not set +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_SMB2 is not set +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_STATS2 is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_XATTR=y +# CONFIG_CIO_DAC is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CLKSRC_VERSATILE is not set +# CONFIG_CLK_HSDK is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_CLOCK_THERMAL is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM3605 is not set +# CONFIG_CM36651 is not set +# CONFIG_CMA is not set +CONFIG_CMDLINE="" +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_CMDLINE_FROM_BOOTLOADER is not set +# CONFIG_CMDLINE_PARTITION is not set +# CONFIG_CNIC is not set +# CONFIG_CODA_FS is not set +# CONFIG_CODE_PATCHING_SELFTEST is not set +# CONFIG_COMEDI is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_COMMON_CLK_FIXED_MMIO is not set +# CONFIG_COMMON_CLK_IPROC is not set +# CONFIG_COMMON_CLK_MAX9485 is not set +# CONFIG_COMMON_CLK_MT6765 is not set +# CONFIG_COMMON_CLK_MT8167 is not set +# CONFIG_COMMON_CLK_MT8167_AUDSYS is not set +# CONFIG_COMMON_CLK_MT8167_IMGSYS is not set +# CONFIG_COMMON_CLK_MT8167_MFGCFG is not set +# CONFIG_COMMON_CLK_MT8167_MMSYS is not set +# CONFIG_COMMON_CLK_MT8167_VDECSYS is not set +# CONFIG_COMMON_CLK_NXP is not set +# CONFIG_COMMON_CLK_PIC32 is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_QCOM is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI5341 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +CONFIG_COMPACTION=y +# CONFIG_COMPAL_LAPTOP is not set +# CONFIG_COMPAT is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_COMPILE_TEST is not set +# CONFIG_CONFIGFS_FS is not set +# CONFIG_CONNECTOR is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_CONSTRUCTORS=y +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_COPS is not set +# CONFIG_CORDIC is not set +# CONFIG_COREDUMP is not set +# CONFIG_CORESIGHT is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_COUNTER is not set +# CONFIG_CPA_DEBUG is not set +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_THERMAL is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND is not set +# CONFIG_CPU_IDLE is not set +# CONFIG_CPU_IDLE_GOV_LADDER is not set +# CONFIG_CPU_IDLE_GOV_MENU is not set +# CONFIG_CPU_IDLE_GOV_TEO is not set +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +# CONFIG_CPU_ISOLATION is not set +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_NO_EFFICIENT_FFS is not set +CONFIG_CPU_SW_DOMAIN_PAN=y +# CONFIG_CPU_THERMAL is not set +# CONFIG_CRAMFS is not set +CONFIG_CRAMFS_BLOCKDEV=y +# CONFIG_CRAMFS_MTD is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_CRC32_BIT is not set +CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_SELFTEST is not set +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SLICEBY8 is not set +# CONFIG_CRC4 is not set +# CONFIG_CRC64 is not set +# CONFIG_CRC7 is not set +# CONFIG_CRC8 is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +CONFIG_CROSS_COMPILE="" +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_ACOMP2=y +# CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AEGIS128L is not set +# CONFIG_CRYPTO_AEGIS128L_AESNI_SSE2 is not set +# CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set +# CONFIG_CRYPTO_AEGIS256 is not set +# CONFIG_CRYPTO_AEGIS256_AESNI_SSE2 is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_586 is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_ARM64 is not set +# CONFIG_CRYPTO_AES_ARM64_BS is not set +# CONFIG_CRYPTO_AES_ARM64_CE is not set +# CONFIG_CRYPTO_AES_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_AES_ARM_BS is not set +# CONFIG_CRYPTO_AES_ARM_CE is not set +# CONFIG_CRYPTO_AES_NI_INTEL is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2S is not set +# CONFIG_CRYPTO_BLAKE2S_X86 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +CONFIG_CRYPTO_CCM=y +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_CHACHA20_X86_64 is not set +# CONFIG_CRYPTO_CHACHA_MIPS is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CRC32C_INTEL is not set +# CONFIG_CRYPTO_CRC32_ARM_CE is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM_CE is not set +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +# CONFIG_CRYPTO_CURVE25519_NEON is not set +# CONFIG_CRYPTO_CURVE25519_X86 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_CRYPTO_DEV_ATMEL_AES is not set +# CONFIG_CRYPTO_DEV_ATMEL_AUTHENC is not set +# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +# CONFIG_CRYPTO_DEV_ATMEL_TDES is not set +# CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_CCP_DEBUGFS is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC is not set +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_HISI_SEC is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set +# CONFIG_CRYPTO_DEV_MARVELL_CESA is not set +# CONFIG_CRYPTO_DEV_MV_CESA is not set +# CONFIG_CRYPTO_DEV_MXC_SCC is not set +# CONFIG_CRYPTO_DEV_MXS_DCP is not set +# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_OCTEONTX_CPT is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set +# CONFIG_CRYPTO_DEV_QAT_C62X is not set +# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set +# CONFIG_CRYPTO_DEV_QCE is not set +# CONFIG_CRYPTO_DEV_S5P is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_CRYPTO_DEV_SP_PSP is not set +# CONFIG_CRYPTO_DEV_TALITOS is not set +# CONFIG_CRYPTO_DEV_VIRTIO is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_GHASH_ARM64_CE is not set +# CONFIG_CRYPTO_GHASH_ARM_CE is not set +# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_KHAZAD is not set +CONFIG_CRYPTO_KPP=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_ARC4=y +# CONFIG_CRYPTO_LIB_BLAKE2S is not set +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +# CONFIG_CRYPTO_LIB_POLY1305 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MCRYPTD is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_MORUS1280 is not set +# CONFIG_CRYPTO_MORUS1280_AVX2 is not set +# CONFIG_CRYPTO_MORUS1280_SSE2 is not set +# CONFIG_CRYPTO_MORUS640 is not set +# CONFIG_CRYPTO_MORUS640_SSE2 is not set +# CONFIG_CRYPTO_NHPOLY1305_NEON is not set +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_PCOMP is not set +# CONFIG_CRYPTO_PCOMP2 is not set +CONFIG_CRYPTO_PCRYPT=y +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_POLY1305_ARM is not set +# CONFIG_CRYPTO_POLY1305_MIPS is not set +# CONFIG_CRYPTO_POLY1305_NEON is not set +# CONFIG_CRYPTO_POLY1305_X86_64 is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_RNG is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SALSA20_586 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA1_ARM64_CE is not set +# CONFIG_CRYPTO_SHA1_ARM_CE is not set +# CONFIG_CRYPTO_SHA1_ARM_NEON is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA256_ARM64 is not set +# CONFIG_CRYPTO_SHA2_ARM64_CE is not set +# CONFIG_CRYPTO_SHA2_ARM_CE is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA3_ARM64 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_SHA512_ARM64 is not set +# CONFIG_CRYPTO_SHA512_ARM64_CE is not set +# CONFIG_CRYPTO_SIMD is not set +CONFIG_CRYPTO_SKCIPHER=y +CONFIG_CRYPTO_SKCIPHER2=y +# CONFIG_CRYPTO_SM2 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM3_ARM64_CE is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_SM4_ARM64_CE is not set +# CONFIG_CRYPTO_SPECK is not set +# CONFIG_CRYPTO_STATS is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_TWOFISH_586 is not set +# CONFIG_CRYPTO_TWOFISH_COMMON is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_XXHASH is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_ZSTD is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_CS89x0 is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set +# CONFIG_CUSE is not set +# CONFIG_CW1200 is not set +# CONFIG_CXD2880_SPI_DRV is not set +# CONFIG_CXL_AFU_DRIVER_OPS is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_EEH is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_LIB is not set +# CONFIG_CYPRESS_FIRMWARE is not set +# CONFIG_DA280 is not set +# CONFIG_DA311 is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DAX is not set +# CONFIG_DCB is not set +# CONFIG_DDR is not set +# CONFIG_DEBUG_ALIGN_RODATA is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_EFI is not set +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_INFO_BTF is not set +# CONFIG_DEBUG_INFO_COMPRESSED is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +CONFIG_DEBUG_INFO_REDUCED=y +# CONFIG_DEBUG_INFO_SPLIT is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_KOBJECT_RELEASE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_LL_UART_8250 is not set +# CONFIG_DEBUG_LL_UART_PL01X is not set +# CONFIG_DEBUG_LOCKDEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_MISC is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_RSEQ is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_SEMIHOSTING is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_DEBUG_UART_8250_PALMCHIP is not set +# CONFIG_DEBUG_UART_8250_WORD is not set +# CONFIG_DEBUG_UART_BCM63XX is not set +# CONFIG_DEBUG_UART_FLOW_CONTROL is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_PGTABLE is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_WX is not set +# CONFIG_DEBUG_ZBOOT is not set +# CONFIG_DECNET is not set +# CONFIG_DEFAULT_CODEL is not set +CONFIG_DEFAULT_CUBIC=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_FQ is not set +CONFIG_DEFAULT_FQ_CODEL=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DEFAULT_INIT="" +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_DEFAULT_NET_SCH="fq_codel" +# CONFIG_DEFAULT_NOOP is not set +# CONFIG_DEFAULT_PFIFO_FAST is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_SECURITY="" +CONFIG_DEFAULT_SECURITY_DAC=y +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SFQ is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +# CONFIG_DELL_LAPTOP is not set +# CONFIG_DELL_RBTN is not set +# CONFIG_DELL_SMBIOS is not set +# CONFIG_DELL_SMO8800 is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_DEVKMEM is not set +# CONFIG_DEVMEM is not set +CONFIG_DEVPORT=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_DEVTMPFS is not set +# CONFIG_DEVTMPFS_MOUNT is not set +# CONFIG_DEV_DAX is not set +# CONFIG_DGAP is not set +# CONFIG_DGNC is not set +# CONFIG_DHT11 is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_DISPLAY_CONNECTOR_ANALOG_TV is not set +# CONFIG_DISPLAY_CONNECTOR_DVI is not set +# CONFIG_DISPLAY_CONNECTOR_HDMI is not set +# CONFIG_DISPLAY_ENCODER_TFP410 is not set +# CONFIG_DISPLAY_ENCODER_TPD12S015 is not set +# CONFIG_DISPLAY_PANEL_DPI is not set +# CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DL2K is not set +# CONFIG_DLHL60D is not set +# CONFIG_DLM is not set +# CONFIG_DM9000 is not set +# CONFIG_DMABUF_HEAPS is not set +# CONFIG_DMABUF_MOVE_NOTIFY is not set +# CONFIG_DMABUF_SELFTESTS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMARD06 is not set +# CONFIG_DMARD09 is not set +# CONFIG_DMARD10 is not set +# CONFIG_DMASCC is not set +# CONFIG_DMATEST is not set +# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_COHERENT_POOL=y +CONFIG_DMA_DECLARE_COHERENT=y +# CONFIG_DMA_ENGINE is not set +# CONFIG_DMA_FENCE_TRACE is not set +# CONFIG_DMA_JZ4780 is not set +CONFIG_DMA_NONCOHERENT_MMAP=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_PERNUMA_CMA is not set +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_CLONE is not set +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_DUST is not set +# CONFIG_DM_EBS is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_INTEGRITY is not set +# CONFIG_DM_LOG_USERSPACE is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_DM_MQ_DEFAULT is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_DM_UNSTRIPED is not set +# CONFIG_DM_VERITY is not set +# CONFIG_DM_WRITECACHE is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DNET is not set +# CONFIG_DNOTIFY is not set +# CONFIG_DNS_RESOLVER is not set +CONFIG_DOUBLEFAULT=y +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83869_PHY is not set +# CONFIG_DP83TC811_PHY is not set +# CONFIG_DPOT_DAC is not set +# CONFIG_DPS310 is not set +CONFIG_DQL=y +# CONFIG_DRAGONRISE_FF is not set +# CONFIG_DRM is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_AMDGPU_CIK is not set +# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set +# CONFIG_DRM_AMDGPU_SI is not set +# CONFIG_DRM_AMDGPU_USERPTR is not set +# CONFIG_DRM_AMD_ACP is not set +# CONFIG_DRM_AMD_DC_DCN2_0 is not set +# CONFIG_DRM_AMD_DC_DCN3_0 is not set +# CONFIG_DRM_AMD_DC_HDCP is not set +# CONFIG_DRM_AMD_DC_SI is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_ARMADA is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MM is not set +# CONFIG_DRM_DEBUG_SELFTEST is not set +# CONFIG_DRM_DISPLAY_CONNECTOR is not set +# CONFIG_DRM_DP_AUX_CHARDEV is not set +# CONFIG_DRM_DP_CEC is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_DW_HDMI_CEC is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_FBDEV_EMULATION is not set +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +# CONFIG_DRM_FSL_DCU is not set +# CONFIG_DRM_GM12U320 is not set +# CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_NXP_TDA9950 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I915 is not set +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_LEGACY is not set +# CONFIG_DRM_LIB_RANDOM is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LVDS_CODEC is not set +# CONFIG_DRM_LVDS_ENCODER is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_MCDE is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_MXSFB is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_OMAP is not set +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set +# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set +# CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set +# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829 is not set +# CONFIG_DRM_PANEL_LG_LB035Q02 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set +# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set +# CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_ROCKTECH_JH057N00900 is not set +# CONFIG_DRM_PANEL_RONBO_RB070D30 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set +# CONFIG_DRM_PANEL_SIMPLE is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SONY_ACX424AKP is not set +# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_RADEON_USERPTR is not set +# CONFIG_DRM_RCAR_DW_HDMI is not set +# CONFIG_DRM_RCAR_LVDS is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SII9234 is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_STI is not set +# CONFIG_DRM_STM is not set +# CONFIG_DRM_SUN4I is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_TINYDRM is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_TOSHIBA_TC358762 is not set +# CONFIG_DRM_TOSHIBA_TC358764 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TVE200 is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_VBOXVIDEO is not set +# CONFIG_DRM_VC4_HDMI_CEC is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VIRTIO_GPU is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_DRM_VMWGFX is not set +# CONFIG_DRM_XEN is not set +# CONFIG_DS1682 is not set +# CONFIG_DS1803 is not set +# CONFIG_DS4424 is not set +# CONFIG_DST_CACHE is not set +# CONFIG_DTLK is not set +# CONFIG_DUMMY is not set +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +# CONFIG_DUMMY_IRQ is not set +# CONFIG_DVB_A8293 is not set +# CONFIG_DVB_AF9013 is not set +# CONFIG_DVB_AF9033 is not set +# CONFIG_DVB_AS102 is not set +# CONFIG_DVB_ASCOT2E is not set +# CONFIG_DVB_ATBM8830 is not set +# CONFIG_DVB_AU8522_DTV is not set +# CONFIG_DVB_AU8522_V4L is not set +# CONFIG_DVB_B2C2_FLEXCOP_USB is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DVB_CX22700 is not set +# CONFIG_DVB_CX22702 is not set +# CONFIG_DVB_CX24110 is not set +# CONFIG_DVB_CX24116 is not set +# CONFIG_DVB_CX24117 is not set +# CONFIG_DVB_CX24120 is not set +# CONFIG_DVB_CX24123 is not set +# CONFIG_DVB_CXD2099 is not set +# CONFIG_DVB_CXD2820R is not set +# CONFIG_DVB_CXD2841ER is not set +# CONFIG_DVB_CXD2880 is not set +# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set +# CONFIG_DVB_DIB3000MB is not set +# CONFIG_DVB_DIB3000MC is not set +# CONFIG_DVB_DIB7000M is not set +# CONFIG_DVB_DIB7000P is not set +# CONFIG_DVB_DIB8000 is not set +# CONFIG_DVB_DIB9000 is not set +# CONFIG_DVB_DRX39XYJ is not set +# CONFIG_DVB_DRXD is not set +# CONFIG_DVB_DRXK is not set +# CONFIG_DVB_DS3000 is not set +# CONFIG_DVB_DUMMY_FE is not set +# CONFIG_DVB_DYNAMIC_MINORS is not set +# CONFIG_DVB_EC100 is not set +# CONFIG_DVB_FIREDTV is not set +# CONFIG_DVB_HELENE is not set +# CONFIG_DVB_HORUS3A is not set +# CONFIG_DVB_ISL6405 is not set +# CONFIG_DVB_ISL6421 is not set +# CONFIG_DVB_ISL6423 is not set +# CONFIG_DVB_IX2505V is not set +# CONFIG_DVB_L64781 is not set +# CONFIG_DVB_LG2160 is not set +# CONFIG_DVB_LGDT3305 is not set +# CONFIG_DVB_LGDT3306A is not set +# CONFIG_DVB_LGDT330X is not set +# CONFIG_DVB_LGS8GL5 is not set +# CONFIG_DVB_LGS8GXX is not set +# CONFIG_DVB_LNBH25 is not set +# CONFIG_DVB_LNBH29 is not set +# CONFIG_DVB_LNBP21 is not set +# CONFIG_DVB_LNBP22 is not set +# CONFIG_DVB_M88DS3103 is not set +# CONFIG_DVB_M88RS2000 is not set +CONFIG_DVB_MAX_ADAPTERS=16 +# CONFIG_DVB_MB86A16 is not set +# CONFIG_DVB_MB86A20S is not set +# CONFIG_DVB_MMAP is not set +# CONFIG_DVB_MN88443X is not set +# CONFIG_DVB_MN88472 is not set +# CONFIG_DVB_MN88473 is not set +# CONFIG_DVB_MT312 is not set +# CONFIG_DVB_MT352 is not set +# CONFIG_DVB_MXL5XX is not set +# CONFIG_DVB_NET is not set +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_NXT6000 is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_PLATFORM_DRIVERS is not set +# CONFIG_DVB_PLL is not set +# CONFIG_DVB_RTL2830 is not set +# CONFIG_DVB_RTL2832 is not set +# CONFIG_DVB_RTL2832_SDR is not set +# CONFIG_DVB_S5H1409 is not set +# CONFIG_DVB_S5H1411 is not set +# CONFIG_DVB_S5H1420 is not set +# CONFIG_DVB_S5H1432 is not set +# CONFIG_DVB_S921 is not set +# CONFIG_DVB_SI2165 is not set +# CONFIG_DVB_SI2168 is not set +# CONFIG_DVB_SI21XX is not set +# CONFIG_DVB_SP2 is not set +# CONFIG_DVB_SP8870 is not set +# CONFIG_DVB_SP887X is not set +# CONFIG_DVB_STB0899 is not set +# CONFIG_DVB_STB6000 is not set +# CONFIG_DVB_STB6100 is not set +# CONFIG_DVB_STV0288 is not set +# CONFIG_DVB_STV0297 is not set +# CONFIG_DVB_STV0299 is not set +# CONFIG_DVB_STV0367 is not set +# CONFIG_DVB_STV0900 is not set +# CONFIG_DVB_STV090x is not set +# CONFIG_DVB_STV0910 is not set +# CONFIG_DVB_STV6110 is not set +# CONFIG_DVB_STV6110x is not set +# CONFIG_DVB_STV6111 is not set +# CONFIG_DVB_TC90522 is not set +# CONFIG_DVB_TDA10021 is not set +# CONFIG_DVB_TDA10023 is not set +# CONFIG_DVB_TDA10048 is not set +# CONFIG_DVB_TDA1004X is not set +# CONFIG_DVB_TDA10071 is not set +# CONFIG_DVB_TDA10086 is not set +# CONFIG_DVB_TDA18271C2DD is not set +# CONFIG_DVB_TDA665x is not set +# CONFIG_DVB_TDA8083 is not set +# CONFIG_DVB_TDA8261 is not set +# CONFIG_DVB_TDA826X is not set +# CONFIG_DVB_TEST_DRIVERS is not set +# CONFIG_DVB_TS2020 is not set +# CONFIG_DVB_TTUSB_BUDGET is not set +# CONFIG_DVB_TTUSB_DEC is not set +# CONFIG_DVB_TUA6100 is not set +# CONFIG_DVB_TUNER_CX24113 is not set +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set +# CONFIG_DVB_TUNER_ITD1000 is not set +# CONFIG_DVB_ULE_DEBUG is not set +# CONFIG_DVB_USB_V2 is not set +# CONFIG_DVB_VES1820 is not set +# CONFIG_DVB_VES1X93 is not set +# CONFIG_DVB_ZD1301_DEMOD is not set +# CONFIG_DVB_ZL10036 is not set +# CONFIG_DVB_ZL10039 is not set +# CONFIG_DVB_ZL10353 is not set +# CONFIG_DWC_XLGMAC is not set +# CONFIG_DWMAC_DWC_QOS_ETH is not set +# CONFIG_DWMAC_INTEL_PLAT is not set +# CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_LPC18XX is not set +# CONFIG_DWMAC_MESON is not set +# CONFIG_DWMAC_ROCKCHIP is not set +# CONFIG_DWMAC_SOCFPGA is not set +# CONFIG_DWMAC_STI is not set +# CONFIG_DW_AXI_DMAC is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_DW_EDMA is not set +# CONFIG_DW_EDMA_PCIE is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_DYNAMIC_DEBUG is not set +CONFIG_DYNAMIC_DEBUG_CORE=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_E1000E_HWTS is not set +# CONFIG_EARLY_PRINTK_8250 is not set +# CONFIG_EARLY_PRINTK_USB_XDBC is not set +# CONFIG_EBC_C384_WDT is not set +# CONFIG_ECHO is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_EDAC is not set +# CONFIG_EEEPC_LAPTOP is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_DIGSY_MTC_CFG is not set +# CONFIG_EEPROM_EE1004 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EFI is not set +CONFIG_EFI_PARTITION=y +# CONFIG_EFI_VARS_PSTORE is not set +# CONFIG_EFS_FS is not set +CONFIG_ELFCORE=y +# CONFIG_ELF_CORE is not set +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_EMBEDDED=y +# CONFIG_EM_TIMER_STI is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENA_ETHERNET is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_ENERGY_MODEL is not set +# CONFIG_ENIC is not set +# CONFIG_ENVELOPE_DETECTOR is not set +# CONFIG_EPAPR_PARAVIRT is not set +# CONFIG_EPIC100 is not set +CONFIG_EPOLL=y +# CONFIG_EQUALIZER is not set +# CONFIG_EROFS_FS is not set +# CONFIG_ET131X is not set +CONFIG_ETHERNET=y +# CONFIG_ETHOC is not set +CONFIG_ETHTOOL_NETLINK=y +CONFIG_EVENTFD=y +# CONFIG_EVM is not set +# CONFIG_EXFAT_FS is not set +CONFIG_EXPERT=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +# CONFIG_EXT2_FS is not set +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_FS is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXTCON is not set +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_ARIZONA is not set +# CONFIG_EXTCON_AXP288 is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_INTEL_INT3496 is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_QCOM_SPMI_MISC is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_EXTRA_FIRMWARE="" +CONFIG_EXTRA_TARGETS="" +# CONFIG_EXYNOS_ADC is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_F2FS_FAULT_INJECTION is not set +# CONFIG_F2FS_FS is not set +# CONFIG_F2FS_FS_COMPRESSION is not set +# CONFIG_F2FS_FS_ENCRYPTION is not set +# CONFIG_F2FS_FS_POSIX_ACL is not set +# CONFIG_F2FS_FS_SECURITY is not set +CONFIG_F2FS_FS_XATTR=y +# CONFIG_F2FS_IO_TRACE is not set +CONFIG_F2FS_STAT_FS=y +# CONFIG_FAILOVER is not set +# CONFIG_FAIR_GROUP_SCHED is not set +# CONFIG_FANOTIFY is not set +# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_FAT_FS is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FB is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_BIG_ENDIAN is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_BOTH_ENDIAN is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_DA8XX is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_FLEX is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_FSL_DIU is not set +# CONFIG_FB_GEODE is not set +# CONFIG_FB_GOLDFISH is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_IMX is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_LE80578 is not set +# CONFIG_FB_LITTLE_ENDIAN is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_MXS is not set +# CONFIG_FB_N411 is not set +# CONFIG_FB_NEOMAGIC is not set +CONFIG_FB_NOTIFY=y +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_OF is not set +# CONFIG_FB_OMAP2 is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_PS3 is not set +# CONFIG_FB_PXA is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_SM712 is not set +# CONFIG_FB_SM750 is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_TFT is not set +# CONFIG_FB_TFT_AGM1264K_FL is not set +# CONFIG_FB_TFT_BD663474 is not set +# CONFIG_FB_TFT_FBTFT_DEVICE is not set +# CONFIG_FB_TFT_HX8340BN is not set +# CONFIG_FB_TFT_HX8347D is not set +# CONFIG_FB_TFT_HX8353D is not set +# CONFIG_FB_TFT_HX8357D is not set +# CONFIG_FB_TFT_ILI9163 is not set +# CONFIG_FB_TFT_ILI9320 is not set +# CONFIG_FB_TFT_ILI9325 is not set +# CONFIG_FB_TFT_ILI9340 is not set +# CONFIG_FB_TFT_ILI9341 is not set +# CONFIG_FB_TFT_ILI9481 is not set +# CONFIG_FB_TFT_ILI9486 is not set +# CONFIG_FB_TFT_PCD8544 is not set +# CONFIG_FB_TFT_RA8875 is not set +# CONFIG_FB_TFT_S6D02A1 is not set +# CONFIG_FB_TFT_S6D1121 is not set +# CONFIG_FB_TFT_SEPS525 is not set +# CONFIG_FB_TFT_SH1106 is not set +# CONFIG_FB_TFT_SSD1289 is not set +# CONFIG_FB_TFT_SSD1305 is not set +# CONFIG_FB_TFT_SSD1306 is not set +# CONFIG_FB_TFT_SSD1325 is not set +# CONFIG_FB_TFT_SSD1331 is not set +# CONFIG_FB_TFT_SSD1351 is not set +# CONFIG_FB_TFT_ST7735R is not set +# CONFIG_FB_TFT_ST7789V is not set +# CONFIG_FB_TFT_TINYLCD is not set +# CONFIG_FB_TFT_TLS8204 is not set +# CONFIG_FB_TFT_UC1611 is not set +# CONFIG_FB_TFT_UC1701 is not set +# CONFIG_FB_TFT_UPD161704 is not set +# CONFIG_FB_TFT_WATTEROTT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_VIA is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_XGI is not set +# CONFIG_FCOE is not set +# CONFIG_FCOE_FNIC is not set +# CONFIG_FDDI is not set +# CONFIG_FEALNX is not set +# CONFIG_FENCE_TRACE is not set +# CONFIG_FHANDLE is not set +CONFIG_FIB_RULES=y +# CONFIG_FIELDBUS_DEV is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FIT_PARTITION is not set +# CONFIG_FIXED_PHY is not set +CONFIG_FLATMEM=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_FM10K is not set +# CONFIG_FMC is not set +# CONFIG_FONTS is not set +# CONFIG_FONT_6x8 is not set +# CONFIG_FONT_TER16x32 is not set +# CONFIG_FORCEDETH is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_FORTIFY_SOURCE=y +# CONFIG_FPGA is not set +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set +# CONFIG_FRAME_POINTER is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_FREEZER is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_FSCACHE is not set +# CONFIG_FSI is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_FSL_ENETC is not set +# CONFIG_FSL_ENETC_MDIO is not set +# CONFIG_FSL_ENETC_VF is not set +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_FSL_MC_BUS is not set +# CONFIG_FSL_PQ_MDIO is not set +# CONFIG_FSL_QDMA is not set +# CONFIG_FSL_RCPM is not set +# CONFIG_FSL_XGMAC_MDIO is not set +CONFIG_FSNOTIFY=y +# CONFIG_FS_DAX is not set +# CONFIG_FS_ENCRYPTION is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_FS_VERITY is not set +# CONFIG_FTGMAC100 is not set +# CONFIG_FTL is not set +# CONFIG_FTMAC100 is not set +# CONFIG_FTRACE is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_FTR_FIXUP_SELFTEST is not set +# CONFIG_FTWDT010_WATCHDOG is not set +# CONFIG_FUJITSU_ERRATUM_010001 is not set +# CONFIG_FUJITSU_ES is not set +# CONFIG_FUJITSU_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_FUSE_FS is not set +# CONFIG_FUSION is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set +# CONFIG_FUSION_SPI is not set +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +# CONFIG_FW_CFG_SYSFS is not set +CONFIG_FW_LOADER=y +# CONFIG_FW_LOADER_COMPRESS is not set +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FXAS21002C is not set +# CONFIG_FXOS8700_I2C is not set +# CONFIG_FXOS8700_SPI is not set +CONFIG_GACT_PROB=y +# CONFIG_GADGET_UAC1 is not set +# CONFIG_GAMEPORT is not set +# CONFIG_GATEWORKS_GW16083 is not set +# CONFIG_GCC_PLUGINS is not set +# CONFIG_GCOV is not set +# CONFIG_GCOV_KERNEL is not set +# CONFIG_GDB_SCRIPTS is not set +# CONFIG_GEMINI_ETHERNET is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_GENERIC_ADC_THERMAL is not set +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_HWEIGHT=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_GENERIC_IRQ_IPI=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_NET_UTILS=y +# CONFIG_GENERIC_PHY is not set +CONFIG_GENERIC_PTDUMP=y +CONFIG_GENERIC_VDSO_TIME_NS=y +# CONFIG_GENEVE is not set +# CONFIG_GENWQE is not set +# CONFIG_GFS2_FS is not set +# CONFIG_GIGASET_CAPI is not set +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_DUMMYLL is not set +# CONFIG_GLOB_SELFTEST is not set +# CONFIG_GNSS is not set +# CONFIG_GOLDFISH is not set +# CONFIG_GOOGLE_FIRMWARE is not set +# CONFIG_GP2AP002 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_GPD_POCKET_FAN is not set +# CONFIG_GPIOLIB is not set +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +# CONFIG_GPIO_104_DIO_48E is not set +# CONFIG_GPIO_104_IDIO_16 is not set +# CONFIG_GPIO_104_IDI_48 is not set +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_AGGREGATOR is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_AMDPT is not set +# CONFIG_GPIO_AMD_FCH is not set +# CONFIG_GPIO_BCM_KONA is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_CADENCE is not set +# CONFIG_GPIO_CASCADE is not set +# CONFIG_GPIO_CDEV is not set +# CONFIG_GPIO_CDEV_V1 is not set +# CONFIG_GPIO_CS5535 is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_EXAR is not set +# CONFIG_GPIO_F7188X is not set +# CONFIG_GPIO_FTGPIO010 is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GPIO_MM is not set +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_GW_PLD is not set +# CONFIG_GPIO_HLWD is not set +# CONFIG_GPIO_ICH is not set +# CONFIG_GPIO_IT87 is not set +# CONFIG_GPIO_LOGICVC is not set +# CONFIG_GPIO_LYNXPOINT is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_MPC8XXX is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCA9570 is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_PCH is not set +# CONFIG_GPIO_PCIE_IDIO_24 is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_RDC321X is not set +# CONFIG_GPIO_SAMA5D2_PIOBU is not set +# CONFIG_GPIO_SCH is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SIFIVE is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_SYSCON is not set +CONFIG_GPIO_SYSFS=y +# CONFIG_GPIO_TPIC2810 is not set +# CONFIG_GPIO_TS4900 is not set +# CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_GPIO_WINBOND is not set +# CONFIG_GPIO_WS16C48 is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_XRA1403 is not set +# CONFIG_GPIO_ZEVIO is not set +# CONFIG_GPIO_ZX is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_GREYBUS is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_GTP is not set +# CONFIG_GUP_BENCHMARK is not set +# CONFIG_GVE is not set +# CONFIG_HABANA_AI is not set +# CONFIG_HAMACHI is not set +# CONFIG_HAMRADIO is not set +# CONFIG_HAPPYMEAL is not set +CONFIG_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY_FALLBACK is not set +# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set +CONFIG_HARDEN_EL2_VECTORS=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +# CONFIG_HCALL_STATS is not set +# CONFIG_HDC100X is not set +# CONFIG_HDC2010 is not set +# CONFIG_HDLC is not set +# CONFIG_HDLC_CISCO is not set +# CONFIG_HDLC_FR is not set +# CONFIG_HDLC_PPP is not set +# CONFIG_HDLC_RAW is not set +# CONFIG_HDLC_RAW_ETH is not set +# CONFIG_HDMI_LPE_AUDIO is not set +# CONFIG_HDQ_MASTER_OMAP is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_HEADERS_INSTALL is not set +# CONFIG_HEADER_TEST is not set +# CONFIG_HERMES is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_HFSPLUS_FS_POSIX_ACL is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFS_FS_POSIX_ACL is not set +# CONFIG_HI8435 is not set +# CONFIG_HIBERNATION is not set +# CONFIG_HID is not set +# CONFIG_HIDRAW is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACCUTOUCH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_ACRUX_FF is not set +# CONFIG_HID_ALPS is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_ASUS is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_BIGBEN_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CREATIVE_SB0540 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_ELAN is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GENERIC is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_GLORIOUS is not set +# CONFIG_HID_GOOGLE_HAMMER is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LED is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_LOGITECH_DJ is not set +# CONFIG_HID_LOGITECH_HIDPP is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_MCP2221 is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTI is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PID is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_RETRODE is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_U2FZERO is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_VIVALDI is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HIGHMEM is not set +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_HINIC is not set +# CONFIG_HIP04_ETH is not set +# CONFIG_HIPPI is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_HISI_DMA is not set +# CONFIG_HISI_FEMAC is not set +# CONFIG_HISI_HIKEY_USB is not set +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HMC425 is not set +# CONFIG_HMC6352 is not set +# CONFIG_HNS is not set +# CONFIG_HNS3 is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HOSTAP is not set +# CONFIG_HOSTAP_CS is not set +# CONFIG_HOSTAP_PCI is not set +# CONFIG_HOSTAP_PLX is not set +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_HP03 is not set +# CONFIG_HP100 is not set +# CONFIG_HP206C is not set +CONFIG_HPET_MMAP_DEFAULT=y +# CONFIG_HPFS_FS is not set +# CONFIG_HP_ILO is not set +# CONFIG_HP_WIRELESS is not set +# CONFIG_HSA_AMD is not set +# CONFIG_HSI is not set +# CONFIG_HSR is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTS221 is not set +# CONFIG_HTU21 is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_HVC_DCC is not set +# CONFIG_HVC_UDBG is not set +# CONFIG_HWLAT_TRACER is not set +# CONFIG_HWMON is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON_VID is not set +# CONFIG_HWSPINLOCK is not set +# CONFIG_HWSPINLOCK_OMAP is not set +CONFIG_HW_PERF_EVENTS=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_BA431 is not set +# CONFIG_HW_RANDOM_CAVIUM is not set +# CONFIG_HW_RANDOM_CCTRNG is not set +# CONFIG_HW_RANDOM_EXYNOS is not set +# CONFIG_HW_RANDOM_GEODE is not set +# CONFIG_HW_RANDOM_INTEL is not set +# CONFIG_HW_RANDOM_IPROC_RNG200 is not set +# CONFIG_HW_RANDOM_MTK is not set +# CONFIG_HW_RANDOM_OMAP is not set +# CONFIG_HW_RANDOM_OMAP3_ROM is not set +# CONFIG_HW_RANDOM_PPC4XX is not set +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_TPM=y +# CONFIG_HW_RANDOM_VIA is not set +# CONFIG_HW_RANDOM_VIRTIO is not set +# CONFIG_HW_RANDOM_XIPHERA is not set +# CONFIG_HX711 is not set +# CONFIG_HYPERV is not set +# CONFIG_HYPERV_TSCPAGE is not set +# CONFIG_HYSDN is not set +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_200 is not set +# CONFIG_HZ_24 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_48 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_PERIODIC is not set +# CONFIG_I2C is not set +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCA is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_AU1550 is not set +# CONFIG_I2C_BCM2835 is not set +# CONFIG_I2C_BCM_IPROC is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_COMPAT is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEMUX_PINCTRL is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_SLAVE is not set +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_EG20T is not set +# CONFIG_I2C_ELEKTOR is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_HID is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_IBM_IIC is not set +# CONFIG_I2C_IMG is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_ISMT is not set +# CONFIG_I2C_JZ4780 is not set +# CONFIG_I2C_MLXCPLD is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_MT65XX is not set +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +# CONFIG_I2C_MV64XXX is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_NVIDIA_GPU is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_OCTEON is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PCA_ISA is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_PXA_SLAVE is not set +# CONFIG_I2C_RCAR is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_S3C2410 is not set +# CONFIG_I2C_SCMI is not set +# CONFIG_I2C_SH_MOBILE is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_SLAVE_EEPROM is not set +# CONFIG_I2C_SMBUS is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_THUNDERX is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VERSATILE is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I3C is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_IAQCORE is not set +# CONFIG_IBM_ASM is not set +# CONFIG_IBM_EMAC_DEBUG is not set +# CONFIG_IBM_EMAC_EMAC4 is not set +# CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_EMAC_MAL_COMMON_ERR is not set +# CONFIG_IBM_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_EMAC_RGMII is not set +# CONFIG_IBM_EMAC_TAH is not set +# CONFIG_IBM_EMAC_ZMII is not set +# CONFIG_ICE is not set +# CONFIG_ICP10100 is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_ICS932S401 is not set +# CONFIG_IDE is not set +# CONFIG_IDEAPAD_LAPTOP is not set +# CONFIG_IDE_GD is not set +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +# CONFIG_IEEE802154 is not set +# CONFIG_IEEE802154_ADF7242 is not set +# CONFIG_IEEE802154_ATUSB is not set +# CONFIG_IEEE802154_CA8210 is not set +# CONFIG_IEEE802154_HWSIM is not set +# CONFIG_IEEE802154_MCR20A is not set +# CONFIG_IFB is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IGC is not set +# CONFIG_IIO is not set +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_BUFFER_CB is not set +# CONFIG_IIO_BUFFER_DMA is not set +# CONFIG_IIO_BUFFER_DMAENGINE is not set +# CONFIG_IIO_BUFFER_HDC2010 is not set +# CONFIG_IIO_BUFFER_HW_CONSUMER is not set +# CONFIG_IIO_CONFIGFS is not set +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +# CONFIG_IIO_CROS_EC_ACCEL_LEGACY is not set +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +# CONFIG_IIO_MUX is not set +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_RESCALE is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_IIO_SW_DEVICE is not set +# CONFIG_IIO_SW_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_TRIGGER is not set +# CONFIG_IIO_TRIGGERED_EVENT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_IKCONFIG_PROC is not set +# CONFIG_IKHEADERS is not set +# CONFIG_IMA is not set +# CONFIG_IMAGE_CMDLINE_HACK is not set +# CONFIG_IMGPDC_WDT is not set +# CONFIG_IMG_MDC_DMA is not set +# CONFIG_IMX7D_ADC is not set +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_IMX_THERMAL is not set +# CONFIG_INA2XX_ADC is not set +# CONFIG_INDIRECT_PIO is not set +CONFIG_INET=y +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_ESPINTCP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_DIAG is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_ESPINTCP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_TCP_DIAG is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INFINIBAND is not set +# CONFIG_INFTL is not set +# CONFIG_INGENIC_ADC is not set +# CONFIG_INGENIC_CGU_JZ4725B is not set +# CONFIG_INGENIC_CGU_JZ4740 is not set +# CONFIG_INGENIC_CGU_JZ4770 is not set +# CONFIG_INGENIC_CGU_JZ4780 is not set +# CONFIG_INGENIC_CGU_X1000 is not set +# CONFIG_INGENIC_CGU_X1830 is not set +# CONFIG_INGENIC_OST is not set +# CONFIG_INGENIC_SYSOST is not set +# CONFIG_INGENIC_TCU_CLK is not set +# CONFIG_INGENIC_TCU_IRQ is not set +# CONFIG_INGENIC_TIMER is not set +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_INIT_STACK_NONE=y +CONFIG_INOTIFY_USER=y +# CONFIG_INPUT is not set +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_APANEL is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_ATLAS_BTNS is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_AXP20X_PEK is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_DECODER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_GPIO_VIBRA is not set +# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_LEDS is not set +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MAX8997_HAPTIC is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_MSM_VIBRATOR is not set +# CONFIG_INPUT_PALMAS_PWRBUTTON is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PCSPKR is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_TPS65218_PWRBUTTON is not set +# CONFIG_INPUT_TWL4030_PWRBUTTON is not set +# CONFIG_INPUT_TWL4030_VIBRA is not set +# CONFIG_INPUT_TWL6040_VIBRA is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_WISTRON_BTNS is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INT340X_THERMAL is not set +# CONFIG_INTEGRITY is not set +# CONFIG_INTEGRITY_AUDIT is not set +# CONFIG_INTEGRITY_SIGNATURE is not set +# CONFIG_INTEL_ATOMISP2_LED is not set +# CONFIG_INTEL_ATOMISP2_PM is not set +# CONFIG_INTEL_CHT_INT33FE is not set +# CONFIG_INTEL_HID_EVENT is not set +# CONFIG_INTEL_IDLE is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_INTEL_INT0002_VGPIO is not set +# CONFIG_INTEL_IOATDMA is not set +# CONFIG_INTEL_ISH_HID is not set +# CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set +# CONFIG_INTEL_MEI_TXE is not set +# CONFIG_INTEL_MIC_CARD is not set +# CONFIG_INTEL_MIC_HOST is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_INTEL_OAKTRAIL is not set +# CONFIG_INTEL_PMC_CORE is not set +# CONFIG_INTEL_PUNIT_IPC is not set +# CONFIG_INTEL_RST is not set +# CONFIG_INTEL_SMARTCONNECT is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set +# CONFIG_INTEL_SOC_PMIC_CHTWC is not set +# CONFIG_INTEL_TH is not set +# CONFIG_INTEL_VBTN is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_INTERCONNECT is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_INV_ICM42600_I2C is not set +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_MPU6050_I2C is not set +# CONFIG_INV_MPU6050_IIO is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_IONIC is not set +# CONFIG_IOSCHED_BFQ is not set +CONFIG_IO_STRICT_DEVMEM=y +# CONFIG_IO_URING is not set +CONFIG_IO_WQ=y +# CONFIG_IP17XX_PHY is not set +# CONFIG_IP6_NF_FILTER is not set +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_IP6_NF_MANGLE is not set +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_MATCH_SRH is not set +# CONFIG_IP6_NF_NAT is not set +# CONFIG_IP6_NF_RAW is not set +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_IP6_NF_TARGET_HL is not set +# CONFIG_IP6_NF_TARGET_MASQUERADE is not set +# CONFIG_IP6_NF_TARGET_REJECT is not set +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_IPC_NS is not set +# CONFIG_IPMB_DEVICE_INTERFACE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_IPV6 is not set +# CONFIG_IPV6_FOU is not set +# CONFIG_IPV6_FOU_TUNNEL is not set +# CONFIG_IPV6_ILA is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_ROUTE_INFO is not set +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_SIT_6RD is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_VTI is not set +# CONFIG_IPVLAN is not set +# CONFIG_IPVTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2200 is not set +# CONFIG_IPW2200_DEBUG is not set +CONFIG_IPW2200_MONITOR=y +# CONFIG_IPW2200_PROMISCUOUS is not set +# CONFIG_IPW2200_QOS is not set +# CONFIG_IPW2200_RADIOTAP is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_IPX is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_DCCP is not set +# CONFIG_IP_FIB_TRIE_STATS is not set +# CONFIG_IP_MROUTE is not set +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_NF_ARPFILTER is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_ARP_MANGLE is not set +# CONFIG_IP_NF_FILTER is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_RPFILTER is not set +# CONFIG_IP_NF_MATCH_TTL is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_SECURITY is not set +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_MASQUERADE is not set +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_IP_NF_TARGET_REJECT is not set +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +# CONFIG_IP_NF_TARGET_TTL is not set +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_IP_PNP is not set +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_SCTP is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_SET_HASH_IPMAC is not set +# CONFIG_IP_VS is not set +# CONFIG_IP_VS_MH is not set +CONFIG_IP_VS_MH_TAB_INDEX=10 +# CONFIG_IRDA is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_IRQ_ALL_CPUS is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_IRQ_POLL is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_IR_GPIO_CIR is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_IMG is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_IMON_RAW is not set +# CONFIG_IR_JVC_DECODER is not set +# CONFIG_IR_LIRC_CODEC is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_NEC_DECODER is not set +# CONFIG_IR_RC5_DECODER is not set +# CONFIG_IR_RC6_DECODER is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_SONY_DECODER is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_ISA_BUS is not set +# CONFIG_ISA_BUS_API is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_ISCSI_TCP is not set +CONFIG_ISDN=y +# CONFIG_ISDN_AUDIO is not set +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_CAPI_CAPIDRV is not set +# CONFIG_ISDN_DIVERSION is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +# CONFIG_ISDN_DRV_GIGASET is not set +# CONFIG_ISDN_DRV_HISAX is not set +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_LOOP is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_I4L is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_ISL29125 is not set +# CONFIG_ISL29501 is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_ISS4xx is not set +# CONFIG_ITG3200 is not set +# CONFIG_IWL3945 is not set +# CONFIG_IWLWIFI is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_JAILHOUSE_GUEST is not set +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_POSIX_ACL is not set +# CONFIG_JFFS2_FS_SECURITY is not set +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_LZMA=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_ZLIB is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_JME is not set +CONFIG_JOLIET=y +# CONFIG_JSA1212 is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_JZ4740_WDT is not set +# CONFIG_JZ4770_PHY is not set +# CONFIG_KALLSYMS is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +# CONFIG_KALLSYMS_UNCOMPRESSED is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_KASAN is not set +CONFIG_KASAN_STACK=1 +# CONFIG_KCMP is not set +# CONFIG_KCOV is not set +# CONFIG_KCSAN is not set +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_CAT is not set +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_LZ4 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_KERNEL_MODE_NEON=y +CONFIG_KERNEL_XZ=y +# CONFIG_KERNEL_ZSTD is not set +CONFIG_KERNFS=y +# CONFIG_KEXEC is not set +# CONFIG_KEXEC_FILE is not set +# CONFIG_KEXEC_SIG is not set +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_APPLESPI is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PXA27x is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_SH_KEYSC is not set +# CONFIG_KEYBOARD_SNVS_PWRKEY is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_TEGRA is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_TWL4030 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYS is not set +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_KGDB is not set +# CONFIG_KMEMCHECK is not set +# CONFIG_KMX61 is not set +# CONFIG_KPC2000 is not set +# CONFIG_KPROBES is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set +# CONFIG_KPROBE_EVENT_GEN_TEST is not set +# CONFIG_KS7010 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSM is not set +# CONFIG_KSZ884X_PCI is not set +# CONFIG_KUNIT is not set +CONFIG_KUSER_HELPERS=y +# CONFIG_KVM_AMD is not set +# CONFIG_KVM_AMD_SEV is not set +# CONFIG_KVM_GUEST is not set +# CONFIG_KVM_INTEL is not set +# CONFIG_KVM_WERROR is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_KXSD9 is not set +# CONFIG_L2TP is not set +# CONFIG_L2TP_ETH is not set +# CONFIG_L2TP_IP is not set +# CONFIG_L2TP_V3 is not set +# CONFIG_LAN743X is not set +# CONFIG_LANMEDIA is not set +# CONFIG_LANTIQ is not set +# CONFIG_LAPB is not set +# CONFIG_LASAT is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_LBDAF=y +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_LCD_HX8357 is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_OTM3225A is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LDISC_AUTOLOAD=y +# CONFIG_LDM_PARTITION is not set +CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y +# CONFIG_LEDS_AN30259A is not set +# CONFIG_LEDS_APU is not set +# CONFIG_LEDS_AW2013 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +CONFIG_LEDS_CLASS_MULTICOLOR=y +# CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_EL15203000 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3532 is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP50XX is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP55XX_COMMON is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_MLXCPLD is not set +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_NIC78BX is not set +# CONFIG_LEDS_NS2 is not set +# CONFIG_LEDS_OT200 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_SPI_BYTE is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TI_LMU_COMMON is not set +# CONFIG_LEDS_TLC591XX is not set +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_AUDIO is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +# CONFIG_LEDS_TRIGGER_DISK is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_MTD is not set +CONFIG_LEDS_TRIGGER_NETDEV=y +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_PANIC is not set +# CONFIG_LEDS_TRIGGER_PATTERN is not set +CONFIG_LEDS_TRIGGER_TIMER=y +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TURRIS_OMNIA is not set +# CONFIG_LEDS_USER is not set +# CONFIG_LED_TRIGGER_PHY is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_LGUEST is not set +# CONFIG_LIB80211 is not set +# CONFIG_LIB80211_CRYPT_CCMP is not set +# CONFIG_LIB80211_CRYPT_TKIP is not set +# CONFIG_LIB80211_CRYPT_WEP is not set +# CONFIG_LIB80211_DEBUG is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_LIBERTAS_USB is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_LIBIPW_DEBUG is not set +# CONFIG_LIBNVDIMM is not set +# CONFIG_LIDAR_LITE_V2 is not set +CONFIG_LINEAR_RANGES=y +# CONFIG_LIQUIDIO is not set +# CONFIG_LIQUIDIO_VF is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_LKDTM is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_LMP91000 is not set +# CONFIG_LNET is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_LOCKD is not set +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_LOCKD_V4=y +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_LOCK_EVENT_COUNTS is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_LOGFS is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIWHEELS_FF is not set +# CONFIG_LOGO is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +# CONFIG_LOONGSON_MC146818 is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_LP_CONSOLE is not set +# CONFIG_LSI_ET1011C_PHY is not set +CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity" +CONFIG_LSM_MMAP_MIN_ADDR=65536 +# CONFIG_LTC1660 is not set +# CONFIG_LTC2471 is not set +# CONFIG_LTC2485 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2497 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2983 is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LTPC is not set +# CONFIG_LTR501 is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_LV0104CS is not set +# CONFIG_LWTUNNEL is not set +# CONFIG_LXT_PHY is not set +# CONFIG_LZ4HC_COMPRESS is not set +# CONFIG_LZ4_COMPRESS is not set +# CONFIG_LZ4_DECOMPRESS is not set +CONFIG_LZMA_COMPRESS=y +CONFIG_LZMA_DECOMPRESS=y +# CONFIG_LZO_COMPRESS is not set +# CONFIG_LZO_DECOMPRESS is not set +# CONFIG_M62332 is not set +# CONFIG_MAC80211 is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_MACB is not set +# CONFIG_MACB_USE_HWSTAMP is not set +# CONFIG_MACH_ASM9260 is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_INGENIC is not set +# CONFIG_MACH_INGENIC_SOC is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_JZ4740 is not set +# CONFIG_MACH_LOONGSON2EF is not set +# CONFIG_MACH_LOONGSON32 is not set +# CONFIG_MACH_LOONGSON64 is not set +# CONFIG_MACH_PIC32 is not set +# CONFIG_MACH_PISTACHIO is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MACH_XILFPGA is not set +# CONFIG_MACINTOSH_DRIVERS is not set +# CONFIG_MACSEC is not set +# CONFIG_MACVLAN is not set +# CONFIG_MACVTAP is not set +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MAG3110 is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +# CONFIG_MAGIC_SYSRQ_SERIAL is not set +CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" +# CONFIG_MAILBOX is not set +# CONFIG_MANAGER_SBS is not set +# CONFIG_MANDATORY_FILE_LOCKING is not set +# CONFIG_MANGLE_BOOTARGS is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MAX30100 is not set +# CONFIG_MAX30102 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX44000 is not set +# CONFIG_MAX44009 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5432 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_MAX9611 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +CONFIG_MAY_USE_DEVLINK=y +# CONFIG_MB1232 is not set +# CONFIG_MC3230 is not set +# CONFIG_MCB is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP4018 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4531 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MCPM is not set +# CONFIG_MD is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BUS_MUX_MULTIPLEXER is not set +# CONFIG_MDIO_DEVICE is not set +# CONFIG_MDIO_DEVRES is not set +# CONFIG_MDIO_HISI_FEMAC is not set +# CONFIG_MDIO_IPQ4019 is not set +# CONFIG_MDIO_IPQ8064 is not set +# CONFIG_MDIO_MSCC_MIIM is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_THUNDER is not set +# CONFIG_MDIO_XPCS is not set +# CONFIG_MD_FAULTY is not set +# CONFIG_MEDIATEK_GE_PHY is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_ATTACH is not set +# CONFIG_MEDIA_CAMERA_SUPPORT is not set +# CONFIG_MEDIA_CEC_SUPPORT is not set +# CONFIG_MEDIA_CONTROLLER is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +# CONFIG_MEDIA_PLATFORM_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +# CONFIG_MEDIA_SUPPORT is not set +# CONFIG_MEDIA_SUPPORT_FILTER is not set +# CONFIG_MEDIA_TEST_SUPPORT is not set +# CONFIG_MEDIA_TUNER_E4000 is not set +# CONFIG_MEDIA_TUNER_FC0011 is not set +# CONFIG_MEDIA_TUNER_FC0012 is not set +# CONFIG_MEDIA_TUNER_FC0013 is not set +# CONFIG_MEDIA_TUNER_FC2580 is not set +# CONFIG_MEDIA_TUNER_IT913X is not set +# CONFIG_MEDIA_TUNER_M88RS6000T is not set +# CONFIG_MEDIA_TUNER_MAX2165 is not set +# CONFIG_MEDIA_TUNER_MC44S803 is not set +# CONFIG_MEDIA_TUNER_MSI001 is not set +# CONFIG_MEDIA_TUNER_MT2060 is not set +# CONFIG_MEDIA_TUNER_MT2063 is not set +# CONFIG_MEDIA_TUNER_MT20XX is not set +# CONFIG_MEDIA_TUNER_MT2131 is not set +# CONFIG_MEDIA_TUNER_MT2266 is not set +# CONFIG_MEDIA_TUNER_MXL301RF is not set +# CONFIG_MEDIA_TUNER_MXL5005S is not set +# CONFIG_MEDIA_TUNER_MXL5007T is not set +# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set +# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set +# CONFIG_MEDIA_TUNER_QT1010 is not set +# CONFIG_MEDIA_TUNER_R820T is not set +# CONFIG_MEDIA_TUNER_SI2157 is not set +# CONFIG_MEDIA_TUNER_SIMPLE is not set +# CONFIG_MEDIA_TUNER_TDA18212 is not set +# CONFIG_MEDIA_TUNER_TDA18218 is not set +# CONFIG_MEDIA_TUNER_TDA18250 is not set +# CONFIG_MEDIA_TUNER_TDA18271 is not set +# CONFIG_MEDIA_TUNER_TDA827X is not set +# CONFIG_MEDIA_TUNER_TDA8290 is not set +# CONFIG_MEDIA_TUNER_TDA9887 is not set +# CONFIG_MEDIA_TUNER_TEA5761 is not set +# CONFIG_MEDIA_TUNER_TEA5767 is not set +# CONFIG_MEDIA_TUNER_TUA9001 is not set +# CONFIG_MEDIA_TUNER_XC2028 is not set +# CONFIG_MEDIA_TUNER_XC4000 is not set +# CONFIG_MEDIA_TUNER_XC5000 is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_MELLANOX_PLATFORM is not set +CONFIG_MEMBARRIER=y +# CONFIG_MEMORY is not set +# CONFIG_MEMORY_FAILURE is not set +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MEMSTICK is not set +# CONFIG_MEMTEST is not set +# CONFIG_MEN_A21_WDT is not set +# CONFIG_MESON_SM is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_AC100 is not set +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_EXYNOS_LPASS is not set +# CONFIG_MFD_GATEWORKS_GSC is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set +# CONFIG_MFD_IQS62X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_LOCHNAGAR is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MAX77650 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_MFD_MP2629 is not set +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_OMAP_USB_HOST is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_PM8921_CORE is not set +# CONFIG_MFD_PM8XXX is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_ROHM_BD70528 is not set +# CONFIG_MFD_ROHM_BD71828 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SL28CPLD is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_STMFX is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_STPMIC1 is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS68470 is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MG_DISK is not set +# CONFIG_MHI_BUS is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_KSZ is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROCHIP_PIT64B is not set +# CONFIG_MICROCHIP_T1_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_MIGRATION is not set +CONFIG_HARDEN_BRANCH_HISTORY=y +CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y +CONFIG_MII=y +# CONFIG_MIKROTIK is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_MINIX_FS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_MIPS_ALCHEMY is not set +# CONFIG_MIPS_CDMM is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MIPS_FPU_EMULATOR is not set +# CONFIG_MIPS_FP_SUPPORT is not set +# CONFIG_MIPS_GENERIC is not set +# CONFIG_MIPS_GENERIC_KERNEL is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_O32_FP64_SUPPORT is not set +# CONFIG_MIPS_PARAVIRT is not set +# CONFIG_MIPS_PLATFORM_DEVICES is not set +# CONFIG_MIPS_SEAD3 is not set +# CONFIG_MISC_ALCOR_PCI is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_MISC_RTSX_PCI is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_MISDN is not set +# CONFIG_MISDN_AVMFRITZ is not set +# CONFIG_MISDN_HFCPCI is not set +# CONFIG_MISDN_HFCUSB is not set +# CONFIG_MISDN_INFINEON is not set +# CONFIG_MISDN_NETJET is not set +# CONFIG_MISDN_SPEEDFAX is not set +# CONFIG_MISDN_W6692 is not set +# CONFIG_MKISS is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLX90614 is not set +# CONFIG_MLX90632 is not set +# CONFIG_MLXFW is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLX_CPLD_PLATFORM is not set +# CONFIG_MLX_PLATFORM is not set +# CONFIG_MMA7455_I2C is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMA7660 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MMC is not set +# CONFIG_MMC35240 is not set +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_AU1X is not set +# CONFIG_MMC_BLOCK is not set +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_MMC_BLOCK_MINORS=8 +# CONFIG_MMC_CAVIUM_THUNDERX is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_JZ4740 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_MVSDIO is not set +# CONFIG_MMC_S3C is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SDHCI_ACPI is not set +# CONFIG_MMC_SDHCI_AM654 is not set +# CONFIG_MMC_SDHCI_BCM_KONA is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_SDHCI_IPROC is not set +# CONFIG_MMC_SDHCI_MILBEAUT is not set +# CONFIG_MMC_SDHCI_MSM is not set +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_ASPEED is not set +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_OF_ESDHC is not set +# CONFIG_MMC_SDHCI_OF_HLWD is not set +# CONFIG_MMC_SDHCI_OMAP is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_S3C is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MMC_SDRICOH_CS is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_STM32_SDMMC is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMIOTRACE is not set +CONFIG_MMU=y +CONFIG_MMU_GATHER_RCU_TABLE_FREE=y +CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MODULES=y +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_MODULE_STRIPPED=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MOST is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_MOUSE_PS2_FOCALTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_MOXTET is not set +# CONFIG_MPL115 is not set +# CONFIG_MPL115_I2C is not set +# CONFIG_MPL115_SPI is not set +# CONFIG_MPL3115 is not set +# CONFIG_MPLS is not set +# CONFIG_MPTCP is not set +# CONFIG_MPU3050_I2C is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_MSCC_OCELOT_SWITCH is not set +# CONFIG_MSDOS_FS is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_MSI_BITMAP_SELFTEST is not set +# CONFIG_MSI_LAPTOP is not set +# CONFIG_MST_IRQ is not set +CONFIG_MTD=y +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_MTD_CFI=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_HYPERBUS is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_LATCH_ADDR is not set +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_LPDDR2_NVM is not set +# CONFIG_MTD_M25P80 is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MT81xx_NOR is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_MYLOADER_PARTS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_NAND_AMS_DELTA is not set +# CONFIG_MTD_NAND_AR934X is not set +# CONFIG_MTD_NAND_AR934X_HW_ECC is not set +# CONFIG_MTD_NAND_ARASAN is not set +# CONFIG_MTD_NAND_ATMEL is not set +# CONFIG_MTD_NAND_AU1550 is not set +# CONFIG_MTD_NAND_BCH is not set +# CONFIG_MTD_NAND_BF5XX is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_CADENCE is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_CM_X270 is not set +# CONFIG_MTD_NAND_CS553X is not set +# CONFIG_MTD_NAND_DAVINCI is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_DENALI_PCI is not set +CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_ECC is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_ECC_SW_BCH is not set +# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set +# CONFIG_MTD_NAND_FSL_ELBC is not set +# CONFIG_MTD_NAND_FSL_IFC is not set +# CONFIG_MTD_NAND_FSL_UPM is not set +# CONFIG_MTD_NAND_FSMC is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_GPMI_NAND is not set +# CONFIG_MTD_NAND_HISI504 is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_JZ4740 is not set +# CONFIG_MTD_NAND_MPC5121_NFC is not set +# CONFIG_MTD_NAND_MTK is not set +# CONFIG_MTD_NAND_MTK_BMT is not set +# CONFIG_MTD_NAND_MXC is not set +# CONFIG_MTD_NAND_MXIC is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_NDFC is not set +# CONFIG_MTD_NAND_NUC900 is not set +# CONFIG_MTD_NAND_OMAP2 is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +# CONFIG_MTD_NAND_ORION is not set +# CONFIG_MTD_NAND_PASEMI is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_NAND_PXA3xx is not set +# CONFIG_MTD_NAND_RB4XX is not set +# CONFIG_MTD_NAND_RB750 is not set +# CONFIG_MTD_NAND_RB91X is not set +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_S3C2410 is not set +# CONFIG_MTD_NAND_SHARPSL is not set +# CONFIG_MTD_NAND_SH_FLCTL is not set +# CONFIG_MTD_NAND_SOCRATES is not set +# CONFIG_MTD_NAND_TMIO is not set +# CONFIG_MTD_NAND_TXX9NDFMC is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_PARSER_TRX is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PHYSMAP_GEMINI is not set +# CONFIG_MTD_PHYSMAP_GPIO_ADDR is not set +# CONFIG_MTD_PHYSMAP_IXP4XX is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PHYSMAP_OF_GEMINI is not set +# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set +# CONFIG_MTD_PHYSMAP_VERSATILE is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_RAW_NAND is not set +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_ROM is not set +CONFIG_MTD_ROOTFS_ROOT_DEV=y +# CONFIG_MTD_ROUTERBOOT_PARTS is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_SPINAND_MT29F is not set +# CONFIG_MTD_SPI_NAND is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 +# CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE is not set +CONFIG_MTD_SPLIT=y +# CONFIG_MTD_SPLIT_BCM63XX_FW is not set +# CONFIG_MTD_SPLIT_BCM_WFI_FW is not set +# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set +# CONFIG_MTD_SPLIT_ELF_FW is not set +# CONFIG_MTD_SPLIT_EVA_FW is not set +# CONFIG_MTD_SPLIT_FIRMWARE is not set +CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" +# CONFIG_MTD_SPLIT_FIT_FW is not set +# CONFIG_MTD_SPLIT_JIMAGE_FW is not set +# CONFIG_MTD_SPLIT_LZMA_FW is not set +# CONFIG_MTD_SPLIT_MINOR_FW is not set +# CONFIG_MTD_SPLIT_SEAMA_FW is not set +CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y +CONFIG_MTD_SPLIT_SUPPORT=y +# CONFIG_MTD_SPLIT_TPLINK_FW is not set +# CONFIG_MTD_SPLIT_TRX_FW is not set +# CONFIG_MTD_SPLIT_UIMAGE_FW is not set +# CONFIG_MTD_SPLIT_WRGG_FW is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_UBI is not set +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UIMAGE_SPLIT is not set +# CONFIG_MTD_VIRT_CONCAT is not set +# CONFIG_MTK_MMC is not set +# CONFIG_MTK_MMSYS is not set +# CONFIG_MULTIPLEXER is not set +CONFIG_MULTIUSER=y +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_MUX_ADG792A is not set +# CONFIG_MUX_ADGS1408 is not set +# CONFIG_MUX_GPIO is not set +# CONFIG_MUX_MMIO is not set +# CONFIG_MV643XX_ETH is not set +# CONFIG_MVMDIO is not set +# CONFIG_MVNETA_BM is not set +# CONFIG_MVSW61XX_PHY is not set +# CONFIG_MV_XOR_V2 is not set +# CONFIG_MWAVE is not set +# CONFIG_MWL8K is not set +# CONFIG_MXC4005 is not set +# CONFIG_MXC6255 is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_NATSEMI is not set +# CONFIG_NAU7802 is not set +# CONFIG_NBPFAXI_DMA is not set +# CONFIG_NCP_FS is not set +# CONFIG_NE2000 is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NEC_MARKEINS is not set +CONFIG_NET=y +# CONFIG_NETCONSOLE is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVSIM is not set +# CONFIG_NETFILTER is not set +# CONFIG_NETFILTER_ADVANCED is not set +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_INGRESS is not set +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NETFILTER_NETLINK_OSF is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_NETFILTER_XT_CONNMARK is not set +# CONFIG_NETFILTER_XT_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +# CONFIG_NETFILTER_XT_MATCH_STATE is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_CT is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +# CONFIG_NETFILTER_XT_TARGET_LOG is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set +# CONFIG_NETFILTER_XT_TARGET_SECMARK is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NETROM is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NET_9P is not set +# CONFIG_NET_ACT_BPF is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_ACT_CT is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_GATE is not set +# CONFIG_NET_ACT_IFE is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_MPLS is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_SAMPLE is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_SKBMOD is not set +# CONFIG_NET_ACT_TUNNEL_KEY is not set +# CONFIG_NET_ACT_VLAN is not set +CONFIG_NET_CADENCE=y +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_FW is not set +CONFIG_NET_CLS_IND=y +# CONFIG_NET_CLS_MATCHALL is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_U32 is not set +CONFIG_NET_CORE=y +# CONFIG_NET_DEVLINK is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_NET_DSA is not set +# CONFIG_NET_DSA_AR9331 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_NET_DSA_LANTIQ_GSWIP is not set +# CONFIG_NET_DSA_LEGACY is not set +# CONFIG_NET_DSA_LOOP is not set +# CONFIG_NET_DSA_MICROCHIP_KSZ8795 is not set +# CONFIG_NET_DSA_MICROCHIP_KSZ9477 is not set +# CONFIG_NET_DSA_MSCC_FELIX is not set +# CONFIG_NET_DSA_MSCC_SEVILLE is not set +# CONFIG_NET_DSA_MT7530 is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6XXX_PTP is not set +# CONFIG_NET_DSA_QCA8K is not set +# CONFIG_NET_DSA_REALTEK_SMI is not set +# CONFIG_NET_DSA_SJA1105 is not set +# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set +# CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set +# CONFIG_NET_DSA_TAG_8021Q is not set +# CONFIG_NET_DSA_TAG_AR9331 is not set +# CONFIG_NET_DSA_TAG_BRCM is not set +# CONFIG_NET_DSA_TAG_BRCM_LEGACY is not set +# CONFIG_NET_DSA_TAG_BRCM_PREPEND is not set +# CONFIG_NET_DSA_TAG_DSA is not set +# CONFIG_NET_DSA_TAG_EDSA is not set +# CONFIG_NET_DSA_TAG_GSWIP is not set +# CONFIG_NET_DSA_TAG_KSZ is not set +# CONFIG_NET_DSA_TAG_LAN9303 is not set +# CONFIG_NET_DSA_TAG_MTK is not set +# CONFIG_NET_DSA_TAG_OCELOT is not set +# CONFIG_NET_DSA_TAG_QCA is not set +# CONFIG_NET_DSA_TAG_RTL4_A is not set +# CONFIG_NET_DSA_TAG_SJA1105 is not set +# CONFIG_NET_DSA_TAG_TRAILER is not set +# CONFIG_NET_DSA_VITESSE_VSC73XX is not set +# CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM is not set +# CONFIG_NET_DSA_VITESSE_VSC73XX_SPI is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_EMATCH_CANID is not set +# CONFIG_NET_EMATCH_CMP is not set +# CONFIG_NET_EMATCH_IPT is not set +# CONFIG_NET_EMATCH_META is not set +# CONFIG_NET_EMATCH_NBYTE is not set +CONFIG_NET_EMATCH_STACK=32 +# CONFIG_NET_EMATCH_TEXT is not set +# CONFIG_NET_EMATCH_U32 is not set +# CONFIG_NET_FAILOVER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_NET_IFE is not set +# CONFIG_NET_IPGRE is not set +CONFIG_NET_IPGRE_BROADCAST=y +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_IP_TUNNEL is not set +# CONFIG_NET_KEY is not set +# CONFIG_NET_KEY_MIGRATE is not set +# CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_NET_MEDIATEK_STAR_EMAC is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_NET_NCSI is not set +# CONFIG_NET_NSH is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_NET_PTP_CLASSIFY is not set +CONFIG_NET_RX_BUSY_POLL=y +# CONFIG_NET_SB1000 is not set +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_ATM is not set +# CONFIG_NET_SCH_CAKE is not set +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_CBS is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_CODEL is not set +CONFIG_NET_SCH_DEFAULT=y +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_ETS is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_NET_SCH_FQ is not set +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ_PIE is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_SKBPRIO is not set +# CONFIG_NET_SCH_TAPRIO is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCTPPROBE is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_TCPPROBE is not set +# CONFIG_NET_TC_SKB_EXT is not set +# CONFIG_NET_TEAM is not set +# CONFIG_NET_TULIP is not set +# CONFIG_NET_UDP_TUNNEL is not set +CONFIG_NET_VENDOR_3COM=y +CONFIG_NET_VENDOR_8390=y +CONFIG_NET_VENDOR_ADAPTEC=y +CONFIG_NET_VENDOR_AGERE=y +CONFIG_NET_VENDOR_ALACRITECH=y +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_NET_VENDOR_AMAZON=y +CONFIG_NET_VENDOR_AMD=y +CONFIG_NET_VENDOR_AQUANTIA=y +CONFIG_NET_VENDOR_ARC=y +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_NET_VENDOR_AURORA=y +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_NET_VENDOR_CADENCE=y +CONFIG_NET_VENDOR_CAVIUM=y +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_NET_VENDOR_CIRRUS=y +CONFIG_NET_VENDOR_CISCO=y +CONFIG_NET_VENDOR_CORTINA=y +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_VENDOR_DLINK=y +CONFIG_NET_VENDOR_EMULEX=y +CONFIG_NET_VENDOR_EXAR=y +CONFIG_NET_VENDOR_EZCHIP=y +CONFIG_NET_VENDOR_FARADAY=y +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_NET_VENDOR_FUJITSU=y +CONFIG_NET_VENDOR_GOOGLE=y +CONFIG_NET_VENDOR_HISILICON=y +CONFIG_NET_VENDOR_HP=y +CONFIG_NET_VENDOR_HUAWEI=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_IBM=y +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MELLANOX=y +CONFIG_NET_VENDOR_MICREL=y +CONFIG_NET_VENDOR_MICROCHIP=y +CONFIG_NET_VENDOR_MICROSEMI=y +CONFIG_NET_VENDOR_MYRI=y +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_NETERION=y +CONFIG_NET_VENDOR_NETRONOME=y +CONFIG_NET_VENDOR_NI=y +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_NET_VENDOR_OKI=y +CONFIG_NET_VENDOR_PACKET_ENGINES=y +CONFIG_NET_VENDOR_PENSANDO=y +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_NET_VENDOR_QUALCOMM=y +CONFIG_NET_VENDOR_RDC=y +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +CONFIG_NET_VENDOR_SIS=y +CONFIG_NET_VENDOR_SMSC=y +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NET_VENDOR_SOLARFLARE=y +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_NET_VENDOR_SUN=y +CONFIG_NET_VENDOR_SYNOPSYS=y +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_NET_VENDOR_TI=y +CONFIG_NET_VENDOR_TOSHIBA=y +CONFIG_NET_VENDOR_VIA=y +CONFIG_NET_VENDOR_WIZNET=y +CONFIG_NET_VENDOR_XILINX=y +CONFIG_NET_VENDOR_XIRCOM=y +# CONFIG_NET_VRF is not set +# CONFIG_NET_XGENE is not set +CONFIG_NEW_LEDS=y +# CONFIG_NFC is not set +# CONFIG_NFP is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V2_ACL is not set +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +# CONFIG_NFS_ACL_SUPPORT is not set +CONFIG_NFS_COMMON=y +# CONFIG_NFS_DISABLE_UDP_SUPPORT is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFS_FSCACHE is not set +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_V4_1 is not set +# CONFIG_NFTL is not set +# CONFIG_NFT_BRIDGE_META is not set +# CONFIG_NFT_BRIDGE_REJECT is not set +# CONFIG_NFT_CONNLIMIT is not set +# CONFIG_NFT_DUP_IPV4 is not set +# CONFIG_NFT_DUP_IPV6 is not set +# CONFIG_NFT_FIB_IPV4 is not set +# CONFIG_NFT_FIB_IPV6 is not set +# CONFIG_NFT_FIB_NETDEV is not set +# CONFIG_NFT_FLOW_OFFLOAD is not set +# CONFIG_NFT_OBJREF is not set +# CONFIG_NFT_OSF is not set +# CONFIG_NFT_RT is not set +# CONFIG_NFT_SET_BITMAP is not set +# CONFIG_NFT_SOCKET is not set +# CONFIG_NFT_SYNPROXY is not set +# CONFIG_NFT_TPROXY is not set +# CONFIG_NFT_TUNNEL is not set +# CONFIG_NFT_XFRM is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_BRIDGE is not set +# CONFIG_NF_CONNTRACK_EVENTS is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_LABELS is not set +# CONFIG_NF_CONNTRACK_MARK is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +CONFIG_NF_CONNTRACK_PROCFS=y +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SECMARK is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CONNTRACK_ZONES is not set +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NF_CT_NETLINK_HELPER is not set +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_GRE is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_FLOW_TABLE is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_BRIDGE is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_LOG_NETDEV is not set +# CONFIG_NF_NAT is not set +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_FTP is not set +# CONFIG_NF_NAT_H323 is not set +# CONFIG_NF_NAT_IPV6 is not set +# CONFIG_NF_NAT_IRC is not set +CONFIG_NF_NAT_MASQUERADE_IPV4=y +CONFIG_NF_NAT_MASQUERADE_IPV6=y +# CONFIG_NF_NAT_NEEDED is not set +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_PROTO_GRE is not set +# CONFIG_NF_NAT_SIP is not set +# CONFIG_NF_NAT_SNMP_BASIC is not set +# CONFIG_NF_NAT_TFTP is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_SOCKET_IPV4 is not set +# CONFIG_NF_SOCKET_IPV6 is not set +# CONFIG_NF_TABLES is not set +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_TABLES_BRIDGE=y +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_IPV4=y +CONFIG_NF_TABLES_IPV6=y +CONFIG_NF_TABLES_NETDEV=y +# CONFIG_NF_TABLES_SET is not set +# CONFIG_NF_TPROXY_IPV4 is not set +# CONFIG_NF_TPROXY_IPV6 is not set +# CONFIG_NI65 is not set +# CONFIG_NI903X_WDT is not set +# CONFIG_NIC7018_WDT is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_NIU is not set +# CONFIG_NI_XGE_MANAGEMENT_ENET is not set +CONFIG_NLATTR=y +# CONFIG_NLMON is not set +# CONFIG_NLM_XLP_BOARD is not set +# CONFIG_NLM_XLR_BOARD is not set +# CONFIG_NLS is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +CONFIG_NMI_LOG_BUF_SHIFT=13 +# CONFIG_NOA1305 is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_NORTEL_HERMES is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT is not set +# CONFIG_NOZOMI is not set +# CONFIG_NO_BOOTMEM is not set +# CONFIG_NO_HZ is not set +# CONFIG_NO_HZ_FULL is not set +# CONFIG_NO_HZ_IDLE is not set +# CONFIG_NS83820 is not set +# CONFIG_NTB is not set +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_NTP_PPS is not set +# CONFIG_NULL_TTY is not set +# CONFIG_NUMA is not set +# CONFIG_NVM is not set +# CONFIG_NVMEM is not set +# CONFIG_NVMEM_BCM_OCOTP is not set +# CONFIG_NVMEM_IMX_OCOTP is not set +# CONFIG_NVMEM_REBOOT_MODE is not set +# 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 +# CONFIG_NXP_STB225 is not set +# CONFIG_NXP_TJA11XX_PHY is not set +# CONFIG_N_GSM is not set +# CONFIG_OABI_COMPAT is not set +# CONFIG_OBS600 is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_OCTEONTX2_AF is not set +# CONFIG_OCTEONTX2_PF is not set +# CONFIG_OF_OVERLAY is not set +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_UNITTEST is not set +# CONFIG_OID_REGISTRY is not set +# CONFIG_OMAP2_DSS_DEBUG is not set +# CONFIG_OMAP2_DSS_DEBUGFS is not set +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP_OCP2SCP is not set +# CONFIG_OMAP_USB2 is not set +# CONFIG_OMFS_FS is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_OPROFILE is not set +# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set +# CONFIG_OPT3001 is not set +CONFIG_OPTIMIZE_INLINING=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ORION_WATCHDOG is not set +# CONFIG_OSF_PARTITION is not set +CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_INDEX is not set +# CONFIG_OVERLAY_FS_METACOPY is not set +CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +CONFIG_OVERLAY_FS_XINO_AUTO=y +# CONFIG_OWL_LOADER is not set +# CONFIG_P54_COMMON is not set +# CONFIG_PA12203001 is not set +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +# CONFIG_PACKING is not set +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_PAGE_REPORTING is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_32KB is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PALMAS_GPADC is not set +# CONFIG_PANASONIC_LAPTOP is not set +# CONFIG_PANEL is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=1 +# CONFIG_PANTHERLORD_FF is not set +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +# CONFIG_PARPORT is not set +# CONFIG_PARPORT_1284 is not set +# CONFIG_PARPORT_AX88796 is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_PC is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARASAN_CF is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CS5535 is not set +# CONFIG_PATA_CS5536 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IMX is not set +# CONFIG_PATA_ISAPNP is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OCTEON_CF is not set +# CONFIG_PATA_OF_PLATFORM is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PCMCIA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_QDI is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_WINBOND_VLB is not set +# CONFIG_PC104 is not set +# CONFIG_PC300TOO is not set +# CONFIG_PCCARD is not set +# CONFIG_PCH_DMA is not set +# CONFIG_PCH_GBE is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_PCI is not set +# CONFIG_PCI200SYN is not set +# CONFIG_PCIEAER is not set +# CONFIG_PCIEAER_INJECT is not set +# CONFIG_PCIEASPM is not set +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCIE_AL is not set +# CONFIG_PCIE_ALTERA is not set +# CONFIG_PCIE_ARMADA_8K is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_PEER2PEER is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_TUNE_OFF is not set +# CONFIG_PCIE_BW is not set +# CONFIG_PCIE_CADENCE_HOST is not set +# CONFIG_PCIE_CADENCE_PLAT_HOST is not set +# CONFIG_PCIE_DPC is not set +# CONFIG_PCIE_DW_PLAT is not set +# CONFIG_PCIE_DW_PLAT_HOST is not set +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIE_IPROC is not set +# CONFIG_PCIE_KIRIN is not set +# CONFIG_PCIE_LAYERSCAPE_GEN4 is not set +# CONFIG_PCIE_PTM is not set +# CONFIG_PCIE_XILINX is not set +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_PCI_ATMEL is not set +# CONFIG_PCI_CNB20LE_QUIRK is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set +# CONFIG_PCI_ENDPOINT is not set +# CONFIG_PCI_ENDPOINT_TEST is not set +# CONFIG_PCI_FTPCI100 is not set +# CONFIG_PCI_HERMES is not set +# CONFIG_PCI_HISI is not set +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_J721E_HOST is not set +# CONFIG_PCI_LAYERSCAPE is not set +# CONFIG_PCI_MESON is not set +# CONFIG_PCI_MSI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_PCI_PF_STUB is not set +# CONFIG_PCI_PRI is not set +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_SW_SWITCHTEC is not set +CONFIG_PCI_SYSCALL=y +# CONFIG_PCI_V3_SEMI is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCMCIA is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_ATMEL is not set +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_PCMCIA_LOAD_CIS is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_SPECTRUM is not set +# CONFIG_PCMCIA_SYM53C500 is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_XIRCOM is not set +# CONFIG_PCNET32 is not set +# CONFIG_PCSPKR_PLATFORM is not set +# CONFIG_PCS_XPCS is not set +# CONFIG_PD6729 is not set +# CONFIG_PDA_POWER is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_PERCPU_STATS is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_EVENTS_AMD_POWER is not set +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_PHANTOM is not set +# CONFIG_PHONET is not set +# CONFIG_PHYLIB is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_PHY_CADENCE_DP is not set +# CONFIG_PHY_CADENCE_DPHY is not set +# CONFIG_PHY_CADENCE_SALVO is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_EXYNOS_DP_VIDEO is not set +# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set +# CONFIG_PHY_FSL_IMX8MQ_USB is not set +# CONFIG_PHY_INTEL_KEEMBAY_EMMC is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +# CONFIG_PHY_MIXEL_MIPI_DPHY is not set +# CONFIG_PHY_MTK_HDMI is not set +# CONFIG_PHY_OCELOT_SERDES is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_QCOM_DWC3 is not set +# CONFIG_PHY_QCOM_USB_HS is not set +# CONFIG_PHY_QCOM_USB_HSIC is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_TUSB1210 is not set +# CONFIG_PHY_XGENE is not set +# CONFIG_PI433 is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_PID_NS is not set +CONFIG_PINCONF=y +# CONFIG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_AXP209 is not set +# CONFIG_PINCTRL_CEDARFORK is not set +# CONFIG_PINCTRL_EXYNOS is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set +# CONFIG_PINCTRL_ICELAKE is not set +# CONFIG_PINCTRL_INGENIC is not set +# CONFIG_PINCTRL_MCP23S08 is not set +# CONFIG_PINCTRL_MSM8X74 is not set +# CONFIG_PINCTRL_MT6779 is not set +# CONFIG_PINCTRL_MT8167 is not set +# CONFIG_PINCTRL_MT8192 is not set +# CONFIG_PINCTRL_MTK_V2 is not set +# CONFIG_PINCTRL_OCELOT is not set +CONFIG_PINCTRL_SINGLE=y +# CONFIG_PINCTRL_STMFX is not set +# CONFIG_PINCTRL_SX150X is not set +# CONFIG_PING is not set +CONFIG_PINMUX=y +# CONFIG_PKCS7_MESSAGE_PARSER is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_PL310_ERRATA_769419 is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_PL330_DMA is not set +# CONFIG_PLATFORM_MHU is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_PLIP is not set +# CONFIG_PLX_DMA is not set +# CONFIG_PLX_HERMES is not set +# CONFIG_PM is not set +# CONFIG_PMBUS is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMS7003 is not set +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_POSIX_MQUEUE is not set +CONFIG_POSIX_TIMERS=y +# CONFIG_POWERCAP is not set +# CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_RESET_BRCMKONA is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LINKSTATION is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_PIIX4_POWEROFF is not set +# CONFIG_POWER_RESET_QNAP is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_POWER_RESET_VERSATILE is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_POWER_SUPPLY_HWMON is not set +# CONFIG_PPC4xx_GPIO is not set +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_256K_PAGES is not set +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_64K_PAGES is not set +# CONFIG_PPC_DISABLE_WERROR is not set +# CONFIG_PPC_EMULATED_STATS is not set +# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set +# CONFIG_PPC_QUEUED_SPINLOCKS is not set +# CONFIG_PPP is not set +# CONFIG_PPPOATM is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_DEFLATE is not set +CONFIG_PPP_FILTER=y +# CONFIG_PPP_MPPE is not set +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPS is not set +# CONFIG_PPS_CLIENT_GPIO is not set +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_PARPORT is not set +# CONFIG_PPS_DEBUG is not set +# CONFIG_PPTP is not set +# CONFIG_PREEMPT is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PRESTERA is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_PRIME_NUMBERS is not set +CONFIG_PRINTK=y +# CONFIG_PRINTK_CALLER is not set +CONFIG_PRINTK_NMI=y +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 +# CONFIG_PRINTK_TIME is not set +CONFIG_PRINT_STACK_DEPTH=64 +# CONFIG_PRISM2_USB is not set +# CONFIG_PRISM54 is not set +# CONFIG_PROC_CHILDREN is not set +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +# CONFIG_PROC_PAGE_MONITOR is not set +# CONFIG_PROC_STRIPPED is not set +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILING is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_PROVE_RAW_LOCK_NESTING is not set +# CONFIG_PROVE_RCU is not set +# CONFIG_PROVE_RCU_LIST is not set +# CONFIG_PROVE_RCU_REPEATEDLY is not set +# CONFIG_PSAMPLE is not set +# CONFIG_PSB6970_PHY is not set +# CONFIG_PSI is not set +# CONFIG_PSTORE is not set +# CONFIG_PSTORE_842_COMPRESS is not set +# CONFIG_PSTORE_COMPRESS is not set +# CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" +# CONFIG_PSTORE_CONSOLE is not set +# CONFIG_PSTORE_DEFLATE_COMPRESS is not set +# CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT is not set +# CONFIG_PSTORE_LZ4HC_COMPRESS is not set +# CONFIG_PSTORE_LZ4_COMPRESS is not set +# CONFIG_PSTORE_LZO_COMPRESS is not set +# CONFIG_PSTORE_PMSG is not set +# CONFIG_PSTORE_RAM is not set +# CONFIG_PSTORE_ZSTD_COMPRESS is not set +# CONFIG_PTDUMP_DEBUGFS is not set +# CONFIG_PTP_1588_CLOCK is not set +# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set +# CONFIG_PTP_1588_CLOCK_IDTCM is not set +# CONFIG_PTP_1588_CLOCK_IXP46X is not set +# CONFIG_PTP_1588_CLOCK_KVM is not set +# CONFIG_PTP_1588_CLOCK_PCH is not set +# CONFIG_PTP_1588_CLOCK_VMW is not set +# CONFIG_PUBLIC_KEY_ALGO_RSA is not set +# CONFIG_PVPANIC is not set +# CONFIG_PWM is not set +# CONFIG_PWM_DEBUG is not set +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_JZ4740 is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWRSEQ_EMMC=y +# CONFIG_PWRSEQ_SD8787 is not set +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_QCA7000 is not set +# CONFIG_QCA7000_SPI is not set +# CONFIG_QCA7000_UART is not set +# CONFIG_QCOM_EMAC is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +# CONFIG_QCOM_HIDMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_QCOM_SPMI_ADC5 is not set +# CONFIG_QCOM_SPMI_IADC is not set +# CONFIG_QCOM_SPMI_TEMP_ALARM is not set +# CONFIG_QCOM_SPMI_VADC is not set +# CONFIG_QED is not set +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_QORIQ_CPUFREQ is not set +# CONFIG_QORIQ_THERMAL is not set +# CONFIG_QRTR is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_QUEUED_LOCK_STAT is not set +# CONFIG_QUICC_ENGINE is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_R3964 is not set +# CONFIG_R6040 is not set +# CONFIG_R8169 is not set +# CONFIG_R8188EU is not set +# CONFIG_R8712U is not set +# CONFIG_R8723AU is not set +# CONFIG_RADIO_ADAPTERS is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +# CONFIG_RAID6_PQ_BENCHMARK is not set +# CONFIG_RAID_ATTRS is not set +# CONFIG_RALINK is not set +# CONFIG_RANDOM32_SELFTEST is not set +# CONFIG_RANDOMIZE_BASE is not set +# CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# CONFIG_RANDOM_TRUST_CPU is not set +# CONFIG_RAPIDIO is not set +# CONFIG_RAS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_RCU_BOOST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +# CONFIG_RCU_EXPERT is not set +CONFIG_RCU_KTHREAD_PRIO=0 +CONFIG_RCU_NEED_SEGCBLIST=y +# CONFIG_RCU_PERF_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set +# CONFIG_RCU_SCALE_TEST is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_STRICT_GRACE_PERIOD is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 +# CONFIG_RCU_TRACE is not set +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_RC_CORE is not set +# CONFIG_RC_DECODERS is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_RC_MAP is not set +# CONFIG_RDS is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_GZIP is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_ZSTD is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_READ_ONLY_THP_FOR_FS is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_REDWOOD is not set +# CONFIG_REED_SOLOMON is not set +# CONFIG_REED_SOLOMON_DEC8 is not set +# CONFIG_REED_SOLOMON_ENC8 is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_REGMAP is not set +# CONFIG_REGMAP_I2C is not set +# CONFIG_REGMAP_MMIO is not set +# CONFIG_REGMAP_SPI is not set +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_88PG86X is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_FAN53880 is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX77826 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MCP16502 is not set +# CONFIG_REGULATOR_MP5416 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MP886X is not set +# CONFIG_REGULATOR_MPQ7920 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +# CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RTMV20 is not set +# CONFIG_REGULATOR_SLG51000 is not set +# CONFIG_REGULATOR_SY8106A is not set +# CONFIG_REGULATOR_SY8824X is not set +# CONFIG_REGULATOR_SY8827N is not set +# CONFIG_REGULATOR_TI_ABB is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_VCTRL is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_FS_POSIX_ACL is not set +# CONFIG_REISERFS_FS_SECURITY is not set +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_RELAY is not set +# CONFIG_RELOCATABLE is not set +# CONFIG_REMOTEPROC is not set +# CONFIG_RENESAS_PHY is not set +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_BRCMSTB_RESCAL is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_RESET_IMX7 is not set +# CONFIG_RESET_INTEL_GW is not set +# CONFIG_RESET_LANTIQ is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set +# CONFIG_RESET_TEGRA_BPMP is not set +# CONFIG_RESET_TI_SYSCON is not set +# CONFIG_RESET_ZYNQ is not set +# CONFIG_RFD77402 is not set +# CONFIG_RFD_FTL is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_FULL is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_LEDS is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_RMNET is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_ROCKER is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_ROSE is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +# CONFIG_RPMSG_VIRTIO is not set +# CONFIG_RPR0521 is not set +# CONFIG_RSEQ is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_RTC_DEBUG is not set +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABEOZ9 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_ARMADA38X is not set +# CONFIG_RTC_DRV_AU1XXX is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_CADENCE is not set +CONFIG_RTC_DRV_CMOS=y +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1307_CENTURY is not set +# CONFIG_RTC_DRV_DS1307_HWMON is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_EP93XX is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_GENERIC is not set +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_JZ4740 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_MOXART is not set +# CONFIG_RTC_DRV_MPC5121 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_MT2712 is not set +# CONFIG_RTC_DRV_OMAP is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_PS3 is not set +# CONFIG_RTC_DRV_PT7C4338 is not set +# CONFIG_RTC_DRV_R7301 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_RTC7301 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV3032 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RX6110 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_SD3078 is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_SUN6I is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_XGENE is not set +# CONFIG_RTC_DRV_ZYNQMP is not set +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_LIB=y +# CONFIG_RTC_NVMEM is not set +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_RTL8192E is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTL8306_PHY is not set +# CONFIG_RTL8366RB_PHY is not set +# CONFIG_RTL8366S_PHY is not set +# CONFIG_RTL8366_SMI is not set +# CONFIG_RTL8366_SMI_DEBUG_FS is not set +# CONFIG_RTL8367B_PHY is not set +# CONFIG_RTL8367_PHY is not set +# CONFIG_RTLLIB is not set +# CONFIG_RTL_CARDS is not set +# CONFIG_RTS5208 is not set +CONFIG_RT_MUTEXES=y +# CONFIG_RUNTIME_DEBUG is not set +CONFIG_RUNTIME_TESTING_MENU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_RXKAD=y +# CONFIG_S2IO is not set +# CONFIG_SAMPLES is not set +# CONFIG_SAMSUNG_LAPTOP is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_SATA_DWC is not set +# CONFIG_SATA_FSL is not set +# CONFIG_SATA_HIGHBANK is not set +# CONFIG_SATA_HOST is not set +# CONFIG_SATA_INIC162X is not set +CONFIG_SATA_MOBILE_LPM_POLICY=0 +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PMP is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_RCAR is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SBC_FITPC2_WATCHDOG is not set +CONFIG_SBITMAP=y +# CONFIG_SC92031 is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCACHE_DEBUGFS is not set +# CONFIG_SCC is not set +# CONFIG_SCD30_CORE is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SCHED_DEBUG is not set +CONFIG_SCHED_HRTICK=y +# CONFIG_SCHED_MC is not set +CONFIG_SCHED_OMIT_FRAME_POINTER=y +# CONFIG_SCHED_SMT is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_SCR24X is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_BNX2X_FCOE is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CHELSIO_FCOE is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_FDOMAIN_PCI is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_HISI_SAS is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_ISCI is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_LPFC is not set +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVSAS_DEBUG is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_MYRB is not set +# CONFIG_SCSI_MYRS is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_PMCRAID is not set +CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_VIRTIO is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SDR_MAX2175 is not set +# CONFIG_SDR_PLATFORM_DRIVERS is not set +# CONFIG_SD_ADC_MODULATOR is not set +# CONFIG_SECCOMP is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_APPARMOR is not set +CONFIG_SECURITY_DMESG_RESTRICT=y +# CONFIG_SECURITY_LOADPIN is not set +# CONFIG_SECURITY_LOCKDOWN_LSM is not set +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_SAFESETID is not set +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 +# CONFIG_SECURITY_SELINUX_DEVELOP is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_YAMA is not set +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_SENSIRION_SGP30 is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_ACPI_POWER is not set +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 is not set +# CONFIG_SENSORS_ADM1266 is not set +# CONFIG_SENSORS_ADM1275 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_SENSORS_APPLESMC is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_ATK0110 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_BEL_PFE is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_CORETEMP is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_DELL_SMM is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FAM15H_POWER is not set +# CONFIG_SENSORS_FSCHMD is not set +# CONFIG_SENSORS_FTSTEUTATES is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_GSC is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HMC5843 is not set +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_I5500 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_IBM_CFFPS is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_INSPUR_IPSPS is not set +# CONFIG_SENSORS_IR35221 is not set +# CONFIG_SENSORS_IR38064 is not set +# CONFIG_SENSORS_IRPS5401 is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_SENSORS_ISL68137 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_K10TEMP is not set +# CONFIG_SENSORS_K8TEMP is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LM25066 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2947_SPI is not set +# CONFIG_SENSORS_LTC2978 is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC3815 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LTQ_CPUTEMP is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16064 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX16601 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX20730 is not set +# CONFIG_SENSORS_MAX20751 is not set +# CONFIG_SENSORS_MAX31722 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX31785 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MAX34440 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX8688 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_MP2975 is not set +# CONFIG_SENSORS_MR75203 is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_NSA320 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_OCC_P8_I2C is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_PMBUS is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_PXE1610 is not set +# CONFIG_SENSORS_RM3100_I2C is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_TPS40422 is not set +# CONFIG_SENSORS_TPS53679 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_SENSORS_UCD9000 is not set +# CONFIG_SENSORS_UCD9200 is not set +# CONFIG_SENSORS_VEXPRESS is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VIA_CPUTEMP is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_XDPE122 is not set +# CONFIG_SENSORS_XGENE is not set +# CONFIG_SENSORS_ZL6100 is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_16550A_VARIANTS=y +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_ASPEED_VUART is not set +# CONFIG_SERIAL_8250_BOCA is not set +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_DMA=y +# CONFIG_SERIAL_8250_DW is not set +# CONFIG_SERIAL_8250_EM is not set +# CONFIG_SERIAL_8250_EXAR is not set +# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_FINTEK is not set +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +# CONFIG_SERIAL_8250_INGENIC is not set +# CONFIG_SERIAL_8250_LPSS is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_MID is not set +# CONFIG_SERIAL_8250_MOXA is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +# CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_RSA is not set +# CONFIG_SERIAL_8250_RT288X is not set +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_BCM63XX is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_DEV_BUS is not set +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SH_SCI is not set +# CONFIG_SERIAL_SIFIVE is not set +# CONFIG_SERIAL_SPRD is not set +# CONFIG_SERIAL_STM32 is not set +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_UARTLITE is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIO is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_GPIO_PS2 is not set +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_SUN4I_PS2 is not set +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +# CONFIG_SFI is not set +# CONFIG_SFP is not set +# CONFIG_SF_PDMA is not set +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP30 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SGI_MFD_IOC3 is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SG_POOL is not set +# CONFIG_SG_SPLIT is not set +CONFIG_SHMEM=y +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +# CONFIG_SH_ETH is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_SI1133 is not set +# CONFIG_SI1145 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +CONFIG_SIGNALFD=y +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +# CONFIG_SIMPLE_GPIO is not set +# CONFIG_SIMPLE_PM_BUS is not set +# CONFIG_SIOX is not set +# CONFIG_SIS190 is not set +# CONFIG_SIS900 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SKY2_DEBUG is not set +# CONFIG_SLAB is not set +CONFIG_SLABINFO=y +# CONFIG_SLAB_FREELIST_HARDENED is not set +# CONFIG_SLAB_FREELIST_RANDOM is not set +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLHC is not set +# CONFIG_SLICOSS is not set +# CONFIG_SLIMBUS is not set +# CONFIG_SLIP is not set +# CONFIG_SLOB is not set +CONFIG_SLUB=y +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_MEMCG_SYSFS_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SMARTJOYPLUS_FF is not set +# CONFIG_SMC911X is not set +# CONFIG_SMC9194 is not set +# CONFIG_SMC91X is not set +# CONFIG_SMP is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_SMS_SDIO_DRV is not set +# CONFIG_SMS_USB_DRV is not set +# CONFIG_SM_FTL is not set +# CONFIG_SND is not set +# CONFIG_SND_AC97_POWER_SAVE is not set +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ADLIB is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_ASIHPI is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_ATMEL_AC97C is not set +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AUDIO_GRAPH_CARD is not set +# CONFIG_SND_AUDIO_GRAPH_SCU_CARD is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_BCM63XX_I2S_WHISTLER is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4236 is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS5530 is not set +# CONFIG_SND_CS5535AUDIO is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_DESIGNWARE_I2S is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_EDMA_SOC is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1688 is not set +# CONFIG_SND_ES18XX is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FIREWIRE is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDA_INTEL_DETECT_DMIC is not set +# CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM is not set +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_PREALLOC_SIZE=64 +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_HWDEP is not set +# CONFIG_SND_I2S_HI6210_I2S is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +# CONFIG_SND_ISA is not set +# CONFIG_SND_JZ4740_SOC_I2S is not set +# CONFIG_SND_KIRKWOOD_SOC is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +CONFIG_SND_MAX_CARDS=16 +# CONFIG_SND_MIA is not set +# CONFIG_SND_MIPS is not set +# CONFIG_SND_MIRO is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MPC52xx_SOC_EFIKA is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set +# CONFIG_SND_MXS_SOC is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_OPL3SA2 is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_OSSEMUL=y +# CONFIG_SND_OXYGEN is not set +CONFIG_SND_PCI=y +# CONFIG_SND_PCM is not set +# CONFIG_SND_PCMCIA is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_PCM_TIMER is not set +# CONFIG_SND_PCM_XRUN_DEBUG is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_PDAUDIOCF is not set +# CONFIG_SND_PORTMAN2X4 is not set +# CONFIG_SND_POWERPC_SOC is not set +# CONFIG_SND_PPC is not set +CONFIG_SND_PROC_FS=y +# CONFIG_SND_RAWMIDI is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_RTCTIMER is not set +# CONFIG_SND_SB16 is not set +# CONFIG_SND_SB8 is not set +# CONFIG_SND_SBAWE is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_SE6X is not set +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SND_SIMPLE_SCU_CARD is not set +# CONFIG_SND_SIS7019 is not set +# CONFIG_SND_SOC is not set +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_ADAU1761_I2C is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_ADAU7002 is not set +# CONFIG_SND_SOC_ADAU7118_HW is not set +# CONFIG_SND_SOC_ADAU7118_I2C is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4118 is not set +# CONFIG_SND_SOC_AK4458 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_AK5558 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_AMD_ACP is not set +# CONFIG_SND_SOC_AMD_ACP3x is not set +# CONFIG_SND_SOC_AMD_RENOIR is not set +# CONFIG_SND_SOC_AU1XAUDIO is not set +# CONFIG_SND_SOC_AU1XPSC is not set +# CONFIG_SND_SOC_BD28623 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS35L33 is not set +# CONFIG_SND_SOC_CS35L34 is not set +# CONFIG_SND_SOC_CS35L35 is not set +# CONFIG_SND_SOC_CS35L36 is not set +# CONFIG_SND_SOC_CS4234 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42L42 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS43130 is not set +# CONFIG_SND_SOC_CS4341 is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CS53L30 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_DA7213 is not set +# CONFIG_SND_SOC_DIO2125 is not set +# CONFIG_SND_SOC_DMIC is not set +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_EUKREA_TLV320 is not set +# CONFIG_SND_SOC_FSL_ASOC_CARD is not set +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_ICS43432 is not set +# CONFIG_SND_SOC_IMG is not set +# CONFIG_SND_SOC_IMX_AUDMIX is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_IMX_ES8328 is not set +# CONFIG_SND_SOC_IMX_SPDIF is not set +# CONFIG_SND_SOC_IMX_WM8962 is not set +# CONFIG_SND_SOC_INNO_RK3036 is not set +# CONFIG_SND_SOC_INTEL_APL is not set +# CONFIG_SND_SOC_INTEL_BAYTRAIL is not set +# CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH is not set +# CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH is not set +# CONFIG_SND_SOC_INTEL_BXT_RT298_MACH is not set +# CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH is not set +# CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH is not set +# CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH is not set +# CONFIG_SND_SOC_INTEL_CATPT is not set +# CONFIG_SND_SOC_INTEL_CFL is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH is not set +# CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH is not set +# CONFIG_SND_SOC_INTEL_CML_H is not set +# CONFIG_SND_SOC_INTEL_CML_LP is not set +# CONFIG_SND_SOC_INTEL_CNL is not set +# CONFIG_SND_SOC_INTEL_GLK is not set +# CONFIG_SND_SOC_INTEL_HASWELL is not set +# CONFIG_SND_SOC_INTEL_KBL is not set +# CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH is not set +# CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH is not set +# CONFIG_SND_SOC_INTEL_KEEMBAY is not set +# CONFIG_SND_SOC_INTEL_SKL is not set +# CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH is not set +# CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH is not set +# CONFIG_SND_SOC_INTEL_SKL_RT286_MACH is not set +# CONFIG_SND_SOC_INTEL_SKYLAKE is not set +# CONFIG_SND_SOC_INTEL_SST is not set +CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y +# CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES is not set +# CONFIG_SND_SOC_JZ4725B_CODEC is not set +# CONFIG_SND_SOC_JZ4740_CODEC is not set +# CONFIG_SND_SOC_JZ4770_CODEC is not set +# CONFIG_SND_SOC_MA120X0P is not set +# CONFIG_SND_SOC_MAX9759 is not set +# CONFIG_SND_SOC_MAX98088 is not set +# CONFIG_SND_SOC_MAX98357A is not set +# CONFIG_SND_SOC_MAX98373 is not set +# CONFIG_SND_SOC_MAX98373_I2C is not set +# CONFIG_SND_SOC_MAX98390 is not set +# CONFIG_SND_SOC_MAX98504 is not set +# CONFIG_SND_SOC_MAX9860 is not set +# CONFIG_SND_SOC_MAX9867 is not set +# CONFIG_SND_SOC_MAX98927 is not set +# CONFIG_SND_SOC_MEDIATEK is not set +# CONFIG_SND_SOC_MPC5200_AC97 is not set +# CONFIG_SND_SOC_MPC5200_I2S is not set +# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set +# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set +# CONFIG_SND_SOC_MT2701 is not set +# CONFIG_SND_SOC_MT6351 is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_MT6660 is not set +# CONFIG_SND_SOC_MT6797 is not set +# CONFIG_SND_SOC_MT8173 is not set +# CONFIG_SND_SOC_MT8183 is not set +# CONFIG_SND_SOC_MTK_BTCVSD is not set +# CONFIG_SND_SOC_NAU8540 is not set +# CONFIG_SND_SOC_NAU8810 is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_SND_SOC_NAU8824 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1789_I2C is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM179X_I2C is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_I2C is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_I2C is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_QCOM is not set +# CONFIG_SND_SOC_RK3328 is not set +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SOF_TOPLEVEL is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2305 is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS2562 is not set +# CONFIG_SND_SOC_TAS2764 is not set +# CONFIG_SND_SOC_TAS2770 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TAS5720 is not set +# CONFIG_SND_SOC_TAS6424 is not set +# CONFIG_SND_SOC_TDA7419 is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320ADCX140 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_TSCS42XX is not set +# CONFIG_SND_SOC_TSCS454 is not set +# CONFIG_SND_SOC_UDA1334 is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8524 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8782 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8974 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set +# CONFIG_SND_SOC_XILINX_I2S is not set +# CONFIG_SND_SOC_XILINX_SPDIF is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SOC_ZX_AUD96P22 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI is not set +# CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI is not set +# CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_TIMER is not set +# CONFIG_SND_TRIDENT is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_US122L is not set +# CONFIG_SND_USB_USX2Y is not set +# CONFIG_SND_USB_VARIAX is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_WAVEFRONT is not set +CONFIG_SND_X86=y +# CONFIG_SND_XEN_FRONTEND is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SNI_RM is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# CONFIG_SOCK_CGROUP_DATA is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_BRCMSTB is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_SOC_HAS_OMAP2_SDRC is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_TI is not set +# CONFIG_SOFTLOCKUP_DETECTOR is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SONYPI is not set +# CONFIG_SONY_LAPTOP is not set +# CONFIG_SOUND is not set +# CONFIG_SOUNDWIRE is not set +# CONFIG_SOUND_OSS_CORE is not set +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +# CONFIG_SOUND_PRIME is not set +# CONFIG_SP5100_TCO is not set +# CONFIG_SPARSEMEM_MANUAL is not set +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +# CONFIG_SPARSE_IRQ is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_SPEAKUP is not set +# CONFIG_SPI is not set +# CONFIG_SPINLOCK_TEST is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AU1550 is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BCM2835 is not set +# CONFIG_SPI_BCM_QSPI is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_BUTTERFLY is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_DSPI is not set +# CONFIG_SPI_FSL_ESPI is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_GPIO_OLD is not set +# CONFIG_SPI_IMG_SPFI is not set +# CONFIG_SPI_LANTIQ_SSC is not set +# CONFIG_SPI_LM70_LLP is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_SPI_MEM is not set +# CONFIG_SPI_MPC52xx is not set +# CONFIG_SPI_MPC52xx_PSC is not set +# CONFIG_SPI_MTK_QUADSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OCTEON is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_ORION is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PPC4xx is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_QCOM_QSPI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_S3C64XX is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_THUNDERX is not set +# CONFIG_SPI_TI_QSPI is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_XWAY is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_SPMI is not set +# CONFIG_SPS30 is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_SQUASHFS_EMBEDDED=y +# CONFIG_SQUASHFS_FILE_CACHE is not set +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_ZLIB is not set +# CONFIG_SQUASHFS_ZSTD is not set +# CONFIG_SRAM is not set +# CONFIG_SRF04 is not set +# CONFIG_SRF08 is not set +# CONFIG_SSB is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_PCMCIAHOST is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB_SDIOHOST is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSFDC is not set +# CONFIG_STACKPROTECTOR is not set +# CONFIG_STACKPROTECTOR_STRONG is not set +# CONFIG_STACKTRACE is not set +CONFIG_STACKTRACE_SUPPORT=y +# CONFIG_STACK_TRACER is not set +# CONFIG_STACK_VALIDATION is not set +CONFIG_STAGING=y +# CONFIG_STAGING_BOARD is not set +# CONFIG_STAGING_GASKET_FRAMEWORK is not set +# CONFIG_STAGING_MEDIA is not set +CONFIG_STANDALONE=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_STDBINUTILS=y +# CONFIG_STE10XP is not set +# CONFIG_STE_MODEM_RPROC is not set +# CONFIG_STK3310 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set +# CONFIG_STM is not set +# CONFIG_STMMAC_ETH is not set +# CONFIG_STMMAC_PCI is not set +# CONFIG_STMMAC_PLATFORM is not set +# CONFIG_STM_DUMMY is not set +# CONFIG_STM_SOURCE_CONSOLE is not set +CONFIG_STP=y +# CONFIG_STREAM_PARSER is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_STRICT_MODULE_RWX=y +# CONFIG_STRING_SELFTEST is not set +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_STX104 is not set +# CONFIG_ST_UVIS25 is not set +# CONFIG_SUN4I_GPADC is not set +# CONFIG_SUN50I_DE2_BUS is not set +# CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_SUNRPC is not set +# CONFIG_SUNRPC_DEBUG is not set +CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SURFACE_3_BUTTON is not set +# CONFIG_SUSPEND is not set +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_SWAP=y +# CONFIG_SWCONFIG is not set +# CONFIG_SWCONFIG_B53 is not set +# CONFIG_SWCONFIG_B53_MDIO_DRIVER is not set +# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set +# CONFIG_SWCONFIG_B53_SPI_DRIVER is not set +# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set +# CONFIG_SWCONFIG_LEDS is not set +# CONFIG_SW_SYNC is not set +# CONFIG_SX9310 is not set +# CONFIG_SX9500 is not set +# CONFIG_SXGBE_ETH is not set +CONFIG_SYMBOLIC_ERRNAME=y +# CONFIG_SYNCLINK_CS is not set +# CONFIG_SYNC_FILE is not set +# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set +# CONFIG_SYNTH_EVENTS is not set +CONFIG_SYN_COOKIES=y +# CONFIG_SYSCON_REBOOT_MODE is not set +CONFIG_SYSCTL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSFS=y +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_SYSV68_PARTITION is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_T5403 is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_TASKS_RCU is not set +# CONFIG_TASK_XACCT is not set +# CONFIG_TC35815 is not set +# CONFIG_TCG_ATMEL is not set +# CONFIG_TCG_CRB is not set +# CONFIG_TCG_FTPM_TEE is not set +# CONFIG_TCG_INFINEON is not set +# CONFIG_TCG_NSC is not set +# CONFIG_TCG_ST33_I2C is not set +# CONFIG_TCG_TIS is not set +# CONFIG_TCG_TIS_I2C_ATMEL is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_TIS_SPI is not set +# CONFIG_TCG_TIS_ST33ZP24_I2C is not set +# CONFIG_TCG_TIS_ST33ZP24_SPI is not set +# CONFIG_TCG_TPM is not set +# CONFIG_TCG_VTPM_PROXY is not set +# CONFIG_TCG_XEN is not set +# CONFIG_TCIC is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BBR is not set +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_CDG is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_NV is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_MD5SIG is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +# CONFIG_TEE is not set +# CONFIG_TEGRA_AHB is not set +# CONFIG_TEGRA_HOST1X is not set +# CONFIG_TEHUTI is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +# CONFIG_TEST_BITFIELD is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_KASAN_MODULE is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_LOCKUP is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_POWER is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_SORT is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UBSAN is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_XARRAY is not set +CONFIG_TEXTSEARCH=y +# CONFIG_TEXTSEARCH_BM is not set +# CONFIG_TEXTSEARCH_FSM is not set +# CONFIG_TEXTSEARCH_KMP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_THERMAL_MMIO is not set +# CONFIG_THERMAL_NETLINK is not set +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +# CONFIG_THINKPAD_ACPI is not set +CONFIG_THIN_ARCHIVES=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_THUNDERBOLT is not set +# CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_THUNDER_NIC_RGX is not set +# CONFIG_THUNDER_NIC_VF is not set +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_TICK_ONESHOT=y +# CONFIG_TIFM_CORE is not set +# CONFIG_TIGON3 is not set +# CONFIG_TIMB_DMA is not set +CONFIG_TIMERFD=y +# CONFIG_TIMER_STATS is not set +# CONFIG_TIME_NS is not set +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_ILI9486 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_ST7586 is not set +# CONFIG_TINYDRM_ST7735R is not set +CONFIG_TINY_RCU=y +# CONFIG_TIPC is not set +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_AM335X_ADC is not set +# CONFIG_TI_CPSW is not set +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TI_CPSW_PHY_SEL is not set +# CONFIG_TI_CPTS is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC5571 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_DAVINCI_CPDMA is not set +# CONFIG_TI_DAVINCI_MDIO is not set +# CONFIG_TI_ST is not set +# CONFIG_TI_SYSCON_RESET is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TLAN is not set +# CONFIG_TLS is not set +# CONFIG_TMD_HERMES is not set +# CONFIG_TMP006 is not set +# CONFIG_TMP007 is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_INODE64 is not set +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_XATTR=y +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_TOSHIBA_HAPS is not set +# CONFIG_TOUCHSCREEN_88PM860X is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AD7879_I2C is not set +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +# CONFIG_TOUCHSCREEN_ADC is not set +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT_T37 is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set +# CONFIG_TOUCHSCREEN_COLIBRI_VF50 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_I2C is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_SPI is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP_I2C is not set +# CONFIG_TOUCHSCREEN_CYTTSP_SPI is not set +# CONFIG_TOUCHSCREEN_DA9034 is not set +# CONFIG_TOUCHSCREEN_DA9052 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HP600 is not set +# CONFIG_TOUCHSCREEN_HP7XX is not set +# CONFIG_TOUCHSCREEN_HTCPEN is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_IPAQ_MICRO is not set +# CONFIG_TOUCHSCREEN_IPROC is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_LPC32XX is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MC13783 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MIGOR is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MX25 is not set +# CONFIG_TOUCHSCREEN_MXS_LRADC is not set +# CONFIG_TOUCHSCREEN_PCAP is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_PROPERTIES is not set +# CONFIG_TOUCHSCREEN_RASPBERRYPI_FW is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set +# CONFIG_TOUCHSCREEN_S3C2410 is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_STMFTS is not set +# CONFIG_TOUCHSCREEN_STMPE is not set +# CONFIG_TOUCHSCREEN_SUN4I is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TI_AM335X_TSC is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_TS4800 is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_TSC2007_IIO is not set +# CONFIG_TOUCHSCREEN_TSC200X_CORE is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_USB_3M is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_USB_DMC_TSC10 is not set +# CONFIG_TOUCHSCREEN_USB_E2I is not set +# CONFIG_TOUCHSCREEN_USB_EASYTOUCH is not set +# CONFIG_TOUCHSCREEN_USB_EGALAX is not set +# CONFIG_TOUCHSCREEN_USB_ELO is not set +# CONFIG_TOUCHSCREEN_USB_ETT_TC45USB is not set +# CONFIG_TOUCHSCREEN_USB_ETURBO is not set +# CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH is not set +# CONFIG_TOUCHSCREEN_USB_GOTOP is not set +# CONFIG_TOUCHSCREEN_USB_GUNZE is not set +# CONFIG_TOUCHSCREEN_USB_IDEALTEK is not set +# CONFIG_TOUCHSCREEN_USB_IRTOUCH is not set +# CONFIG_TOUCHSCREEN_USB_ITM is not set +# CONFIG_TOUCHSCREEN_USB_JASTEC is not set +# CONFIG_TOUCHSCREEN_USB_NEXIO is not set +# CONFIG_TOUCHSCREEN_USB_PANJIT is not set +# CONFIG_TOUCHSCREEN_USB_ZYTRONIC is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_WM831X is not set +# CONFIG_TOUCHSCREEN_WM9705 is not set +# CONFIG_TOUCHSCREEN_WM9712 is not set +# CONFIG_TOUCHSCREEN_WM9713 is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set +# CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set +# CONFIG_TPL0102 is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_TRACER_SNAPSHOT is not set +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +# CONFIG_TRACE_EVENT_INJECT is not set +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_TRACE_SINK is not set +# CONFIG_TRACING_EVENTS_GPIO is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_TRAD_SIGNALS=y +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_TREE_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set +# CONFIG_TRUSTED_FOUNDATIONS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2772 is not set +# CONFIG_TSL2x7x is not set +# CONFIG_TSL4531 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +# CONFIG_TTPCI_EEPROM is not set +CONFIG_TTY=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_TUN is not set +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL4030_MADC is not set +# CONFIG_TWL6030_GPADC is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_TYPEC is not set +# CONFIG_TYPEC_TCPM is not set +# CONFIG_TYPEC_UCSI is not set +# CONFIG_TYPHOON is not set +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_UBIFS_ATIME_SUPPORT is not set +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_AUTHENTICATION is not set +# CONFIG_UBIFS_FS_ENCRYPTION is not set +CONFIG_UBIFS_FS_LZO=y +# CONFIG_UBIFS_FS_SECURITY is not set +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y +# CONFIG_UBSAN is not set +CONFIG_UBSAN_ALIGNMENT=y +# CONFIG_UBSAN_MISC is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_UCSI is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDMABUF is not set +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_UFS_FS is not set +# CONFIG_UHID is not set +CONFIG_UID16=y +# CONFIG_UIO is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_UNICODE is not set +# CONFIG_UNISYSSPAR is not set +# CONFIG_UNISYS_VISORBUS is not set +CONFIG_UNIX=y +CONFIG_UNIX98_PTYS=y +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_UNIX_DIAG is not set +CONFIG_UNIX_SCM=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_UNWINDER_FRAME_POINTER is not set +# CONFIG_UPROBES is not set +# CONFIG_UPROBE_EVENTS is not set +# CONFIG_US5182D is not set +# CONFIG_USB is not set +# CONFIG_USB4 is not set +# CONFIG_USBIP_CORE is not set +CONFIG_USBIP_VHCI_HC_PORTS=8 +CONFIG_USBIP_VHCI_NR_HCS=1 +# CONFIG_USBIP_VUDC is not set +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AIRSPY is not set +CONFIG_USB_ALI_M5632=y +# CONFIG_USB_AMD5536UDC is not set +CONFIG_USB_AN2720=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_ATM is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +# CONFIG_USB_BDC_UDC is not set +CONFIG_USB_BELKIN=y +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_CHIPIDEA_GENERIC is not set +# CONFIG_USB_CHIPIDEA_IMX is not set +# CONFIG_USB_CHIPIDEA_MSM is not set +# CONFIG_USB_CHIPIDEA_PCI is not set +# CONFIG_USB_CHIPIDEA_TEGRA is not set +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_CONN_GPIO is not set +# CONFIG_USB_CXACRU is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DSBR is not set +# CONFIG_USB_DUMMY_HCD is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_DUAL_ROLE is not set +# CONFIG_USB_DWC2_HOST is not set +# CONFIG_USB_DWC2_PERIPHERAL is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC3_EXYNOS is not set +# CONFIG_USB_DWC3_HAPS is not set +# CONFIG_USB_DWC3_KEYSTONE is not set +# CONFIG_USB_DWC3_OF_SIMPLE is not set +# CONFIG_USB_DWC3_PCI is not set +# CONFIG_USB_DWC3_QCOM is not set +# CONFIG_USB_DWC3_ULPI is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_EHCI_ATH79 is not set +# CONFIG_USB_EHCI_FSL is not set +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_EHCI_HCD_AT91 is not set +# CONFIG_USB_EHCI_HCD_OMAP is not set +# CONFIG_USB_EHCI_HCD_PPC_OF is not set +# CONFIG_USB_EHCI_MSM is not set +# CONFIG_USB_EHCI_MV is not set +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_GADGET is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_VBUS_DRAW=2 +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_GSPCA is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TOUPTEK is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_G_NOKIA is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_HACKRF is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_HID is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IMX21_HCD is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_KC2190 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LGM_PHY is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_M5602 is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_MAX3420_UDC is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_MSI2500 is not set +# CONFIG_USB_MSM_OTG is not set +# CONFIG_USB_MTU3 is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MXS_PHY is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_NET_AQC111 is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_EEM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_CDC_NCM is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_CH9200 is not set +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_OHCI_HCD_PCI is not set +# CONFIG_USB_OHCI_HCD_PPC_OF is not set +# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set +# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_PCI is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_PHY is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_PWC_INPUT_EVDEV is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RAW_GADGET is not set +# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_RENESAS_USBHS is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_ROLES_INTEL_XHCI is not set +# CONFIG_USB_ROLE_SWITCH is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_S2255 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_DEBUG is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_F8153X is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_GARMIN is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7715_PARPORT is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SAFE_PADDED=y +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_UPD78F0730 is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_SPEEDTOUCH is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TMC is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_UEAGLEATM is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_USS720 is not set +# CONFIG_USB_VIDEO_CLASS is not set +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +# CONFIG_USB_VL600 is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set +# CONFIG_USB_XHCI_DBGCAP is not set +# CONFIG_USB_XHCI_HCD is not set +# CONFIG_USB_XHCI_MVEBU is not set +# CONFIG_USB_XHCI_PCI_RENESAS is not set +# CONFIG_USB_XUSBATM is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USELIB is not set +# CONFIG_USERFAULTFD is not set +# CONFIG_USERIO is not set +# CONFIG_USE_OF is not set +# CONFIG_UTS_NS is not set +# CONFIG_UWB is not set +# CONFIG_U_SERIAL_CONSOLE is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set +# CONFIG_VALIDATE_FS_PARSER is not set +# CONFIG_VBOXGUEST is not set +# CONFIG_VCNL3020 is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VCNL4035 is not set +# CONFIG_VDPA is not set +CONFIG_VDSO=y +# CONFIG_VEML6030 is not set +# CONFIG_VEML6070 is not set +# CONFIG_VETH is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_VF610_ADC is not set +# CONFIG_VF610_DAC is not set +# CONFIG_VFAT_FS is not set +# CONFIG_VFIO is not set +# CONFIG_VGASTATE is not set +# CONFIG_VGA_ARB is not set +# CONFIG_VGA_SWITCHEROO is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set +CONFIG_VHOST_MENU=y +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_VSOCK is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_VIDEO_AD5820 is not set +# CONFIG_VIDEO_AD9389B is not set +# CONFIG_VIDEO_ADP1653 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7511 is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_AK7375 is not set +# CONFIG_VIDEO_AK881X is not set +# CONFIG_VIDEO_AM437X_VPFE is not set +# CONFIG_VIDEO_ASPEED is not set +# CONFIG_VIDEO_ATMEL_ISC is not set +# CONFIG_VIDEO_ATMEL_ISI is not set +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_CADENCE is not set +# CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_VIDEO_CS3308 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_DM6446_CCDC is not set +# CONFIG_VIDEO_DT3155 is not set +# CONFIG_VIDEO_DW9714 is not set +# CONFIG_VIDEO_DW9768 is not set +# CONFIG_VIDEO_DW9807_VCM is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_ET8EK8 is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_HI556 is not set +# CONFIG_VIDEO_I2C is not set +# CONFIG_VIDEO_IMX214 is not set +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_IMX258 is not set +# CONFIG_VIDEO_IMX274 is not set +# CONFIG_VIDEO_IMX290 is not set +# CONFIG_VIDEO_IMX319 is not set +# CONFIG_VIDEO_IMX355 is not set +# CONFIG_VIDEO_IMX477 is not set +# CONFIG_VIDEO_IRS1125 is not set +# CONFIG_VIDEO_IR_I2C is not set +# CONFIG_VIDEO_IVTV is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_LM3560 is not set +# CONFIG_VIDEO_LM3646 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_M5MOLS is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_MT9M001 is not set +# CONFIG_VIDEO_MT9M032 is not set +# CONFIG_VIDEO_MT9M111 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T001 is not set +# CONFIG_VIDEO_MT9T112 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_MT9V111 is not set +# CONFIG_VIDEO_MUX is not set +# CONFIG_VIDEO_MXB is not set +# CONFIG_VIDEO_NOON010PC30 is not set +# CONFIG_VIDEO_OMAP2_VOUT is not set +# CONFIG_VIDEO_OV13858 is not set +# CONFIG_VIDEO_OV2640 is not set +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV2680 is not set +# CONFIG_VIDEO_OV2685 is not set +# CONFIG_VIDEO_OV2740 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV5670 is not set +# CONFIG_VIDEO_OV5675 is not set +# CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV6650 is not set +# CONFIG_VIDEO_OV7251 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV772X is not set +# CONFIG_VIDEO_OV7740 is not set +# CONFIG_VIDEO_OV8856 is not set +# CONFIG_VIDEO_OV9281 is not set +# CONFIG_VIDEO_OV9640 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_RDACM20 is not set +# CONFIG_VIDEO_RJ54N1 is not set +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_VIDEO_S5K4ECGX is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_S5K6AA is not set +# CONFIG_VIDEO_SAA6588 is not set +# CONFIG_VIDEO_SAA6752HS is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +# CONFIG_VIDEO_SMIAPP is not set +# CONFIG_VIDEO_SONY_BTF_MPX is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_STK1160_COMMON is not set +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TDA1997X is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_THS8200 is not set +# CONFIG_VIDEO_TIMBERDALE is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_TM6000 is not set +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_TW2804 is not set +# CONFIG_VIDEO_TW9903 is not set +# CONFIG_VIDEO_TW9906 is not set +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_UDA1342 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# CONFIG_VIDEO_USBTV is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_VIDEO_V4L2 is not set +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_VPX3220 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_XILINX is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_BLK_SCSI is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_VIRTIO_FS is not set +# CONFIG_VIRTIO_INPUT is not set +CONFIG_VIRTIO_MENU=y +# CONFIG_VIRTIO_MMIO is not set +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTUALIZATION is not set +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRT_TO_BUS=y +# CONFIG_VITESSE_PHY is not set +# CONFIG_VL53L0X_I2C is not set +# CONFIG_VL6180 is not set +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_VME_BUS is not set +# CONFIG_VMSPLIT_1G is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_2G_OPT is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_3G_OPT is not set +# CONFIG_VMWARE_PVSCSI is not set +# CONFIG_VMXNET3 is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_VOP_BUS is not set +# CONFIG_VORTEX is not set +# CONFIG_VSOCKETS is not set +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VT is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set +# CONFIG_VXFS_FS is not set +# CONFIG_VXGE is not set +# CONFIG_VXLAN is not set +# CONFIG_VZ89X is not set +# CONFIG_W1 is not set +# CONFIG_W1_CON is not set +# CONFIG_W1_MASTER_DS1WM is not set +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_DS2490 is not set +# CONFIG_W1_MASTER_GPIO is not set +# CONFIG_W1_MASTER_MATROX is not set +# CONFIG_W1_MASTER_SGI is not set +# CONFIG_W1_SLAVE_DS2405 is not set +# CONFIG_W1_SLAVE_DS2406 is not set +# CONFIG_W1_SLAVE_DS2408 is not set +# CONFIG_W1_SLAVE_DS2413 is not set +# CONFIG_W1_SLAVE_DS2423 is not set +# CONFIG_W1_SLAVE_DS2430 is not set +# CONFIG_W1_SLAVE_DS2431 is not set +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2438 is not set +# CONFIG_W1_SLAVE_DS250X is not set +# CONFIG_W1_SLAVE_DS2780 is not set +# CONFIG_W1_SLAVE_DS2781 is not set +# CONFIG_W1_SLAVE_DS2805 is not set +# CONFIG_W1_SLAVE_DS28E04 is not set +# CONFIG_W1_SLAVE_DS28E17 is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W83627HF_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_W83977F_WDT is not set +# CONFIG_WAN is not set +# CONFIG_WANXL is not set +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +# CONFIG_WATCHDOG_SYSFS is not set +# CONFIG_WATCH_QUEUE is not set +# CONFIG_WD80x3 is not set +# CONFIG_WDAT_WDT is not set +# CONFIG_WDTPCI is not set +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PRIV=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WILINK_PLATFORM_DATA=y +# CONFIG_WIMAX is not set +# CONFIG_WIREGUARD is not set +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_WDS is not set +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_WL1251 is not set +# CONFIG_WL12XX is not set +# CONFIG_WL18XX is not set +CONFIG_WLAN=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLCORE is not set +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_X25 is not set +# CONFIG_X509_CERTIFICATE_PARSER is not set +# CONFIG_X86_PKG_TEMP_THERMAL is not set +CONFIG_X86_SYSFB=y +# CONFIG_XDP_SOCKETS is not set +# CONFIG_XEN is not set +# CONFIG_XEN_GRANT_DMA_ALLOC is not set +# CONFIG_XEN_PVCALLS_FRONTEND is not set +CONFIG_XEN_SCRUB_PAGES_DEFAULT=y +CONFIG_XFRM=y +# CONFIG_XFRM_INTERFACE is not set +# CONFIG_XFRM_IPCOMP is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_USER is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_ONLINE_SCRUB is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_SUPPORT_V4 is not set +# CONFIG_XFS_WARN is not set +# CONFIG_XILINX_AXI_EMAC is not set +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_EMACLITE is not set +# CONFIG_XILINX_GMII2RGMII is not set +# CONFIG_XILINX_LL_TEMAC is not set +# CONFIG_XILINX_SDFEC is not set +# CONFIG_XILINX_VCU is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_XILINX_XADC is not set +# CONFIG_XILINX_ZYNQMP_DMA is not set +# CONFIG_XILINX_ZYNQMP_DPDMA is not set +# CONFIG_XILLYBUS is not set +# CONFIG_XIL_AXIS_FIFO is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_XMON is not set +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_BCJ is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_SPARC is not set +# CONFIG_XZ_DEC_TEST is not set +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_YAM is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_YENTA is not set +# CONFIG_YENTA_O2 is not set +# CONFIG_YENTA_RICOH is not set +# CONFIG_YENTA_TI is not set +# CONFIG_YENTA_TOSHIBA is not set +# CONFIG_ZBUD is not set +# CONFIG_ZD1211RW is not set +# CONFIG_ZD1211RW_DEBUG is not set +# CONFIG_ZEROPLUS_FF is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +# CONFIG_ZISOFS is not set +# CONFIG_ZLIB_DEFLATE is not set +# CONFIG_ZLIB_INFLATE is not set +CONFIG_ZONE_DMA=y +# CONFIG_ZOPT2201 is not set +# CONFIG_ZPA2326 is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZRAM is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_ZSMALLOC is not set +# CONFIG_ZX_TDM is not set diff --git a/target/linux/generic/hack-5.15/204-module_strip.patch b/target/linux/generic/hack-5.15/204-module_strip.patch new file mode 100644 index 0000000000..645074821f --- /dev/null +++ b/target/linux/generic/hack-5.15/204-module_strip.patch @@ -0,0 +1,212 @@ +From a779a482fb9b9f8fcdf8b2519c789b4b9bb5dd05 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 16:56:48 +0200 +Subject: build: add a hack for removing non-essential module info + +Signed-off-by: Felix Fietkau +--- + include/linux/module.h | 13 ++++++++----- + include/linux/moduleparam.h | 15 ++++++++++++--- + init/Kconfig | 7 +++++++ + kernel/module.c | 5 ++++- + scripts/mod/modpost.c | 12 ++++++++++++ + 5 files changed, 43 insertions(+), 9 deletions(-) + +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -161,6 +161,7 @@ extern void cleanup_module(void); + + /* Generic info of form tag = "info" */ + #define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info) ++#define MODULE_INFO_STRIP(tag, info) __MODULE_INFO_STRIP(tag, tag, info) + + /* For userspace: you can also call me... */ + #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) +@@ -230,12 +231,12 @@ extern void cleanup_module(void); + * Author(s), use "Name " or just "Name", for multiple + * authors use multiple MODULE_AUTHOR() statements/lines. + */ +-#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) ++#define MODULE_AUTHOR(_author) MODULE_INFO_STRIP(author, _author) + + /* What your module does. */ +-#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description) ++#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description) + +-#ifdef MODULE ++#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED) + /* Creates an alias so file2alias.c can find device table. */ + #define MODULE_DEVICE_TABLE(type, name) \ + extern typeof(name) __mod_##type##__##name##_device_table \ +@@ -262,7 +263,9 @@ extern typeof(name) __mod_##type##__##na + */ + + #if defined(MODULE) || !defined(CONFIG_SYSFS) +-#define MODULE_VERSION(_version) MODULE_INFO(version, _version) ++#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version) ++#elif defined(CONFIG_MODULE_STRIPPED) ++#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version) + #else + #define MODULE_VERSION(_version) \ + MODULE_INFO(version, _version); \ +@@ -285,7 +288,7 @@ extern typeof(name) __mod_##type##__##na + /* Optional firmware file (or files) needed by the module + * format is simply firmware file name. Multiple firmware + * files require multiple MODULE_FIRMWARE() specifiers */ +-#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware) ++#define MODULE_FIRMWARE(_firmware) MODULE_INFO_STRIP(firmware, _firmware) + + #define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, #ns) + +--- a/include/linux/moduleparam.h ++++ b/include/linux/moduleparam.h +@@ -20,6 +20,16 @@ + /* Chosen so that structs with an unsigned long line up. */ + #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) + ++/* This struct is here for syntactic coherency, it is not used */ ++#define __MODULE_INFO_DISABLED(name) \ ++ struct __UNIQUE_ID(name) {} ++ ++#ifdef CONFIG_MODULE_STRIPPED ++#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name) ++#else ++#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info) ++#endif ++ + #define __MODULE_INFO(tag, name, info) \ + static const char __UNIQUE_ID(name)[] \ + __used __section(".modinfo") __attribute__((unused, aligned(1))) \ +@@ -31,7 +41,7 @@ static const char __UNIQUE_ID(name)[] + /* One for each parameter, describing how to use it. Some files do + multiple of these per line, so can't just use MODULE_INFO. */ + #define MODULE_PARM_DESC(_parm, desc) \ +- __MODULE_INFO(parm, _parm, #_parm ":" desc) ++ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc) + + struct kernel_param; + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -2347,6 +2347,13 @@ config UNUSED_KSYMS_WHITELIST + one per line. The path can be absolute, or relative to the kernel + source tree. + ++config MODULE_STRIPPED ++ bool "Reduce module size" ++ depends on MODULES ++ help ++ Remove module parameter descriptions, author info, version, aliases, ++ device tables, etc. ++ + endif # MODULES + + config MODULES_TREE_LOOKUP +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -1285,6 +1285,7 @@ static struct module_attribute *modinfo_ + + static const char vermagic[] = VERMAGIC_STRING; + ++#if defined(CONFIG_MODVERSIONS) || !defined(CONFIG_MODULE_STRIPPED) + static int try_to_force_load(struct module *mod, const char *reason) + { + #ifdef CONFIG_MODULE_FORCE_LOAD +@@ -1296,6 +1297,7 @@ static int try_to_force_load(struct modu + return -ENOEXEC; + #endif + } ++#endif + + #ifdef CONFIG_MODVERSIONS + +@@ -3247,9 +3249,11 @@ static int setup_load_info(struct load_i + + static int check_modinfo(struct module *mod, struct load_info *info, int flags) + { +- const char *modmagic = get_modinfo(info, "vermagic"); + int err; + ++#ifndef CONFIG_MODULE_STRIPPED ++ const char *modmagic = get_modinfo(info, "vermagic"); ++ + if (flags & MODULE_INIT_IGNORE_VERMAGIC) + modmagic = NULL; + +@@ -3270,6 +3274,7 @@ static int check_modinfo(struct module * + mod->name); + add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); + } ++#endif + + check_modinfo_retpoline(mod, info); + +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -2037,7 +2037,9 @@ static void read_symbols(const char *mod + symname = remove_dot(info.strtab + sym->st_name); + + handle_symbol(mod, &info, sym, symname); ++#ifndef CONFIG_MODULE_STRIPPED + handle_moddevtable(mod, &info, sym, symname); ++#endif + } + + for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { +@@ -2250,8 +2252,10 @@ static void add_header(struct buffer *b, + buf_printf(b, "\n"); + buf_printf(b, "BUILD_SALT;\n"); + buf_printf(b, "\n"); ++#ifndef CONFIG_MODULE_STRIPPED + buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); + buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n"); ++#endif + buf_printf(b, "\n"); + buf_printf(b, "__visible struct module __this_module\n"); + buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n"); +@@ -2268,8 +2272,10 @@ static void add_header(struct buffer *b, + + static void add_intree_flag(struct buffer *b, int is_intree) + { ++#ifndef CONFIG_MODULE_STRIPPED + if (is_intree) + buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); ++#endif + } + + /* Cannot check for assembler */ +@@ -2282,8 +2288,10 @@ static void add_retpoline(struct buffer + + static void add_staging_flag(struct buffer *b, const char *name) + { ++#ifndef CONFIG_MODULE_STRIPPED + if (strstarts(name, "drivers/staging")) + buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); ++#endif + } + + /** +@@ -2367,11 +2375,13 @@ static void add_depends(struct buffer *b + + static void add_srcversion(struct buffer *b, struct module *mod) + { ++#ifndef CONFIG_MODULE_STRIPPED + if (mod->srcversion[0]) { + buf_printf(b, "\n"); + buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", + mod->srcversion); + } ++#endif + } + + static void write_buf(struct buffer *b, const char *fname) +@@ -2630,7 +2640,9 @@ int main(int argc, char **argv) + add_staging_flag(&buf, mod->name); + err |= add_versions(&buf, mod); + add_depends(&buf, mod); ++#ifndef CONFIG_MODULE_STRIPPED + add_moddevtable(&buf, mod); ++#endif + add_srcversion(&buf, mod); + + sprintf(fname, "%s.mod.c", mod->name); diff --git a/target/linux/generic/hack-5.15/205-kconfig-exit.patch b/target/linux/generic/hack-5.15/205-kconfig-exit.patch new file mode 100644 index 0000000000..c3fb7a1f99 --- /dev/null +++ b/target/linux/generic/hack-5.15/205-kconfig-exit.patch @@ -0,0 +1,11 @@ +--- a/scripts/kconfig/conf.c ++++ b/scripts/kconfig/conf.c +@@ -215,6 +215,8 @@ static int conf_sym(struct menu *menu) + break; + continue; + case 0: ++ if (!sym_has_value(sym) && !tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) ++ exit(1); + newval = oldval; + break; + case '?': diff --git a/target/linux/generic/hack-5.15/210-darwin_scripts_include.patch b/target/linux/generic/hack-5.15/210-darwin_scripts_include.patch new file mode 100644 index 0000000000..be6adc0d11 --- /dev/null +++ b/target/linux/generic/hack-5.15/210-darwin_scripts_include.patch @@ -0,0 +1,3053 @@ +From db7c30dcd9a0391bf13b62c9f91e144d762ef43a Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Fri, 7 Jul 2017 17:00:49 +0200 +Subject: Add an OSX specific patch to make the kernel be compiled + +lede-commit: 3fc2a24f0422b2f55f9ed43f116db3111f700526 +Signed-off-by: Florian Fainelli +--- + scripts/kconfig/Makefile | 3 + + scripts/mod/elf.h | 3007 ++++++++++++++++++++++++++++++++++++++++++++ + scripts/mod/mk_elfconfig.c | 4 + + scripts/mod/modpost.h | 4 + + 4 files changed, 3018 insertions(+) + create mode 100644 scripts/mod/elf.h + +--- /dev/null ++++ b/scripts/mod/elf.h +@@ -0,0 +1,3007 @@ ++/* This file defines standard ELF types, structures, and macros. ++ Copyright (C) 1995-2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _ELF_H ++#define _ELF_H 1 ++ ++/* Standard ELF types. */ ++ ++#include ++ ++/* Type for a 16-bit quantity. */ ++typedef uint16_t Elf32_Half; ++typedef uint16_t Elf64_Half; ++ ++/* Types for signed and unsigned 32-bit quantities. */ ++typedef uint32_t Elf32_Word; ++typedef int32_t Elf32_Sword; ++typedef uint32_t Elf64_Word; ++typedef int32_t Elf64_Sword; ++ ++/* Types for signed and unsigned 64-bit quantities. */ ++typedef uint64_t Elf32_Xword; ++typedef int64_t Elf32_Sxword; ++typedef uint64_t Elf64_Xword; ++typedef int64_t Elf64_Sxword; ++ ++/* Type of addresses. */ ++typedef uint32_t Elf32_Addr; ++typedef uint64_t Elf64_Addr; ++ ++/* Type of file offsets. */ ++typedef uint32_t Elf32_Off; ++typedef uint64_t Elf64_Off; ++ ++/* Type for section indices, which are 16-bit quantities. */ ++typedef uint16_t Elf32_Section; ++typedef uint16_t Elf64_Section; ++ ++/* Type for version symbol information. */ ++typedef Elf32_Half Elf32_Versym; ++typedef Elf64_Half Elf64_Versym; ++ ++ ++/* The ELF file header. This appears at the start of every ELF file. */ ++ ++#define EI_NIDENT (16) ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ ++ Elf32_Half e_type; /* Object file type */ ++ Elf32_Half e_machine; /* Architecture */ ++ Elf32_Word e_version; /* Object file version */ ++ Elf32_Addr e_entry; /* Entry point virtual address */ ++ Elf32_Off e_phoff; /* Program header table file offset */ ++ Elf32_Off e_shoff; /* Section header table file offset */ ++ Elf32_Word e_flags; /* Processor-specific flags */ ++ Elf32_Half e_ehsize; /* ELF header size in bytes */ ++ Elf32_Half e_phentsize; /* Program header table entry size */ ++ Elf32_Half e_phnum; /* Program header table entry count */ ++ Elf32_Half e_shentsize; /* Section header table entry size */ ++ Elf32_Half e_shnum; /* Section header table entry count */ ++ Elf32_Half e_shstrndx; /* Section header string table index */ ++} Elf32_Ehdr; ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ ++ Elf64_Half e_type; /* Object file type */ ++ Elf64_Half e_machine; /* Architecture */ ++ Elf64_Word e_version; /* Object file version */ ++ Elf64_Addr e_entry; /* Entry point virtual address */ ++ Elf64_Off e_phoff; /* Program header table file offset */ ++ Elf64_Off e_shoff; /* Section header table file offset */ ++ Elf64_Word e_flags; /* Processor-specific flags */ ++ Elf64_Half e_ehsize; /* ELF header size in bytes */ ++ Elf64_Half e_phentsize; /* Program header table entry size */ ++ Elf64_Half e_phnum; /* Program header table entry count */ ++ Elf64_Half e_shentsize; /* Section header table entry size */ ++ Elf64_Half e_shnum; /* Section header table entry count */ ++ Elf64_Half e_shstrndx; /* Section header string table index */ ++} Elf64_Ehdr; ++ ++/* Fields in the e_ident array. The EI_* macros are indices into the ++ array. The macros under each EI_* macro are the values the byte ++ may have. */ ++ ++#define EI_MAG0 0 /* File identification byte 0 index */ ++#define ELFMAG0 0x7f /* Magic number byte 0 */ ++ ++#define EI_MAG1 1 /* File identification byte 1 index */ ++#define ELFMAG1 'E' /* Magic number byte 1 */ ++ ++#define EI_MAG2 2 /* File identification byte 2 index */ ++#define ELFMAG2 'L' /* Magic number byte 2 */ ++ ++#define EI_MAG3 3 /* File identification byte 3 index */ ++#define ELFMAG3 'F' /* Magic number byte 3 */ ++ ++/* Conglomeration of the identification bytes, for easy testing as a word. */ ++#define ELFMAG "\177ELF" ++#define SELFMAG 4 ++ ++#define EI_CLASS 4 /* File class byte index */ ++#define ELFCLASSNONE 0 /* Invalid class */ ++#define ELFCLASS32 1 /* 32-bit objects */ ++#define ELFCLASS64 2 /* 64-bit objects */ ++#define ELFCLASSNUM 3 ++ ++#define EI_DATA 5 /* Data encoding byte index */ ++#define ELFDATANONE 0 /* Invalid data encoding */ ++#define ELFDATA2LSB 1 /* 2's complement, little endian */ ++#define ELFDATA2MSB 2 /* 2's complement, big endian */ ++#define ELFDATANUM 3 ++ ++#define EI_VERSION 6 /* File version byte index */ ++ /* Value must be EV_CURRENT */ ++ ++#define EI_OSABI 7 /* OS ABI identification */ ++#define ELFOSABI_NONE 0 /* UNIX System V ABI */ ++#define ELFOSABI_SYSV 0 /* Alias. */ ++#define ELFOSABI_HPUX 1 /* HP-UX */ ++#define ELFOSABI_NETBSD 2 /* NetBSD. */ ++#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ ++#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ ++#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ ++#define ELFOSABI_AIX 7 /* IBM AIX. */ ++#define ELFOSABI_IRIX 8 /* SGI Irix. */ ++#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ ++#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ ++#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ ++#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ ++#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ ++#define ELFOSABI_ARM 97 /* ARM */ ++#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ ++ ++#define EI_ABIVERSION 8 /* ABI version */ ++ ++#define EI_PAD 9 /* Byte index of padding bytes */ ++ ++/* Legal values for e_type (object file type). */ ++ ++#define ET_NONE 0 /* No file type */ ++#define ET_REL 1 /* Relocatable file */ ++#define ET_EXEC 2 /* Executable file */ ++#define ET_DYN 3 /* Shared object file */ ++#define ET_CORE 4 /* Core file */ ++#define ET_NUM 5 /* Number of defined types */ ++#define ET_LOOS 0xfe00 /* OS-specific range start */ ++#define ET_HIOS 0xfeff /* OS-specific range end */ ++#define ET_LOPROC 0xff00 /* Processor-specific range start */ ++#define ET_HIPROC 0xffff /* Processor-specific range end */ ++ ++/* Legal values for e_machine (architecture). */ ++ ++#define EM_NONE 0 /* No machine */ ++#define EM_M32 1 /* AT&T WE 32100 */ ++#define EM_SPARC 2 /* SUN SPARC */ ++#define EM_386 3 /* Intel 80386 */ ++#define EM_68K 4 /* Motorola m68k family */ ++#define EM_88K 5 /* Motorola m88k family */ ++#define EM_860 7 /* Intel 80860 */ ++#define EM_MIPS 8 /* MIPS R3000 big-endian */ ++#define EM_S370 9 /* IBM System/370 */ ++#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ ++ ++#define EM_PARISC 15 /* HPPA */ ++#define EM_VPP500 17 /* Fujitsu VPP500 */ ++#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ ++#define EM_960 19 /* Intel 80960 */ ++#define EM_PPC 20 /* PowerPC */ ++#define EM_PPC64 21 /* PowerPC 64-bit */ ++#define EM_S390 22 /* IBM S390 */ ++ ++#define EM_V800 36 /* NEC V800 series */ ++#define EM_FR20 37 /* Fujitsu FR20 */ ++#define EM_RH32 38 /* TRW RH-32 */ ++#define EM_RCE 39 /* Motorola RCE */ ++#define EM_ARM 40 /* ARM */ ++#define EM_FAKE_ALPHA 41 /* Digital Alpha */ ++#define EM_SH 42 /* Hitachi SH */ ++#define EM_SPARCV9 43 /* SPARC v9 64-bit */ ++#define EM_TRICORE 44 /* Siemens Tricore */ ++#define EM_ARC 45 /* Argonaut RISC Core */ ++#define EM_H8_300 46 /* Hitachi H8/300 */ ++#define EM_H8_300H 47 /* Hitachi H8/300H */ ++#define EM_H8S 48 /* Hitachi H8S */ ++#define EM_H8_500 49 /* Hitachi H8/500 */ ++#define EM_IA_64 50 /* Intel Merced */ ++#define EM_MIPS_X 51 /* Stanford MIPS-X */ ++#define EM_COLDFIRE 52 /* Motorola Coldfire */ ++#define EM_68HC12 53 /* Motorola M68HC12 */ ++#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ ++#define EM_PCP 55 /* Siemens PCP */ ++#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ ++#define EM_NDR1 57 /* Denso NDR1 microprocessor */ ++#define EM_STARCORE 58 /* Motorola Start*Core processor */ ++#define EM_ME16 59 /* Toyota ME16 processor */ ++#define EM_ST100 60 /* STMicroelectronic ST100 processor */ ++#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ ++#define EM_X86_64 62 /* AMD x86-64 architecture */ ++#define EM_PDSP 63 /* Sony DSP Processor */ ++ ++#define EM_FX66 66 /* Siemens FX66 microcontroller */ ++#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ ++#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ ++#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ ++#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ ++#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ ++#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ ++#define EM_SVX 73 /* Silicon Graphics SVx */ ++#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ ++#define EM_VAX 75 /* Digital VAX */ ++#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ ++#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ ++#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ ++#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ ++#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ ++#define EM_HUANY 81 /* Harvard University machine-independent object files */ ++#define EM_PRISM 82 /* SiTera Prism */ ++#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ ++#define EM_FR30 84 /* Fujitsu FR30 */ ++#define EM_D10V 85 /* Mitsubishi D10V */ ++#define EM_D30V 86 /* Mitsubishi D30V */ ++#define EM_V850 87 /* NEC v850 */ ++#define EM_M32R 88 /* Mitsubishi M32R */ ++#define EM_MN10300 89 /* Matsushita MN10300 */ ++#define EM_MN10200 90 /* Matsushita MN10200 */ ++#define EM_PJ 91 /* picoJava */ ++#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ ++#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ ++#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ ++#define EM_TILEPRO 188 /* Tilera TILEPro */ ++#define EM_TILEGX 191 /* Tilera TILE-Gx */ ++#define EM_NUM 192 ++ ++/* If it is necessary to assign new unofficial EM_* values, please ++ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the ++ chances of collision with official or non-GNU unofficial values. */ ++ ++#define EM_ALPHA 0x9026 ++ ++/* Legal values for e_version (version). */ ++ ++#define EV_NONE 0 /* Invalid ELF version */ ++#define EV_CURRENT 1 /* Current version */ ++#define EV_NUM 2 ++ ++/* Section header. */ ++ ++typedef struct ++{ ++ Elf32_Word sh_name; /* Section name (string tbl index) */ ++ Elf32_Word sh_type; /* Section type */ ++ Elf32_Word sh_flags; /* Section flags */ ++ Elf32_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf32_Off sh_offset; /* Section file offset */ ++ Elf32_Word sh_size; /* Section size in bytes */ ++ Elf32_Word sh_link; /* Link to another section */ ++ Elf32_Word sh_info; /* Additional section information */ ++ Elf32_Word sh_addralign; /* Section alignment */ ++ Elf32_Word sh_entsize; /* Entry size if section holds table */ ++} Elf32_Shdr; ++ ++typedef struct ++{ ++ Elf64_Word sh_name; /* Section name (string tbl index) */ ++ Elf64_Word sh_type; /* Section type */ ++ Elf64_Xword sh_flags; /* Section flags */ ++ Elf64_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf64_Off sh_offset; /* Section file offset */ ++ Elf64_Xword sh_size; /* Section size in bytes */ ++ Elf64_Word sh_link; /* Link to another section */ ++ Elf64_Word sh_info; /* Additional section information */ ++ Elf64_Xword sh_addralign; /* Section alignment */ ++ Elf64_Xword sh_entsize; /* Entry size if section holds table */ ++} Elf64_Shdr; ++ ++/* Special section indices. */ ++ ++#define SHN_UNDEF 0 /* Undefined section */ ++#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ ++#define SHN_LOPROC 0xff00 /* Start of processor-specific */ ++#define SHN_BEFORE 0xff00 /* Order section before all others ++ (Solaris). */ ++#define SHN_AFTER 0xff01 /* Order section after all others ++ (Solaris). */ ++#define SHN_HIPROC 0xff1f /* End of processor-specific */ ++#define SHN_LOOS 0xff20 /* Start of OS-specific */ ++#define SHN_HIOS 0xff3f /* End of OS-specific */ ++#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ ++#define SHN_COMMON 0xfff2 /* Associated symbol is common */ ++#define SHN_XINDEX 0xffff /* Index is in extra table. */ ++#define SHN_HIRESERVE 0xffff /* End of reserved indices */ ++ ++/* Legal values for sh_type (section type). */ ++ ++#define SHT_NULL 0 /* Section header table entry unused */ ++#define SHT_PROGBITS 1 /* Program data */ ++#define SHT_SYMTAB 2 /* Symbol table */ ++#define SHT_STRTAB 3 /* String table */ ++#define SHT_RELA 4 /* Relocation entries with addends */ ++#define SHT_HASH 5 /* Symbol hash table */ ++#define SHT_DYNAMIC 6 /* Dynamic linking information */ ++#define SHT_NOTE 7 /* Notes */ ++#define SHT_NOBITS 8 /* Program space with no data (bss) */ ++#define SHT_REL 9 /* Relocation entries, no addends */ ++#define SHT_SHLIB 10 /* Reserved */ ++#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ ++#define SHT_INIT_ARRAY 14 /* Array of constructors */ ++#define SHT_FINI_ARRAY 15 /* Array of destructors */ ++#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ ++#define SHT_GROUP 17 /* Section group */ ++#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ ++#define SHT_NUM 19 /* Number of defined types. */ ++#define SHT_LOOS 0x60000000 /* Start OS-specific. */ ++#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ ++#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ ++#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ ++#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ ++#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ ++#define SHT_SUNW_move 0x6ffffffa ++#define SHT_SUNW_COMDAT 0x6ffffffb ++#define SHT_SUNW_syminfo 0x6ffffffc ++#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ ++#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ ++#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ ++#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ ++#define SHT_HIOS 0x6fffffff /* End OS-specific type */ ++#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ ++#define SHT_LOUSER 0x80000000 /* Start of application-specific */ ++#define SHT_HIUSER 0x8fffffff /* End of application-specific */ ++ ++/* Legal values for sh_flags (section flags). */ ++ ++#define SHF_WRITE (1 << 0) /* Writable */ ++#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ ++#define SHF_EXECINSTR (1 << 2) /* Executable */ ++#define SHF_MERGE (1 << 4) /* Might be merged */ ++#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ ++#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ ++#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ ++#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling ++ required */ ++#define SHF_GROUP (1 << 9) /* Section is member of a group. */ ++#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ ++#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ ++#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ ++#define SHF_ORDERED (1 << 30) /* Special ordering requirement ++ (Solaris). */ ++#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless ++ referenced or allocated (Solaris).*/ ++ ++/* Section group handling. */ ++#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ ++ ++/* Symbol table entry. */ ++ ++typedef struct ++{ ++ Elf32_Word st_name; /* Symbol name (string tbl index) */ ++ Elf32_Addr st_value; /* Symbol value */ ++ Elf32_Word st_size; /* Symbol size */ ++ unsigned char st_info; /* Symbol type and binding */ ++ unsigned char st_other; /* Symbol visibility */ ++ Elf32_Section st_shndx; /* Section index */ ++} Elf32_Sym; ++ ++typedef struct ++{ ++ Elf64_Word st_name; /* Symbol name (string tbl index) */ ++ unsigned char st_info; /* Symbol type and binding */ ++ unsigned char st_other; /* Symbol visibility */ ++ Elf64_Section st_shndx; /* Section index */ ++ Elf64_Addr st_value; /* Symbol value */ ++ Elf64_Xword st_size; /* Symbol size */ ++} Elf64_Sym; ++ ++/* The syminfo section if available contains additional information about ++ every dynamic symbol. */ ++ ++typedef struct ++{ ++ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ ++ Elf32_Half si_flags; /* Per symbol flags */ ++} Elf32_Syminfo; ++ ++typedef struct ++{ ++ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ ++ Elf64_Half si_flags; /* Per symbol flags */ ++} Elf64_Syminfo; ++ ++/* Possible values for si_boundto. */ ++#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ ++#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ ++#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ ++ ++/* Possible bitmasks for si_flags. */ ++#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ ++#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ ++#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ ++#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy ++ loaded */ ++/* Syminfo version values. */ ++#define SYMINFO_NONE 0 ++#define SYMINFO_CURRENT 1 ++#define SYMINFO_NUM 2 ++ ++ ++/* How to extract and insert information held in the st_info field. */ ++ ++#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) ++#define ELF32_ST_TYPE(val) ((val) & 0xf) ++#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) ++ ++/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ ++#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) ++#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) ++#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) ++ ++/* Legal values for ST_BIND subfield of st_info (symbol binding). */ ++ ++#define STB_LOCAL 0 /* Local symbol */ ++#define STB_GLOBAL 1 /* Global symbol */ ++#define STB_WEAK 2 /* Weak symbol */ ++#define STB_NUM 3 /* Number of defined types. */ ++#define STB_LOOS 10 /* Start of OS-specific */ ++#define STB_GNU_UNIQUE 10 /* Unique symbol. */ ++#define STB_HIOS 12 /* End of OS-specific */ ++#define STB_LOPROC 13 /* Start of processor-specific */ ++#define STB_HIPROC 15 /* End of processor-specific */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_NOTYPE 0 /* Symbol type is unspecified */ ++#define STT_OBJECT 1 /* Symbol is a data object */ ++#define STT_FUNC 2 /* Symbol is a code object */ ++#define STT_SECTION 3 /* Symbol associated with a section */ ++#define STT_FILE 4 /* Symbol's name is file name */ ++#define STT_COMMON 5 /* Symbol is a common data object */ ++#define STT_TLS 6 /* Symbol is thread-local data object*/ ++#define STT_NUM 7 /* Number of defined types. */ ++#define STT_LOOS 10 /* Start of OS-specific */ ++#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ ++#define STT_HIOS 12 /* End of OS-specific */ ++#define STT_LOPROC 13 /* Start of processor-specific */ ++#define STT_HIPROC 15 /* End of processor-specific */ ++ ++ ++/* Symbol table indices are found in the hash buckets and chain table ++ of a symbol hash table section. This special index value indicates ++ the end of a chain, meaning no further symbols are found in that bucket. */ ++ ++#define STN_UNDEF 0 /* End of a chain. */ ++ ++ ++/* How to extract and insert information held in the st_other field. */ ++ ++#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) ++ ++/* For ELF64 the definitions are the same. */ ++#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) ++ ++/* Symbol visibility specification encoded in the st_other field. */ ++#define STV_DEFAULT 0 /* Default symbol visibility rules */ ++#define STV_INTERNAL 1 /* Processor specific hidden class */ ++#define STV_HIDDEN 2 /* Sym unavailable in other modules */ ++#define STV_PROTECTED 3 /* Not preemptible, not exported */ ++ ++ ++/* Relocation table entry without addend (in section of type SHT_REL). */ ++ ++typedef struct ++{ ++ Elf32_Addr r_offset; /* Address */ ++ Elf32_Word r_info; /* Relocation type and symbol index */ ++} Elf32_Rel; ++ ++/* I have seen two different definitions of the Elf64_Rel and ++ Elf64_Rela structures, so we'll leave them out until Novell (or ++ whoever) gets their act together. */ ++/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ ++ ++typedef struct ++{ ++ Elf64_Addr r_offset; /* Address */ ++ Elf64_Xword r_info; /* Relocation type and symbol index */ ++} Elf64_Rel; ++ ++/* Relocation table entry with addend (in section of type SHT_RELA). */ ++ ++typedef struct ++{ ++ Elf32_Addr r_offset; /* Address */ ++ Elf32_Word r_info; /* Relocation type and symbol index */ ++ Elf32_Sword r_addend; /* Addend */ ++} Elf32_Rela; ++ ++typedef struct ++{ ++ Elf64_Addr r_offset; /* Address */ ++ Elf64_Xword r_info; /* Relocation type and symbol index */ ++ Elf64_Sxword r_addend; /* Addend */ ++} Elf64_Rela; ++ ++/* How to extract and insert information held in the r_info field. */ ++ ++#define ELF32_R_SYM(val) ((val) >> 8) ++#define ELF32_R_TYPE(val) ((val) & 0xff) ++#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) ++ ++#define ELF64_R_SYM(i) ((i) >> 32) ++#define ELF64_R_TYPE(i) ((i) & 0xffffffff) ++#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) ++ ++/* Program segment header. */ ++ ++typedef struct ++{ ++ Elf32_Word p_type; /* Segment type */ ++ Elf32_Off p_offset; /* Segment file offset */ ++ Elf32_Addr p_vaddr; /* Segment virtual address */ ++ Elf32_Addr p_paddr; /* Segment physical address */ ++ Elf32_Word p_filesz; /* Segment size in file */ ++ Elf32_Word p_memsz; /* Segment size in memory */ ++ Elf32_Word p_flags; /* Segment flags */ ++ Elf32_Word p_align; /* Segment alignment */ ++} Elf32_Phdr; ++ ++typedef struct ++{ ++ Elf64_Word p_type; /* Segment type */ ++ Elf64_Word p_flags; /* Segment flags */ ++ Elf64_Off p_offset; /* Segment file offset */ ++ Elf64_Addr p_vaddr; /* Segment virtual address */ ++ Elf64_Addr p_paddr; /* Segment physical address */ ++ Elf64_Xword p_filesz; /* Segment size in file */ ++ Elf64_Xword p_memsz; /* Segment size in memory */ ++ Elf64_Xword p_align; /* Segment alignment */ ++} Elf64_Phdr; ++ ++/* Special value for e_phnum. This indicates that the real number of ++ program headers is too large to fit into e_phnum. Instead the real ++ value is in the field sh_info of section 0. */ ++ ++#define PN_XNUM 0xffff ++ ++/* Legal values for p_type (segment type). */ ++ ++#define PT_NULL 0 /* Program header table entry unused */ ++#define PT_LOAD 1 /* Loadable program segment */ ++#define PT_DYNAMIC 2 /* Dynamic linking information */ ++#define PT_INTERP 3 /* Program interpreter */ ++#define PT_NOTE 4 /* Auxiliary information */ ++#define PT_SHLIB 5 /* Reserved */ ++#define PT_PHDR 6 /* Entry for header table itself */ ++#define PT_TLS 7 /* Thread-local storage segment */ ++#define PT_NUM 8 /* Number of defined types */ ++#define PT_LOOS 0x60000000 /* Start of OS-specific */ ++#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ ++#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ ++#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ ++#define PT_LOSUNW 0x6ffffffa ++#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ ++#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ ++#define PT_HISUNW 0x6fffffff ++#define PT_HIOS 0x6fffffff /* End of OS-specific */ ++#define PT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define PT_HIPROC 0x7fffffff /* End of processor-specific */ ++ ++/* Legal values for p_flags (segment flags). */ ++ ++#define PF_X (1 << 0) /* Segment is executable */ ++#define PF_W (1 << 1) /* Segment is writable */ ++#define PF_R (1 << 2) /* Segment is readable */ ++#define PF_MASKOS 0x0ff00000 /* OS-specific */ ++#define PF_MASKPROC 0xf0000000 /* Processor-specific */ ++ ++/* Legal values for note segment descriptor types for core files. */ ++ ++#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ ++#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ ++#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ ++#define NT_PRXREG 4 /* Contains copy of prxregset struct */ ++#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ ++#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ ++#define NT_AUXV 6 /* Contains copy of auxv array */ ++#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ ++#define NT_ASRS 8 /* Contains copy of asrset struct */ ++#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ ++#define NT_PSINFO 13 /* Contains copy of psinfo struct */ ++#define NT_PRCRED 14 /* Contains copy of prcred struct */ ++#define NT_UTSNAME 15 /* Contains copy of utsname struct */ ++#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ ++#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ ++#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ ++#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ ++#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ ++#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ ++#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ ++#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ ++#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ ++#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ ++ ++/* Legal values for the note segment descriptor types for object files. */ ++ ++#define NT_VERSION 1 /* Contains a version string. */ ++ ++ ++/* Dynamic section entry. */ ++ ++typedef struct ++{ ++ Elf32_Sword d_tag; /* Dynamic entry type */ ++ union ++ { ++ Elf32_Word d_val; /* Integer value */ ++ Elf32_Addr d_ptr; /* Address value */ ++ } d_un; ++} Elf32_Dyn; ++ ++typedef struct ++{ ++ Elf64_Sxword d_tag; /* Dynamic entry type */ ++ union ++ { ++ Elf64_Xword d_val; /* Integer value */ ++ Elf64_Addr d_ptr; /* Address value */ ++ } d_un; ++} Elf64_Dyn; ++ ++/* Legal values for d_tag (dynamic entry type). */ ++ ++#define DT_NULL 0 /* Marks end of dynamic section */ ++#define DT_NEEDED 1 /* Name of needed library */ ++#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ ++#define DT_PLTGOT 3 /* Processor defined value */ ++#define DT_HASH 4 /* Address of symbol hash table */ ++#define DT_STRTAB 5 /* Address of string table */ ++#define DT_SYMTAB 6 /* Address of symbol table */ ++#define DT_RELA 7 /* Address of Rela relocs */ ++#define DT_RELASZ 8 /* Total size of Rela relocs */ ++#define DT_RELAENT 9 /* Size of one Rela reloc */ ++#define DT_STRSZ 10 /* Size of string table */ ++#define DT_SYMENT 11 /* Size of one symbol table entry */ ++#define DT_INIT 12 /* Address of init function */ ++#define DT_FINI 13 /* Address of termination function */ ++#define DT_SONAME 14 /* Name of shared object */ ++#define DT_RPATH 15 /* Library search path (deprecated) */ ++#define DT_SYMBOLIC 16 /* Start symbol search here */ ++#define DT_REL 17 /* Address of Rel relocs */ ++#define DT_RELSZ 18 /* Total size of Rel relocs */ ++#define DT_RELENT 19 /* Size of one Rel reloc */ ++#define DT_PLTREL 20 /* Type of reloc in PLT */ ++#define DT_DEBUG 21 /* For debugging; unspecified */ ++#define DT_TEXTREL 22 /* Reloc might modify .text */ ++#define DT_JMPREL 23 /* Address of PLT relocs */ ++#define DT_BIND_NOW 24 /* Process relocations of object */ ++#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ ++#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ ++#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ ++#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ ++#define DT_RUNPATH 29 /* Library search path */ ++#define DT_FLAGS 30 /* Flags for the object being loaded */ ++#define DT_ENCODING 32 /* Start of encoded range */ ++#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ ++#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ ++#define DT_NUM 34 /* Number used */ ++#define DT_LOOS 0x6000000d /* Start of OS-specific */ ++#define DT_HIOS 0x6ffff000 /* End of OS-specific */ ++#define DT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define DT_HIPROC 0x7fffffff /* End of processor-specific */ ++#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ ++ ++/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the ++ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's ++ approach. */ ++#define DT_VALRNGLO 0x6ffffd00 ++#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ ++#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ ++#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ ++#define DT_CHECKSUM 0x6ffffdf8 ++#define DT_PLTPADSZ 0x6ffffdf9 ++#define DT_MOVEENT 0x6ffffdfa ++#define DT_MOVESZ 0x6ffffdfb ++#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ ++#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting ++ the following DT_* entry. */ ++#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ ++#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ ++#define DT_VALRNGHI 0x6ffffdff ++#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ ++#define DT_VALNUM 12 ++ ++/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the ++ Dyn.d_un.d_ptr field of the Elf*_Dyn structure. ++ ++ If any adjustment is made to the ELF object after it has been ++ built these entries will need to be adjusted. */ ++#define DT_ADDRRNGLO 0x6ffffe00 ++#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ ++#define DT_TLSDESC_PLT 0x6ffffef6 ++#define DT_TLSDESC_GOT 0x6ffffef7 ++#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ ++#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ ++#define DT_CONFIG 0x6ffffefa /* Configuration information. */ ++#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ ++#define DT_AUDIT 0x6ffffefc /* Object auditing. */ ++#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ ++#define DT_MOVETAB 0x6ffffefe /* Move table. */ ++#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ ++#define DT_ADDRRNGHI 0x6ffffeff ++#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ ++#define DT_ADDRNUM 11 ++ ++/* The versioning entry types. The next are defined as part of the ++ GNU extension. */ ++#define DT_VERSYM 0x6ffffff0 ++ ++#define DT_RELACOUNT 0x6ffffff9 ++#define DT_RELCOUNT 0x6ffffffa ++ ++/* These were chosen by Sun. */ ++#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ ++#define DT_VERDEF 0x6ffffffc /* Address of version definition ++ table */ ++#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ ++#define DT_VERNEED 0x6ffffffe /* Address of table with needed ++ versions */ ++#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ ++#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ ++#define DT_VERSIONTAGNUM 16 ++ ++/* Sun added these machine-independent extensions in the "processor-specific" ++ range. Be compatible. */ ++#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ ++#define DT_FILTER 0x7fffffff /* Shared object to get values from */ ++#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) ++#define DT_EXTRANUM 3 ++ ++/* Values of `d_un.d_val' in the DT_FLAGS entry. */ ++#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ ++#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ ++#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ ++#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ ++#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ ++ ++/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 ++ entry in the dynamic section. */ ++#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ ++#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ ++#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ ++#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ ++#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ ++#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ ++#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ ++#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ ++#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ ++#define DF_1_TRANS 0x00000200 ++#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ ++#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ ++#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ ++#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ ++#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ ++#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ ++#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ ++ ++/* Flags for the feature selection in DT_FEATURE_1. */ ++#define DTF_1_PARINIT 0x00000001 ++#define DTF_1_CONFEXP 0x00000002 ++ ++/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ ++#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ ++#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not ++ generally available. */ ++ ++/* Version definition sections. */ ++ ++typedef struct ++{ ++ Elf32_Half vd_version; /* Version revision */ ++ Elf32_Half vd_flags; /* Version information */ ++ Elf32_Half vd_ndx; /* Version Index */ ++ Elf32_Half vd_cnt; /* Number of associated aux entries */ ++ Elf32_Word vd_hash; /* Version name hash value */ ++ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ ++ Elf32_Word vd_next; /* Offset in bytes to next verdef ++ entry */ ++} Elf32_Verdef; ++ ++typedef struct ++{ ++ Elf64_Half vd_version; /* Version revision */ ++ Elf64_Half vd_flags; /* Version information */ ++ Elf64_Half vd_ndx; /* Version Index */ ++ Elf64_Half vd_cnt; /* Number of associated aux entries */ ++ Elf64_Word vd_hash; /* Version name hash value */ ++ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ ++ Elf64_Word vd_next; /* Offset in bytes to next verdef ++ entry */ ++} Elf64_Verdef; ++ ++ ++/* Legal values for vd_version (version revision). */ ++#define VER_DEF_NONE 0 /* No version */ ++#define VER_DEF_CURRENT 1 /* Current version */ ++#define VER_DEF_NUM 2 /* Given version number */ ++ ++/* Legal values for vd_flags (version information flags). */ ++#define VER_FLG_BASE 0x1 /* Version definition of file itself */ ++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ ++ ++/* Versym symbol index values. */ ++#define VER_NDX_LOCAL 0 /* Symbol is local. */ ++#define VER_NDX_GLOBAL 1 /* Symbol is global. */ ++#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ ++#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ ++ ++/* Auxialiary version information. */ ++ ++typedef struct ++{ ++ Elf32_Word vda_name; /* Version or dependency names */ ++ Elf32_Word vda_next; /* Offset in bytes to next verdaux ++ entry */ ++} Elf32_Verdaux; ++ ++typedef struct ++{ ++ Elf64_Word vda_name; /* Version or dependency names */ ++ Elf64_Word vda_next; /* Offset in bytes to next verdaux ++ entry */ ++} Elf64_Verdaux; ++ ++ ++/* Version dependency section. */ ++ ++typedef struct ++{ ++ Elf32_Half vn_version; /* Version of structure */ ++ Elf32_Half vn_cnt; /* Number of associated aux entries */ ++ Elf32_Word vn_file; /* Offset of filename for this ++ dependency */ ++ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ ++ Elf32_Word vn_next; /* Offset in bytes to next verneed ++ entry */ ++} Elf32_Verneed; ++ ++typedef struct ++{ ++ Elf64_Half vn_version; /* Version of structure */ ++ Elf64_Half vn_cnt; /* Number of associated aux entries */ ++ Elf64_Word vn_file; /* Offset of filename for this ++ dependency */ ++ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ ++ Elf64_Word vn_next; /* Offset in bytes to next verneed ++ entry */ ++} Elf64_Verneed; ++ ++ ++/* Legal values for vn_version (version revision). */ ++#define VER_NEED_NONE 0 /* No version */ ++#define VER_NEED_CURRENT 1 /* Current version */ ++#define VER_NEED_NUM 2 /* Given version number */ ++ ++/* Auxiliary needed version information. */ ++ ++typedef struct ++{ ++ Elf32_Word vna_hash; /* Hash value of dependency name */ ++ Elf32_Half vna_flags; /* Dependency specific information */ ++ Elf32_Half vna_other; /* Unused */ ++ Elf32_Word vna_name; /* Dependency name string offset */ ++ Elf32_Word vna_next; /* Offset in bytes to next vernaux ++ entry */ ++} Elf32_Vernaux; ++ ++typedef struct ++{ ++ Elf64_Word vna_hash; /* Hash value of dependency name */ ++ Elf64_Half vna_flags; /* Dependency specific information */ ++ Elf64_Half vna_other; /* Unused */ ++ Elf64_Word vna_name; /* Dependency name string offset */ ++ Elf64_Word vna_next; /* Offset in bytes to next vernaux ++ entry */ ++} Elf64_Vernaux; ++ ++ ++/* Legal values for vna_flags. */ ++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ ++ ++ ++/* Auxiliary vector. */ ++ ++/* This vector is normally only used by the program interpreter. The ++ usual definition in an ABI supplement uses the name auxv_t. The ++ vector is not usually defined in a standard file, but it ++ can't hurt. We rename it to avoid conflicts. The sizes of these ++ types are an arrangement between the exec server and the program ++ interpreter, so we don't fully specify them here. */ ++ ++typedef struct ++{ ++ uint32_t a_type; /* Entry type */ ++ union ++ { ++ uint32_t a_val; /* Integer value */ ++ /* We use to have pointer elements added here. We cannot do that, ++ though, since it does not work when using 32-bit definitions ++ on 64-bit platforms and vice versa. */ ++ } a_un; ++} Elf32_auxv_t; ++ ++typedef struct ++{ ++ uint64_t a_type; /* Entry type */ ++ union ++ { ++ uint64_t a_val; /* Integer value */ ++ /* We use to have pointer elements added here. We cannot do that, ++ though, since it does not work when using 32-bit definitions ++ on 64-bit platforms and vice versa. */ ++ } a_un; ++} Elf64_auxv_t; ++ ++/* Legal values for a_type (entry type). */ ++ ++#define AT_NULL 0 /* End of vector */ ++#define AT_IGNORE 1 /* Entry should be ignored */ ++#define AT_EXECFD 2 /* File descriptor of program */ ++#define AT_PHDR 3 /* Program headers for program */ ++#define AT_PHENT 4 /* Size of program header entry */ ++#define AT_PHNUM 5 /* Number of program headers */ ++#define AT_PAGESZ 6 /* System page size */ ++#define AT_BASE 7 /* Base address of interpreter */ ++#define AT_FLAGS 8 /* Flags */ ++#define AT_ENTRY 9 /* Entry point of program */ ++#define AT_NOTELF 10 /* Program is not ELF */ ++#define AT_UID 11 /* Real uid */ ++#define AT_EUID 12 /* Effective uid */ ++#define AT_GID 13 /* Real gid */ ++#define AT_EGID 14 /* Effective gid */ ++#define AT_CLKTCK 17 /* Frequency of times() */ ++ ++/* Some more special a_type values describing the hardware. */ ++#define AT_PLATFORM 15 /* String identifying platform. */ ++#define AT_HWCAP 16 /* Machine dependent hints about ++ processor capabilities. */ ++ ++/* This entry gives some information about the FPU initialization ++ performed by the kernel. */ ++#define AT_FPUCW 18 /* Used FPU control word. */ ++ ++/* Cache block sizes. */ ++#define AT_DCACHEBSIZE 19 /* Data cache block size. */ ++#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ ++#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ ++ ++/* A special ignored value for PPC, used by the kernel to control the ++ interpretation of the AUXV. Must be > 16. */ ++#define AT_IGNOREPPC 22 /* Entry should be ignored. */ ++ ++#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ ++ ++#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ ++ ++#define AT_RANDOM 25 /* Address of 16 random bytes. */ ++ ++#define AT_EXECFN 31 /* Filename of executable. */ ++ ++/* Pointer to the global system page used for system calls and other ++ nice things. */ ++#define AT_SYSINFO 32 ++#define AT_SYSINFO_EHDR 33 ++ ++/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains ++ log2 of line size; mask those to get cache size. */ ++#define AT_L1I_CACHESHAPE 34 ++#define AT_L1D_CACHESHAPE 35 ++#define AT_L2_CACHESHAPE 36 ++#define AT_L3_CACHESHAPE 37 ++ ++/* Note section contents. Each entry in the note section begins with ++ a header of a fixed form. */ ++ ++typedef struct ++{ ++ Elf32_Word n_namesz; /* Length of the note's name. */ ++ Elf32_Word n_descsz; /* Length of the note's descriptor. */ ++ Elf32_Word n_type; /* Type of the note. */ ++} Elf32_Nhdr; ++ ++typedef struct ++{ ++ Elf64_Word n_namesz; /* Length of the note's name. */ ++ Elf64_Word n_descsz; /* Length of the note's descriptor. */ ++ Elf64_Word n_type; /* Type of the note. */ ++} Elf64_Nhdr; ++ ++/* Known names of notes. */ ++ ++/* Solaris entries in the note section have this name. */ ++#define ELF_NOTE_SOLARIS "SUNW Solaris" ++ ++/* Note entries for GNU systems have this name. */ ++#define ELF_NOTE_GNU "GNU" ++ ++ ++/* Defined types of notes for Solaris. */ ++ ++/* Value of descriptor (one word) is desired pagesize for the binary. */ ++#define ELF_NOTE_PAGESIZE_HINT 1 ++ ++ ++/* Defined note types for GNU systems. */ ++ ++/* ABI information. The descriptor consists of words: ++ word 0: OS descriptor ++ word 1: major version of the ABI ++ word 2: minor version of the ABI ++ word 3: subminor version of the ABI ++*/ ++#define NT_GNU_ABI_TAG 1 ++#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ ++ ++/* Known OSes. These values can appear in word 0 of an ++ NT_GNU_ABI_TAG note section entry. */ ++#define ELF_NOTE_OS_LINUX 0 ++#define ELF_NOTE_OS_GNU 1 ++#define ELF_NOTE_OS_SOLARIS2 2 ++#define ELF_NOTE_OS_FREEBSD 3 ++ ++/* Synthetic hwcap information. The descriptor begins with two words: ++ word 0: number of entries ++ word 1: bitmask of enabled entries ++ Then follow variable-length entries, one byte followed by a ++ '\0'-terminated hwcap name string. The byte gives the bit ++ number to test if enabled, (1U << bit) & bitmask. */ ++#define NT_GNU_HWCAP 2 ++ ++/* Build ID bits as generated by ld --build-id. ++ The descriptor consists of any nonzero number of bytes. */ ++#define NT_GNU_BUILD_ID 3 ++ ++/* Version note generated by GNU gold containing a version string. */ ++#define NT_GNU_GOLD_VERSION 4 ++ ++ ++/* Move records. */ ++typedef struct ++{ ++ Elf32_Xword m_value; /* Symbol value. */ ++ Elf32_Word m_info; /* Size and index. */ ++ Elf32_Word m_poffset; /* Symbol offset. */ ++ Elf32_Half m_repeat; /* Repeat count. */ ++ Elf32_Half m_stride; /* Stride info. */ ++} Elf32_Move; ++ ++typedef struct ++{ ++ Elf64_Xword m_value; /* Symbol value. */ ++ Elf64_Xword m_info; /* Size and index. */ ++ Elf64_Xword m_poffset; /* Symbol offset. */ ++ Elf64_Half m_repeat; /* Repeat count. */ ++ Elf64_Half m_stride; /* Stride info. */ ++} Elf64_Move; ++ ++/* Macro to construct move records. */ ++#define ELF32_M_SYM(info) ((info) >> 8) ++#define ELF32_M_SIZE(info) ((unsigned char) (info)) ++#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) ++ ++#define ELF64_M_SYM(info) ELF32_M_SYM (info) ++#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) ++#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) ++ ++ ++/* Motorola 68k specific definitions. */ ++ ++/* Values for Elf32_Ehdr.e_flags. */ ++#define EF_CPU32 0x00810000 ++ ++/* m68k relocs. */ ++ ++#define R_68K_NONE 0 /* No reloc */ ++#define R_68K_32 1 /* Direct 32 bit */ ++#define R_68K_16 2 /* Direct 16 bit */ ++#define R_68K_8 3 /* Direct 8 bit */ ++#define R_68K_PC32 4 /* PC relative 32 bit */ ++#define R_68K_PC16 5 /* PC relative 16 bit */ ++#define R_68K_PC8 6 /* PC relative 8 bit */ ++#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ ++#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ ++#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ ++#define R_68K_GOT32O 10 /* 32 bit GOT offset */ ++#define R_68K_GOT16O 11 /* 16 bit GOT offset */ ++#define R_68K_GOT8O 12 /* 8 bit GOT offset */ ++#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ ++#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ ++#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ ++#define R_68K_PLT32O 16 /* 32 bit PLT offset */ ++#define R_68K_PLT16O 17 /* 16 bit PLT offset */ ++#define R_68K_PLT8O 18 /* 8 bit PLT offset */ ++#define R_68K_COPY 19 /* Copy symbol at runtime */ ++#define R_68K_GLOB_DAT 20 /* Create GOT entry */ ++#define R_68K_JMP_SLOT 21 /* Create PLT entry */ ++#define R_68K_RELATIVE 22 /* Adjust by program base */ ++#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ ++#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ ++#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ ++#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ ++#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ ++#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ ++#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ ++#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ ++#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ ++#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ ++#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ ++#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ ++#define R_68K_TLS_LE32 37 /* 32 bit offset relative to ++ static TLS block */ ++#define R_68K_TLS_LE16 38 /* 16 bit offset relative to ++ static TLS block */ ++#define R_68K_TLS_LE8 39 /* 8 bit offset relative to ++ static TLS block */ ++#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ ++#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ ++#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ ++/* Keep this the last entry. */ ++#define R_68K_NUM 43 ++ ++/* Intel 80386 specific definitions. */ ++ ++/* i386 relocs. */ ++ ++#define R_386_NONE 0 /* No reloc */ ++#define R_386_32 1 /* Direct 32 bit */ ++#define R_386_PC32 2 /* PC relative 32 bit */ ++#define R_386_GOT32 3 /* 32 bit GOT entry */ ++#define R_386_PLT32 4 /* 32 bit PLT address */ ++#define R_386_COPY 5 /* Copy symbol at runtime */ ++#define R_386_GLOB_DAT 6 /* Create GOT entry */ ++#define R_386_JMP_SLOT 7 /* Create PLT entry */ ++#define R_386_RELATIVE 8 /* Adjust by program base */ ++#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ ++#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ ++#define R_386_32PLT 11 ++#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ ++#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS ++ block offset */ ++#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block ++ offset */ ++#define R_386_TLS_LE 17 /* Offset relative to static TLS ++ block */ ++#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of ++ general dynamic thread local data */ ++#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of ++ local dynamic thread local data ++ in LE code */ ++#define R_386_16 20 ++#define R_386_PC16 21 ++#define R_386_8 22 ++#define R_386_PC8 23 ++#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic ++ thread local data */ ++#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ ++#define R_386_TLS_GD_CALL 26 /* Relocation for call to ++ __tls_get_addr() */ ++#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ ++#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic ++ thread local data in LE code */ ++#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ ++#define R_386_TLS_LDM_CALL 30 /* Relocation for call to ++ __tls_get_addr() in LDM code */ ++#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ ++#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ ++#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS ++ block offset */ ++#define R_386_TLS_LE_32 34 /* Negated offset relative to static ++ TLS block */ ++#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ ++#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ ++#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ ++/* 38? */ ++#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ ++#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS ++ descriptor for ++ relaxation. */ ++#define R_386_TLS_DESC 41 /* TLS descriptor containing ++ pointer to code and to ++ argument, returning the TLS ++ offset for the symbol. */ ++#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ ++/* Keep this the last entry. */ ++#define R_386_NUM 43 ++ ++/* SUN SPARC specific definitions. */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ ++ ++/* Values for Elf64_Ehdr.e_flags. */ ++ ++#define EF_SPARCV9_MM 3 ++#define EF_SPARCV9_TSO 0 ++#define EF_SPARCV9_PSO 1 ++#define EF_SPARCV9_RMO 2 ++#define EF_SPARC_LEDATA 0x800000 /* little endian data */ ++#define EF_SPARC_EXT_MASK 0xFFFF00 ++#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ ++#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ ++#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ ++#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ ++ ++/* SPARC relocs. */ ++ ++#define R_SPARC_NONE 0 /* No reloc */ ++#define R_SPARC_8 1 /* Direct 8 bit */ ++#define R_SPARC_16 2 /* Direct 16 bit */ ++#define R_SPARC_32 3 /* Direct 32 bit */ ++#define R_SPARC_DISP8 4 /* PC relative 8 bit */ ++#define R_SPARC_DISP16 5 /* PC relative 16 bit */ ++#define R_SPARC_DISP32 6 /* PC relative 32 bit */ ++#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ ++#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ ++#define R_SPARC_HI22 9 /* High 22 bit */ ++#define R_SPARC_22 10 /* Direct 22 bit */ ++#define R_SPARC_13 11 /* Direct 13 bit */ ++#define R_SPARC_LO10 12 /* Truncated 10 bit */ ++#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ ++#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ ++#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ ++#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ ++#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ ++#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ ++#define R_SPARC_COPY 19 /* Copy symbol at runtime */ ++#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ ++#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ ++#define R_SPARC_RELATIVE 22 /* Adjust by program base */ ++#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ ++ ++/* Additional Sparc64 relocs. */ ++ ++#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ ++#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ ++#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ ++#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ ++#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ ++#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ ++#define R_SPARC_10 30 /* Direct 10 bit */ ++#define R_SPARC_11 31 /* Direct 11 bit */ ++#define R_SPARC_64 32 /* Direct 64 bit */ ++#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ ++#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ ++#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ ++#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ ++#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ ++#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ ++#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ ++#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ ++#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ ++#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ ++#define R_SPARC_7 43 /* Direct 7 bit */ ++#define R_SPARC_5 44 /* Direct 5 bit */ ++#define R_SPARC_6 45 /* Direct 6 bit */ ++#define R_SPARC_DISP64 46 /* PC relative 64 bit */ ++#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ ++#define R_SPARC_HIX22 48 /* High 22 bit complemented */ ++#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ ++#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ ++#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ ++#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ ++#define R_SPARC_REGISTER 53 /* Global register usage */ ++#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ ++#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ ++#define R_SPARC_TLS_GD_HI22 56 ++#define R_SPARC_TLS_GD_LO10 57 ++#define R_SPARC_TLS_GD_ADD 58 ++#define R_SPARC_TLS_GD_CALL 59 ++#define R_SPARC_TLS_LDM_HI22 60 ++#define R_SPARC_TLS_LDM_LO10 61 ++#define R_SPARC_TLS_LDM_ADD 62 ++#define R_SPARC_TLS_LDM_CALL 63 ++#define R_SPARC_TLS_LDO_HIX22 64 ++#define R_SPARC_TLS_LDO_LOX10 65 ++#define R_SPARC_TLS_LDO_ADD 66 ++#define R_SPARC_TLS_IE_HI22 67 ++#define R_SPARC_TLS_IE_LO10 68 ++#define R_SPARC_TLS_IE_LD 69 ++#define R_SPARC_TLS_IE_LDX 70 ++#define R_SPARC_TLS_IE_ADD 71 ++#define R_SPARC_TLS_LE_HIX22 72 ++#define R_SPARC_TLS_LE_LOX10 73 ++#define R_SPARC_TLS_DTPMOD32 74 ++#define R_SPARC_TLS_DTPMOD64 75 ++#define R_SPARC_TLS_DTPOFF32 76 ++#define R_SPARC_TLS_DTPOFF64 77 ++#define R_SPARC_TLS_TPOFF32 78 ++#define R_SPARC_TLS_TPOFF64 79 ++#define R_SPARC_GOTDATA_HIX22 80 ++#define R_SPARC_GOTDATA_LOX10 81 ++#define R_SPARC_GOTDATA_OP_HIX22 82 ++#define R_SPARC_GOTDATA_OP_LOX10 83 ++#define R_SPARC_GOTDATA_OP 84 ++#define R_SPARC_H34 85 ++#define R_SPARC_SIZE32 86 ++#define R_SPARC_SIZE64 87 ++#define R_SPARC_WDISP10 88 ++#define R_SPARC_JMP_IREL 248 ++#define R_SPARC_IRELATIVE 249 ++#define R_SPARC_GNU_VTINHERIT 250 ++#define R_SPARC_GNU_VTENTRY 251 ++#define R_SPARC_REV32 252 ++/* Keep this the last entry. */ ++#define R_SPARC_NUM 253 ++ ++/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ ++ ++#define DT_SPARC_REGISTER 0x70000001 ++#define DT_SPARC_NUM 2 ++ ++/* MIPS R3000 specific definitions. */ ++ ++/* Legal values for e_flags field of Elf32_Ehdr. */ ++ ++#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ ++#define EF_MIPS_PIC 2 /* Contains PIC code */ ++#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ ++#define EF_MIPS_XGOT 8 ++#define EF_MIPS_64BIT_WHIRL 16 ++#define EF_MIPS_ABI2 32 ++#define EF_MIPS_ABI_ON32 64 ++#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ ++ ++/* Legal values for MIPS architecture level. */ ++ ++#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ ++#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ ++#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ ++#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ ++#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ ++#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ ++#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ ++ ++/* The following are non-official names and should not be used. */ ++ ++#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ ++#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ ++#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ ++#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ ++#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ ++#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ ++#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ ++ ++/* Special section indices. */ ++ ++#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ ++#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ ++#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ ++#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ ++#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ ++ ++/* Legal values for sh_type field of Elf32_Shdr. */ ++ ++#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ ++#define SHT_MIPS_MSYM 0x70000001 ++#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ ++#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ ++#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ ++#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ ++#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ ++#define SHT_MIPS_PACKAGE 0x70000007 ++#define SHT_MIPS_PACKSYM 0x70000008 ++#define SHT_MIPS_RELD 0x70000009 ++#define SHT_MIPS_IFACE 0x7000000b ++#define SHT_MIPS_CONTENT 0x7000000c ++#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ ++#define SHT_MIPS_SHDR 0x70000010 ++#define SHT_MIPS_FDESC 0x70000011 ++#define SHT_MIPS_EXTSYM 0x70000012 ++#define SHT_MIPS_DENSE 0x70000013 ++#define SHT_MIPS_PDESC 0x70000014 ++#define SHT_MIPS_LOCSYM 0x70000015 ++#define SHT_MIPS_AUXSYM 0x70000016 ++#define SHT_MIPS_OPTSYM 0x70000017 ++#define SHT_MIPS_LOCSTR 0x70000018 ++#define SHT_MIPS_LINE 0x70000019 ++#define SHT_MIPS_RFDESC 0x7000001a ++#define SHT_MIPS_DELTASYM 0x7000001b ++#define SHT_MIPS_DELTAINST 0x7000001c ++#define SHT_MIPS_DELTACLASS 0x7000001d ++#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ ++#define SHT_MIPS_DELTADECL 0x7000001f ++#define SHT_MIPS_SYMBOL_LIB 0x70000020 ++#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ ++#define SHT_MIPS_TRANSLATE 0x70000022 ++#define SHT_MIPS_PIXIE 0x70000023 ++#define SHT_MIPS_XLATE 0x70000024 ++#define SHT_MIPS_XLATE_DEBUG 0x70000025 ++#define SHT_MIPS_WHIRL 0x70000026 ++#define SHT_MIPS_EH_REGION 0x70000027 ++#define SHT_MIPS_XLATE_OLD 0x70000028 ++#define SHT_MIPS_PDR_EXCEPTION 0x70000029 ++ ++/* Legal values for sh_flags field of Elf32_Shdr. */ ++ ++#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ ++#define SHF_MIPS_MERGE 0x20000000 ++#define SHF_MIPS_ADDR 0x40000000 ++#define SHF_MIPS_STRINGS 0x80000000 ++#define SHF_MIPS_NOSTRIP 0x08000000 ++#define SHF_MIPS_LOCAL 0x04000000 ++#define SHF_MIPS_NAMES 0x02000000 ++#define SHF_MIPS_NODUPE 0x01000000 ++ ++ ++/* Symbol tables. */ ++ ++/* MIPS specific values for `st_other'. */ ++#define STO_MIPS_DEFAULT 0x0 ++#define STO_MIPS_INTERNAL 0x1 ++#define STO_MIPS_HIDDEN 0x2 ++#define STO_MIPS_PROTECTED 0x3 ++#define STO_MIPS_PLT 0x8 ++#define STO_MIPS_SC_ALIGN_UNUSED 0xff ++ ++/* MIPS specific values for `st_info'. */ ++#define STB_MIPS_SPLIT_COMMON 13 ++ ++/* Entries found in sections of type SHT_MIPS_GPTAB. */ ++ ++typedef union ++{ ++ struct ++ { ++ Elf32_Word gt_current_g_value; /* -G value used for compilation */ ++ Elf32_Word gt_unused; /* Not used */ ++ } gt_header; /* First entry in section */ ++ struct ++ { ++ Elf32_Word gt_g_value; /* If this value were used for -G */ ++ Elf32_Word gt_bytes; /* This many bytes would be used */ ++ } gt_entry; /* Subsequent entries in section */ ++} Elf32_gptab; ++ ++/* Entry found in sections of type SHT_MIPS_REGINFO. */ ++ ++typedef struct ++{ ++ Elf32_Word ri_gprmask; /* General registers used */ ++ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ ++ Elf32_Sword ri_gp_value; /* $gp register value */ ++} Elf32_RegInfo; ++ ++/* Entries found in sections of type SHT_MIPS_OPTIONS. */ ++ ++typedef struct ++{ ++ unsigned char kind; /* Determines interpretation of the ++ variable part of descriptor. */ ++ unsigned char size; /* Size of descriptor, including header. */ ++ Elf32_Section section; /* Section header index of section affected, ++ 0 for global options. */ ++ Elf32_Word info; /* Kind-specific information. */ ++} Elf_Options; ++ ++/* Values for `kind' field in Elf_Options. */ ++ ++#define ODK_NULL 0 /* Undefined. */ ++#define ODK_REGINFO 1 /* Register usage information. */ ++#define ODK_EXCEPTIONS 2 /* Exception processing options. */ ++#define ODK_PAD 3 /* Section padding options. */ ++#define ODK_HWPATCH 4 /* Hardware workarounds performed */ ++#define ODK_FILL 5 /* record the fill value used by the linker. */ ++#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ ++#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ ++#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ ++ ++/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ ++ ++#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ ++#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ ++#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ ++#define OEX_SMM 0x20000 /* Force sequential memory mode? */ ++#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ ++#define OEX_PRECISEFP OEX_FPDBUG ++#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ ++ ++#define OEX_FPU_INVAL 0x10 ++#define OEX_FPU_DIV0 0x08 ++#define OEX_FPU_OFLO 0x04 ++#define OEX_FPU_UFLO 0x02 ++#define OEX_FPU_INEX 0x01 ++ ++/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ ++ ++#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ ++#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ ++#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ ++#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ ++ ++#define OPAD_PREFIX 0x1 ++#define OPAD_POSTFIX 0x2 ++#define OPAD_SYMBOL 0x4 ++ ++/* Entry found in `.options' section. */ ++ ++typedef struct ++{ ++ Elf32_Word hwp_flags1; /* Extra flags. */ ++ Elf32_Word hwp_flags2; /* Extra flags. */ ++} Elf_Options_Hw; ++ ++/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ ++ ++#define OHWA0_R4KEOP_CHECKED 0x00000001 ++#define OHWA1_R4KEOP_CLEAN 0x00000002 ++ ++/* MIPS relocs. */ ++ ++#define R_MIPS_NONE 0 /* No reloc */ ++#define R_MIPS_16 1 /* Direct 16 bit */ ++#define R_MIPS_32 2 /* Direct 32 bit */ ++#define R_MIPS_REL32 3 /* PC relative 32 bit */ ++#define R_MIPS_26 4 /* Direct 26 bit shifted */ ++#define R_MIPS_HI16 5 /* High 16 bit */ ++#define R_MIPS_LO16 6 /* Low 16 bit */ ++#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ ++#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ ++#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ ++#define R_MIPS_PC16 10 /* PC relative 16 bit */ ++#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ ++#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ ++ ++#define R_MIPS_SHIFT5 16 ++#define R_MIPS_SHIFT6 17 ++#define R_MIPS_64 18 ++#define R_MIPS_GOT_DISP 19 ++#define R_MIPS_GOT_PAGE 20 ++#define R_MIPS_GOT_OFST 21 ++#define R_MIPS_GOT_HI16 22 ++#define R_MIPS_GOT_LO16 23 ++#define R_MIPS_SUB 24 ++#define R_MIPS_INSERT_A 25 ++#define R_MIPS_INSERT_B 26 ++#define R_MIPS_DELETE 27 ++#define R_MIPS_HIGHER 28 ++#define R_MIPS_HIGHEST 29 ++#define R_MIPS_CALL_HI16 30 ++#define R_MIPS_CALL_LO16 31 ++#define R_MIPS_SCN_DISP 32 ++#define R_MIPS_REL16 33 ++#define R_MIPS_ADD_IMMEDIATE 34 ++#define R_MIPS_PJUMP 35 ++#define R_MIPS_RELGOT 36 ++#define R_MIPS_JALR 37 ++#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ ++#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ ++#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ ++#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ ++#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ ++#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ ++#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ ++#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ ++#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ ++#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ ++#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ ++#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ ++#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ ++#define R_MIPS_GLOB_DAT 51 ++#define R_MIPS_COPY 126 ++#define R_MIPS_JUMP_SLOT 127 ++/* Keep this the last entry. */ ++#define R_MIPS_NUM 128 ++ ++/* Legal values for p_type field of Elf32_Phdr. */ ++ ++#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ ++#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ ++#define PT_MIPS_OPTIONS 0x70000002 ++ ++/* Special program header types. */ ++ ++#define PF_MIPS_LOCAL 0x10000000 ++ ++/* Legal values for d_tag field of Elf32_Dyn. */ ++ ++#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ ++#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ ++#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ ++#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ ++#define DT_MIPS_FLAGS 0x70000005 /* Flags */ ++#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ ++#define DT_MIPS_MSYM 0x70000007 ++#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ ++#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ ++#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ ++#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ ++#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ ++#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ ++#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ ++#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ ++#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ ++#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ ++#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ ++#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in ++ DT_MIPS_DELTA_CLASS. */ ++#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ ++#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in ++ DT_MIPS_DELTA_INSTANCE. */ ++#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ ++#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in ++ DT_MIPS_DELTA_RELOC. */ ++#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta ++ relocations refer to. */ ++#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in ++ DT_MIPS_DELTA_SYM. */ ++#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the ++ class declaration. */ ++#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in ++ DT_MIPS_DELTA_CLASSSYM. */ ++#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ ++#define DT_MIPS_PIXIE_INIT 0x70000023 ++#define DT_MIPS_SYMBOL_LIB 0x70000024 ++#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 ++#define DT_MIPS_LOCAL_GOTIDX 0x70000026 ++#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 ++#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 ++#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ ++#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ ++#define DT_MIPS_DYNSTR_ALIGN 0x7000002b ++#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ ++#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve ++ function stored in GOT. */ ++#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added ++ by rld on dlopen() calls. */ ++#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ ++#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ ++#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ ++/* The address of .got.plt in an executable using the new non-PIC ABI. */ ++#define DT_MIPS_PLTGOT 0x70000032 ++/* The base of the PLT in an executable using the new non-PIC ABI if that ++ PLT is writable. For a non-writable PLT, this is omitted or has a zero ++ value. */ ++#define DT_MIPS_RWPLT 0x70000034 ++#define DT_MIPS_NUM 0x35 ++ ++/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ ++ ++#define RHF_NONE 0 /* No flags */ ++#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ ++#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ ++#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ ++#define RHF_NO_MOVE (1 << 3) ++#define RHF_SGI_ONLY (1 << 4) ++#define RHF_GUARANTEE_INIT (1 << 5) ++#define RHF_DELTA_C_PLUS_PLUS (1 << 6) ++#define RHF_GUARANTEE_START_INIT (1 << 7) ++#define RHF_PIXIE (1 << 8) ++#define RHF_DEFAULT_DELAY_LOAD (1 << 9) ++#define RHF_REQUICKSTART (1 << 10) ++#define RHF_REQUICKSTARTED (1 << 11) ++#define RHF_CORD (1 << 12) ++#define RHF_NO_UNRES_UNDEF (1 << 13) ++#define RHF_RLD_ORDER_SAFE (1 << 14) ++ ++/* Entries found in sections of type SHT_MIPS_LIBLIST. */ ++ ++typedef struct ++{ ++ Elf32_Word l_name; /* Name (string table index) */ ++ Elf32_Word l_time_stamp; /* Timestamp */ ++ Elf32_Word l_checksum; /* Checksum */ ++ Elf32_Word l_version; /* Interface version */ ++ Elf32_Word l_flags; /* Flags */ ++} Elf32_Lib; ++ ++typedef struct ++{ ++ Elf64_Word l_name; /* Name (string table index) */ ++ Elf64_Word l_time_stamp; /* Timestamp */ ++ Elf64_Word l_checksum; /* Checksum */ ++ Elf64_Word l_version; /* Interface version */ ++ Elf64_Word l_flags; /* Flags */ ++} Elf64_Lib; ++ ++ ++/* Legal values for l_flags. */ ++ ++#define LL_NONE 0 ++#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ ++#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ ++#define LL_REQUIRE_MINOR (1 << 2) ++#define LL_EXPORTS (1 << 3) ++#define LL_DELAY_LOAD (1 << 4) ++#define LL_DELTA (1 << 5) ++ ++/* Entries found in sections of type SHT_MIPS_CONFLICT. */ ++ ++typedef Elf32_Addr Elf32_Conflict; ++ ++ ++/* HPPA specific definitions. */ ++ ++/* Legal values for e_flags field of Elf32_Ehdr. */ ++ ++#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ ++#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ ++#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ ++#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ ++#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch ++ prediction. */ ++#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ ++#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ ++ ++/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ ++ ++#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ ++#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ ++#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ ++ ++/* Additional section indeces. */ ++ ++#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared ++ symbols in ANSI C. */ ++#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ ++ ++/* Legal values for sh_type field of Elf32_Shdr. */ ++ ++#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ ++#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ ++#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ ++ ++/* Legal values for sh_flags field of Elf32_Shdr. */ ++ ++#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ ++#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ ++#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ ++ ++#define STT_HP_OPAQUE (STT_LOOS + 0x1) ++#define STT_HP_STUB (STT_LOOS + 0x2) ++ ++/* HPPA relocs. */ ++ ++#define R_PARISC_NONE 0 /* No reloc. */ ++#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ ++#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ ++#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ ++#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ ++#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ ++#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ ++#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ ++#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ ++#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ ++#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ ++#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ ++#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ ++#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ ++#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ ++#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ ++#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ ++#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ ++#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ ++#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ ++#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ ++#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ ++#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ ++#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ ++#define R_PARISC_FPTR64 64 /* 64 bits function address. */ ++#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ ++#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ ++#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ ++#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ ++#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ ++#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ ++#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ ++#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ ++#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ ++#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ ++#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ ++#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ ++#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ ++#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ ++#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ ++#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ ++#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ ++#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ ++#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ ++#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ ++#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ ++#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ ++#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ ++#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ ++#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ ++#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ ++#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ ++#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ ++#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ ++#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ ++#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ ++#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ ++#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ ++#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LORESERVE 128 ++#define R_PARISC_COPY 128 /* Copy relocation. */ ++#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ ++#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ ++#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ ++#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ ++#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ ++#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ ++#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ ++#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ ++#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ ++#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ ++#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_GNU_VTENTRY 232 ++#define R_PARISC_GNU_VTINHERIT 233 ++#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ ++#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ ++#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ ++#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ ++#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ ++#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ ++#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ ++#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ ++#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ ++#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ ++#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ ++#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ ++#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L ++#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R ++#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L ++#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R ++#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 ++#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 ++#define R_PARISC_HIRESERVE 255 ++ ++/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ ++ ++#define PT_HP_TLS (PT_LOOS + 0x0) ++#define PT_HP_CORE_NONE (PT_LOOS + 0x1) ++#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) ++#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) ++#define PT_HP_CORE_COMM (PT_LOOS + 0x4) ++#define PT_HP_CORE_PROC (PT_LOOS + 0x5) ++#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) ++#define PT_HP_CORE_STACK (PT_LOOS + 0x7) ++#define PT_HP_CORE_SHM (PT_LOOS + 0x8) ++#define PT_HP_CORE_MMF (PT_LOOS + 0x9) ++#define PT_HP_PARALLEL (PT_LOOS + 0x10) ++#define PT_HP_FASTBIND (PT_LOOS + 0x11) ++#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) ++#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) ++#define PT_HP_STACK (PT_LOOS + 0x14) ++ ++#define PT_PARISC_ARCHEXT 0x70000000 ++#define PT_PARISC_UNWIND 0x70000001 ++ ++/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ ++ ++#define PF_PARISC_SBP 0x08000000 ++ ++#define PF_HP_PAGE_SIZE 0x00100000 ++#define PF_HP_FAR_SHARED 0x00200000 ++#define PF_HP_NEAR_SHARED 0x00400000 ++#define PF_HP_CODE 0x01000000 ++#define PF_HP_MODIFY 0x02000000 ++#define PF_HP_LAZYSWAP 0x04000000 ++#define PF_HP_SBP 0x08000000 ++ ++ ++/* Alpha specific definitions. */ ++ ++/* Legal values for e_flags field of Elf64_Ehdr. */ ++ ++#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ ++#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ ++ ++/* Legal values for sh_type field of Elf64_Shdr. */ ++ ++/* These two are primerily concerned with ECOFF debugging info. */ ++#define SHT_ALPHA_DEBUG 0x70000001 ++#define SHT_ALPHA_REGINFO 0x70000002 ++ ++/* Legal values for sh_flags field of Elf64_Shdr. */ ++ ++#define SHF_ALPHA_GPREL 0x10000000 ++ ++/* Legal values for st_other field of Elf64_Sym. */ ++#define STO_ALPHA_NOPV 0x80 /* No PV required. */ ++#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ ++ ++/* Alpha relocs. */ ++ ++#define R_ALPHA_NONE 0 /* No reloc */ ++#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ ++#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ ++#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ ++#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ ++#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ ++#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ ++#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ ++#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ ++#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ ++#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ ++#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ ++#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ ++#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ ++#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ ++#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ ++#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ ++#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ ++#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ ++#define R_ALPHA_TLS_GD_HI 28 ++#define R_ALPHA_TLSGD 29 ++#define R_ALPHA_TLS_LDM 30 ++#define R_ALPHA_DTPMOD64 31 ++#define R_ALPHA_GOTDTPREL 32 ++#define R_ALPHA_DTPREL64 33 ++#define R_ALPHA_DTPRELHI 34 ++#define R_ALPHA_DTPRELLO 35 ++#define R_ALPHA_DTPREL16 36 ++#define R_ALPHA_GOTTPREL 37 ++#define R_ALPHA_TPREL64 38 ++#define R_ALPHA_TPRELHI 39 ++#define R_ALPHA_TPRELLO 40 ++#define R_ALPHA_TPREL16 41 ++/* Keep this the last entry. */ ++#define R_ALPHA_NUM 46 ++ ++/* Magic values of the LITUSE relocation addend. */ ++#define LITUSE_ALPHA_ADDR 0 ++#define LITUSE_ALPHA_BASE 1 ++#define LITUSE_ALPHA_BYTOFF 2 ++#define LITUSE_ALPHA_JSR 3 ++#define LITUSE_ALPHA_TLS_GD 4 ++#define LITUSE_ALPHA_TLS_LDM 5 ++ ++/* Legal values for d_tag of Elf64_Dyn. */ ++#define DT_ALPHA_PLTRO (DT_LOPROC + 0) ++#define DT_ALPHA_NUM 1 ++ ++/* PowerPC specific declarations */ ++ ++/* Values for Elf32/64_Ehdr.e_flags. */ ++#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ ++ ++/* Cygnus local bits below */ ++#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ ++#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib ++ flag */ ++ ++/* PowerPC relocations defined by the ABIs */ ++#define R_PPC_NONE 0 ++#define R_PPC_ADDR32 1 /* 32bit absolute address */ ++#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ ++#define R_PPC_ADDR16 3 /* 16bit absolute address */ ++#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ ++#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ ++#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ ++#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ ++#define R_PPC_ADDR14_BRTAKEN 8 ++#define R_PPC_ADDR14_BRNTAKEN 9 ++#define R_PPC_REL24 10 /* PC relative 26 bit */ ++#define R_PPC_REL14 11 /* PC relative 16 bit */ ++#define R_PPC_REL14_BRTAKEN 12 ++#define R_PPC_REL14_BRNTAKEN 13 ++#define R_PPC_GOT16 14 ++#define R_PPC_GOT16_LO 15 ++#define R_PPC_GOT16_HI 16 ++#define R_PPC_GOT16_HA 17 ++#define R_PPC_PLTREL24 18 ++#define R_PPC_COPY 19 ++#define R_PPC_GLOB_DAT 20 ++#define R_PPC_JMP_SLOT 21 ++#define R_PPC_RELATIVE 22 ++#define R_PPC_LOCAL24PC 23 ++#define R_PPC_UADDR32 24 ++#define R_PPC_UADDR16 25 ++#define R_PPC_REL32 26 ++#define R_PPC_PLT32 27 ++#define R_PPC_PLTREL32 28 ++#define R_PPC_PLT16_LO 29 ++#define R_PPC_PLT16_HI 30 ++#define R_PPC_PLT16_HA 31 ++#define R_PPC_SDAREL16 32 ++#define R_PPC_SECTOFF 33 ++#define R_PPC_SECTOFF_LO 34 ++#define R_PPC_SECTOFF_HI 35 ++#define R_PPC_SECTOFF_HA 36 ++ ++/* PowerPC relocations defined for the TLS access ABI. */ ++#define R_PPC_TLS 67 /* none (sym+add)@tls */ ++#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ ++#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ ++#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ ++#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ ++#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ ++#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ ++#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ ++#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ ++#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ ++#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ ++#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ ++#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ ++#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ ++#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ ++#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ ++#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ ++#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ ++#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ ++#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ ++#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ ++#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ ++#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ ++#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ ++#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ ++#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ ++#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ ++#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ ++ ++/* The remaining relocs are from the Embedded ELF ABI, and are not ++ in the SVR4 ELF ABI. */ ++#define R_PPC_EMB_NADDR32 101 ++#define R_PPC_EMB_NADDR16 102 ++#define R_PPC_EMB_NADDR16_LO 103 ++#define R_PPC_EMB_NADDR16_HI 104 ++#define R_PPC_EMB_NADDR16_HA 105 ++#define R_PPC_EMB_SDAI16 106 ++#define R_PPC_EMB_SDA2I16 107 ++#define R_PPC_EMB_SDA2REL 108 ++#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ ++#define R_PPC_EMB_MRKREF 110 ++#define R_PPC_EMB_RELSEC16 111 ++#define R_PPC_EMB_RELST_LO 112 ++#define R_PPC_EMB_RELST_HI 113 ++#define R_PPC_EMB_RELST_HA 114 ++#define R_PPC_EMB_BIT_FLD 115 ++#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ ++ ++/* Diab tool relocations. */ ++#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ ++#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ ++#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ ++#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ ++#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ ++#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ ++ ++/* GNU extension to support local ifunc. */ ++#define R_PPC_IRELATIVE 248 ++ ++/* GNU relocs used in PIC code sequences. */ ++#define R_PPC_REL16 249 /* half16 (sym+add-.) */ ++#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ ++#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ ++#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ ++ ++/* This is a phony reloc to handle any old fashioned TOC16 references ++ that may still be in object files. */ ++#define R_PPC_TOC16 255 ++ ++/* PowerPC specific values for the Dyn d_tag field. */ ++#define DT_PPC_GOT (DT_LOPROC + 0) ++#define DT_PPC_NUM 1 ++ ++/* PowerPC64 relocations defined by the ABIs */ ++#define R_PPC64_NONE R_PPC_NONE ++#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ ++#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ ++#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ ++#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ ++#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ ++#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ ++#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ ++#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN ++#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN ++#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ ++#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ ++#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN ++#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN ++#define R_PPC64_GOT16 R_PPC_GOT16 ++#define R_PPC64_GOT16_LO R_PPC_GOT16_LO ++#define R_PPC64_GOT16_HI R_PPC_GOT16_HI ++#define R_PPC64_GOT16_HA R_PPC_GOT16_HA ++ ++#define R_PPC64_COPY R_PPC_COPY ++#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT ++#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT ++#define R_PPC64_RELATIVE R_PPC_RELATIVE ++ ++#define R_PPC64_UADDR32 R_PPC_UADDR32 ++#define R_PPC64_UADDR16 R_PPC_UADDR16 ++#define R_PPC64_REL32 R_PPC_REL32 ++#define R_PPC64_PLT32 R_PPC_PLT32 ++#define R_PPC64_PLTREL32 R_PPC_PLTREL32 ++#define R_PPC64_PLT16_LO R_PPC_PLT16_LO ++#define R_PPC64_PLT16_HI R_PPC_PLT16_HI ++#define R_PPC64_PLT16_HA R_PPC_PLT16_HA ++ ++#define R_PPC64_SECTOFF R_PPC_SECTOFF ++#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO ++#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI ++#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA ++#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ ++#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ ++#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ ++#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ ++#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ ++#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ ++#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ ++#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ ++#define R_PPC64_PLT64 45 /* doubleword64 L + A */ ++#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ ++#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ ++#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ ++#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ ++#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ ++#define R_PPC64_TOC 51 /* doubleword64 .TOC */ ++#define R_PPC64_PLTGOT16 52 /* half16* M + A */ ++#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ ++#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ ++#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ ++ ++#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ ++#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ ++#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ ++#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ ++#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ ++#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ ++#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ ++#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ ++#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ ++#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ ++#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ ++ ++/* PowerPC64 relocations defined for the TLS access ABI. */ ++#define R_PPC64_TLS 67 /* none (sym+add)@tls */ ++#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ ++#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ ++#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ ++#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ ++#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ ++#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ ++#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ ++#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ ++#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ ++#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ ++#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ ++#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ ++#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ ++#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ ++#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ ++#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ ++#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ ++#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ ++#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ ++#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ ++#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ ++#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ ++#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ ++#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ ++#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ ++#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ ++#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ ++#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ ++#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ ++#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ ++#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ ++#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ ++#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ ++#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ ++#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ ++#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ ++#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ ++#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ ++#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ ++ ++/* GNU extension to support local ifunc. */ ++#define R_PPC64_JMP_IREL 247 ++#define R_PPC64_IRELATIVE 248 ++#define R_PPC64_REL16 249 /* half16 (sym+add-.) */ ++#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ ++#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ ++#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ ++ ++/* PowerPC64 specific values for the Dyn d_tag field. */ ++#define DT_PPC64_GLINK (DT_LOPROC + 0) ++#define DT_PPC64_OPD (DT_LOPROC + 1) ++#define DT_PPC64_OPDSZ (DT_LOPROC + 2) ++#define DT_PPC64_NUM 3 ++ ++ ++/* ARM specific declarations */ ++ ++/* Processor specific flags for the ELF header e_flags field. */ ++#define EF_ARM_RELEXEC 0x01 ++#define EF_ARM_HASENTRY 0x02 ++#define EF_ARM_INTERWORK 0x04 ++#define EF_ARM_APCS_26 0x08 ++#define EF_ARM_APCS_FLOAT 0x10 ++#define EF_ARM_PIC 0x20 ++#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ ++#define EF_ARM_NEW_ABI 0x80 ++#define EF_ARM_OLD_ABI 0x100 ++#define EF_ARM_SOFT_FLOAT 0x200 ++#define EF_ARM_VFP_FLOAT 0x400 ++#define EF_ARM_MAVERICK_FLOAT 0x800 ++ ++ ++/* Other constants defined in the ARM ELF spec. version B-01. */ ++/* NB. These conflict with values defined above. */ ++#define EF_ARM_SYMSARESORTED 0x04 ++#define EF_ARM_DYNSYMSUSESEGIDX 0x08 ++#define EF_ARM_MAPSYMSFIRST 0x10 ++#define EF_ARM_EABIMASK 0XFF000000 ++ ++/* Constants defined in AAELF. */ ++#define EF_ARM_BE8 0x00800000 ++#define EF_ARM_LE8 0x00400000 ++ ++#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) ++#define EF_ARM_EABI_UNKNOWN 0x00000000 ++#define EF_ARM_EABI_VER1 0x01000000 ++#define EF_ARM_EABI_VER2 0x02000000 ++#define EF_ARM_EABI_VER3 0x03000000 ++#define EF_ARM_EABI_VER4 0x04000000 ++#define EF_ARM_EABI_VER5 0x05000000 ++ ++/* Additional symbol types for Thumb. */ ++#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ ++#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ ++ ++/* ARM-specific values for sh_flags */ ++#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ ++#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined ++ in the input to a link step. */ ++ ++/* ARM-specific program header flags */ ++#define PF_ARM_SB 0x10000000 /* Segment contains the location ++ addressed by the static base. */ ++#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ ++#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ ++ ++/* Processor specific values for the Phdr p_type field. */ ++#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ ++ ++/* Processor specific values for the Shdr sh_type field. */ ++#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ ++#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ ++#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ ++ ++ ++/* ARM relocs. */ ++ ++#define R_ARM_NONE 0 /* No reloc */ ++#define R_ARM_PC24 1 /* PC relative 26 bit branch */ ++#define R_ARM_ABS32 2 /* Direct 32 bit */ ++#define R_ARM_REL32 3 /* PC relative 32 bit */ ++#define R_ARM_PC13 4 ++#define R_ARM_ABS16 5 /* Direct 16 bit */ ++#define R_ARM_ABS12 6 /* Direct 12 bit */ ++#define R_ARM_THM_ABS5 7 ++#define R_ARM_ABS8 8 /* Direct 8 bit */ ++#define R_ARM_SBREL32 9 ++#define R_ARM_THM_PC22 10 ++#define R_ARM_THM_PC8 11 ++#define R_ARM_AMP_VCALL9 12 ++#define R_ARM_SWI24 13 /* Obsolete static relocation. */ ++#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ ++#define R_ARM_THM_SWI8 14 ++#define R_ARM_XPC25 15 ++#define R_ARM_THM_XPC22 16 ++#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ ++#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ ++#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ ++#define R_ARM_COPY 20 /* Copy symbol at runtime */ ++#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ ++#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ ++#define R_ARM_RELATIVE 23 /* Adjust by program base */ ++#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ ++#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ ++#define R_ARM_GOT32 26 /* 32 bit GOT entry */ ++#define R_ARM_PLT32 27 /* 32 bit PLT address */ ++#define R_ARM_ALU_PCREL_7_0 32 ++#define R_ARM_ALU_PCREL_15_8 33 ++#define R_ARM_ALU_PCREL_23_15 34 ++#define R_ARM_LDR_SBREL_11_0 35 ++#define R_ARM_ALU_SBREL_19_12 36 ++#define R_ARM_ALU_SBREL_27_20 37 ++#define R_ARM_TLS_GOTDESC 90 ++#define R_ARM_TLS_CALL 91 ++#define R_ARM_TLS_DESCSEQ 92 ++#define R_ARM_THM_TLS_CALL 93 ++#define R_ARM_GNU_VTENTRY 100 ++#define R_ARM_GNU_VTINHERIT 101 ++#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ ++#define R_ARM_THM_PC9 103 /* thumb conditional branch */ ++#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic ++ thread local data */ ++#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic ++ thread local data */ ++#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS ++ block */ ++#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of ++ static TLS block offset */ ++#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static ++ TLS block */ ++#define R_ARM_THM_TLS_DESCSEQ 129 ++#define R_ARM_IRELATIVE 160 ++#define R_ARM_RXPC25 249 ++#define R_ARM_RSBREL32 250 ++#define R_ARM_THM_RPC22 251 ++#define R_ARM_RREL32 252 ++#define R_ARM_RABS22 253 ++#define R_ARM_RPC24 254 ++#define R_ARM_RBASE 255 ++/* Keep this the last entry. */ ++#define R_ARM_NUM 256 ++ ++/* IA-64 specific declarations. */ ++ ++/* Processor specific flags for the Ehdr e_flags field. */ ++#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ ++#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ ++#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ ++ ++/* Processor specific values for the Phdr p_type field. */ ++#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ ++#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ ++#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) ++#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) ++#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) ++ ++/* Processor specific flags for the Phdr p_flags field. */ ++#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ ++ ++/* Processor specific values for the Shdr sh_type field. */ ++#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ ++#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ ++ ++/* Processor specific flags for the Shdr sh_flags field. */ ++#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ ++#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ ++ ++/* Processor specific values for the Dyn d_tag field. */ ++#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) ++#define DT_IA_64_NUM 1 ++ ++/* IA-64 relocations. */ ++#define R_IA64_NONE 0x00 /* none */ ++#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ ++#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ ++#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ ++#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ ++#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ ++#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ ++#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ ++#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ ++#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ ++#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ ++#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ ++#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ ++#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ ++#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ ++#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ ++#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ ++#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ ++#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ ++#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ ++#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ ++#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ ++#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ ++#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ ++#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ ++#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ ++#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ ++#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ ++#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ ++#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ ++#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ ++#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ ++#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ ++#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ ++#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ ++#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ ++#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ ++#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ ++#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ ++#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ ++#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ ++#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ ++#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ ++#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ ++#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ ++#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ ++#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ ++#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ ++#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ ++#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ ++#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ ++#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ ++#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ ++#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ ++#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ ++#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ ++#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ ++#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ ++#define R_IA64_COPY 0x84 /* copy relocation */ ++#define R_IA64_SUB 0x85 /* Addend and symbol difference */ ++#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ ++#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ ++#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ ++#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ ++#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ ++#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ ++#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ ++#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ ++#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ ++#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ ++#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ ++#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ ++#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ ++#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ ++#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ ++#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ ++ ++/* SH specific declarations */ ++ ++/* Processor specific flags for the ELF header e_flags field. */ ++#define EF_SH_MACH_MASK 0x1f ++#define EF_SH_UNKNOWN 0x0 ++#define EF_SH1 0x1 ++#define EF_SH2 0x2 ++#define EF_SH3 0x3 ++#define EF_SH_DSP 0x4 ++#define EF_SH3_DSP 0x5 ++#define EF_SH4AL_DSP 0x6 ++#define EF_SH3E 0x8 ++#define EF_SH4 0x9 ++#define EF_SH2E 0xb ++#define EF_SH4A 0xc ++#define EF_SH2A 0xd ++#define EF_SH4_NOFPU 0x10 ++#define EF_SH4A_NOFPU 0x11 ++#define EF_SH4_NOMMU_NOFPU 0x12 ++#define EF_SH2A_NOFPU 0x13 ++#define EF_SH3_NOMMU 0x14 ++#define EF_SH2A_SH4_NOFPU 0x15 ++#define EF_SH2A_SH3_NOFPU 0x16 ++#define EF_SH2A_SH4 0x17 ++#define EF_SH2A_SH3E 0x18 ++ ++/* SH relocs. */ ++#define R_SH_NONE 0 ++#define R_SH_DIR32 1 ++#define R_SH_REL32 2 ++#define R_SH_DIR8WPN 3 ++#define R_SH_IND12W 4 ++#define R_SH_DIR8WPL 5 ++#define R_SH_DIR8WPZ 6 ++#define R_SH_DIR8BP 7 ++#define R_SH_DIR8W 8 ++#define R_SH_DIR8L 9 ++#define R_SH_SWITCH16 25 ++#define R_SH_SWITCH32 26 ++#define R_SH_USES 27 ++#define R_SH_COUNT 28 ++#define R_SH_ALIGN 29 ++#define R_SH_CODE 30 ++#define R_SH_DATA 31 ++#define R_SH_LABEL 32 ++#define R_SH_SWITCH8 33 ++#define R_SH_GNU_VTINHERIT 34 ++#define R_SH_GNU_VTENTRY 35 ++#define R_SH_TLS_GD_32 144 ++#define R_SH_TLS_LD_32 145 ++#define R_SH_TLS_LDO_32 146 ++#define R_SH_TLS_IE_32 147 ++#define R_SH_TLS_LE_32 148 ++#define R_SH_TLS_DTPMOD32 149 ++#define R_SH_TLS_DTPOFF32 150 ++#define R_SH_TLS_TPOFF32 151 ++#define R_SH_GOT32 160 ++#define R_SH_PLT32 161 ++#define R_SH_COPY 162 ++#define R_SH_GLOB_DAT 163 ++#define R_SH_JMP_SLOT 164 ++#define R_SH_RELATIVE 165 ++#define R_SH_GOTOFF 166 ++#define R_SH_GOTPC 167 ++/* Keep this the last entry. */ ++#define R_SH_NUM 256 ++ ++/* S/390 specific definitions. */ ++ ++/* Valid values for the e_flags field. */ ++ ++#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ ++ ++/* Additional s390 relocs */ ++ ++#define R_390_NONE 0 /* No reloc. */ ++#define R_390_8 1 /* Direct 8 bit. */ ++#define R_390_12 2 /* Direct 12 bit. */ ++#define R_390_16 3 /* Direct 16 bit. */ ++#define R_390_32 4 /* Direct 32 bit. */ ++#define R_390_PC32 5 /* PC relative 32 bit. */ ++#define R_390_GOT12 6 /* 12 bit GOT offset. */ ++#define R_390_GOT32 7 /* 32 bit GOT offset. */ ++#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ ++#define R_390_COPY 9 /* Copy symbol at runtime. */ ++#define R_390_GLOB_DAT 10 /* Create GOT entry. */ ++#define R_390_JMP_SLOT 11 /* Create PLT entry. */ ++#define R_390_RELATIVE 12 /* Adjust by program base. */ ++#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ ++#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ ++#define R_390_GOT16 15 /* 16 bit GOT offset. */ ++#define R_390_PC16 16 /* PC relative 16 bit. */ ++#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ ++#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ ++#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ ++#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ ++#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ ++#define R_390_64 22 /* Direct 64 bit. */ ++#define R_390_PC64 23 /* PC relative 64 bit. */ ++#define R_390_GOT64 24 /* 64 bit GOT offset. */ ++#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ ++#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ ++#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ ++#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ ++#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ ++#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ ++#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ ++#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ ++#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ ++#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ ++#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ ++#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ ++#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ ++#define R_390_TLS_GDCALL 38 /* Tag for function call in general ++ dynamic TLS code. */ ++#define R_390_TLS_LDCALL 39 /* Tag for function call in local ++ dynamic TLS code. */ ++#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic ++ thread local data. */ ++#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic ++ thread local data. */ ++#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic ++ thread local data in LE code. */ ++#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic ++ thread local data in LE code. */ ++#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to ++ static TLS block. */ ++#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to ++ static TLS block. */ ++#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS ++ block. */ ++#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS ++ block. */ ++#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ ++#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ ++#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS ++ block. */ ++#define R_390_20 57 /* Direct 20 bit. */ ++#define R_390_GOT20 58 /* 20 bit GOT offset. */ ++#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ ++#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ ++/* Keep this the last entry. */ ++#define R_390_NUM 62 ++ ++ ++/* CRIS relocations. */ ++#define R_CRIS_NONE 0 ++#define R_CRIS_8 1 ++#define R_CRIS_16 2 ++#define R_CRIS_32 3 ++#define R_CRIS_8_PCREL 4 ++#define R_CRIS_16_PCREL 5 ++#define R_CRIS_32_PCREL 6 ++#define R_CRIS_GNU_VTINHERIT 7 ++#define R_CRIS_GNU_VTENTRY 8 ++#define R_CRIS_COPY 9 ++#define R_CRIS_GLOB_DAT 10 ++#define R_CRIS_JUMP_SLOT 11 ++#define R_CRIS_RELATIVE 12 ++#define R_CRIS_16_GOT 13 ++#define R_CRIS_32_GOT 14 ++#define R_CRIS_16_GOTPLT 15 ++#define R_CRIS_32_GOTPLT 16 ++#define R_CRIS_32_GOTREL 17 ++#define R_CRIS_32_PLT_GOTREL 18 ++#define R_CRIS_32_PLT_PCREL 19 ++ ++#define R_CRIS_NUM 20 ++ ++ ++/* AMD x86-64 relocations. */ ++#define R_X86_64_NONE 0 /* No reloc */ ++#define R_X86_64_64 1 /* Direct 64 bit */ ++#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ ++#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ ++#define R_X86_64_PLT32 4 /* 32 bit PLT address */ ++#define R_X86_64_COPY 5 /* Copy symbol at runtime */ ++#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ ++#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ ++#define R_X86_64_RELATIVE 8 /* Adjust by program base */ ++#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative ++ offset to GOT */ ++#define R_X86_64_32 10 /* Direct 32 bit zero extended */ ++#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ ++#define R_X86_64_16 12 /* Direct 16 bit zero extended */ ++#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ ++#define R_X86_64_8 14 /* Direct 8 bit sign extended */ ++#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ ++#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ ++#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ ++#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ ++#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset ++ to two GOT entries for GD symbol */ ++#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset ++ to two GOT entries for LD symbol */ ++#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ ++#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset ++ to GOT entry for IE symbol */ ++#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ ++#define R_X86_64_PC64 24 /* PC relative 64 bit */ ++#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ ++#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative ++ offset to GOT */ ++#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ ++#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset ++ to GOT entry */ ++#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ ++#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ ++#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset ++ to PLT entry */ ++#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ ++#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ ++#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ ++#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS ++ descriptor. */ ++#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ ++#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ ++#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ ++ ++#define R_X86_64_NUM 39 ++ ++ ++/* AM33 relocations. */ ++#define R_MN10300_NONE 0 /* No reloc. */ ++#define R_MN10300_32 1 /* Direct 32 bit. */ ++#define R_MN10300_16 2 /* Direct 16 bit. */ ++#define R_MN10300_8 3 /* Direct 8 bit. */ ++#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ ++#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ ++#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ ++#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ ++#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ ++#define R_MN10300_24 9 /* Direct 24 bit. */ ++#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ ++#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ ++#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ ++#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ ++#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ ++#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ ++#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ ++#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ ++#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ ++#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ ++#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ ++#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ ++#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ ++#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ ++ ++#define R_MN10300_NUM 24 ++ ++ ++/* M32R relocs. */ ++#define R_M32R_NONE 0 /* No reloc. */ ++#define R_M32R_16 1 /* Direct 16 bit. */ ++#define R_M32R_32 2 /* Direct 32 bit. */ ++#define R_M32R_24 3 /* Direct 24 bit. */ ++#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ ++#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ ++#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ ++#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ ++#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ ++#define R_M32R_LO16 9 /* Low 16 bit. */ ++#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ ++#define R_M32R_GNU_VTINHERIT 11 ++#define R_M32R_GNU_VTENTRY 12 ++/* M32R relocs use SHT_RELA. */ ++#define R_M32R_16_RELA 33 /* Direct 16 bit. */ ++#define R_M32R_32_RELA 34 /* Direct 32 bit. */ ++#define R_M32R_24_RELA 35 /* Direct 24 bit. */ ++#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ ++#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ ++#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ ++#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ ++#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ ++#define R_M32R_LO16_RELA 41 /* Low 16 bit */ ++#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ ++#define R_M32R_RELA_GNU_VTINHERIT 43 ++#define R_M32R_RELA_GNU_VTENTRY 44 ++#define R_M32R_REL32 45 /* PC relative 32 bit. */ ++ ++#define R_M32R_GOT24 48 /* 24 bit GOT entry */ ++#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ ++#define R_M32R_COPY 50 /* Copy symbol at runtime */ ++#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ ++#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ ++#define R_M32R_RELATIVE 53 /* Adjust by program base */ ++#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ ++#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ ++#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned ++ low */ ++#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed ++ low */ ++#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ ++#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to ++ GOT with unsigned low */ ++#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to ++ GOT with signed low */ ++#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to ++ GOT */ ++#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT ++ with unsigned low */ ++#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT ++ with signed low */ ++#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ ++#define R_M32R_NUM 256 /* Keep this the last entry. */ ++ ++ ++/* TILEPro relocations. */ ++#define R_TILEPRO_NONE 0 /* No reloc */ ++#define R_TILEPRO_32 1 /* Direct 32 bit */ ++#define R_TILEPRO_16 2 /* Direct 16 bit */ ++#define R_TILEPRO_8 3 /* Direct 8 bit */ ++#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ ++#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ ++#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ ++#define R_TILEPRO_LO16 7 /* Low 16 bit */ ++#define R_TILEPRO_HI16 8 /* High 16 bit */ ++#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ ++#define R_TILEPRO_COPY 10 /* Copy relocation */ ++#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ ++#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ ++#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ ++#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ ++#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ ++#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ ++#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ ++#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ ++#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ ++#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ ++#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ ++#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ ++#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ ++#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ ++#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ ++#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ ++#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ ++#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ ++#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ ++#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ ++#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ ++#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ ++#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ ++#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ ++#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ ++#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ ++#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ ++#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ ++#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ ++#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ ++#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ ++#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ ++#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ ++#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ ++#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ ++#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ ++#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ ++#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ ++#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ ++/* Relocs 56-59 are currently not defined. */ ++#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ ++#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ ++#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ ++#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ ++#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ ++#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ ++#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ ++#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ ++#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ ++#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ ++#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ ++#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ ++ ++#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ ++#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ ++ ++#define R_TILEPRO_NUM 130 ++ ++ ++/* TILE-Gx relocations. */ ++#define R_TILEGX_NONE 0 /* No reloc */ ++#define R_TILEGX_64 1 /* Direct 64 bit */ ++#define R_TILEGX_32 2 /* Direct 32 bit */ ++#define R_TILEGX_16 3 /* Direct 16 bit */ ++#define R_TILEGX_8 4 /* Direct 8 bit */ ++#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ ++#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ ++#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ ++#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ ++#define R_TILEGX_HW0 9 /* hword 0 16-bit */ ++#define R_TILEGX_HW1 10 /* hword 1 16-bit */ ++#define R_TILEGX_HW2 11 /* hword 2 16-bit */ ++#define R_TILEGX_HW3 12 /* hword 3 16-bit */ ++#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ ++#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ ++#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ ++#define R_TILEGX_COPY 16 /* Copy relocation */ ++#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ ++#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ ++#define R_TILEGX_RELATIVE 19 /* Adjust by program base */ ++#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ ++#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ ++#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ ++#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ ++#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ ++#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ ++#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ ++#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ ++#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ ++#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ ++#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ ++#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ ++#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ ++#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ ++#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ ++#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ ++#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ ++#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ ++#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ ++#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ ++#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ ++#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ ++#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ ++#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ ++#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ ++#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ ++#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ ++/* Relocs 66-71 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ ++/* Relocs 76-77 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ ++#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ ++#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ ++#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ ++/* Relocs 90-91 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ ++#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ ++/* Relocs 94-99 are currently not defined. */ ++#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ ++#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ ++#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ ++#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ ++/* Relocs 104-105 are currently not defined. */ ++#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ ++#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ ++#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ ++#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ ++#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ ++#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ ++#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ ++#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ ++#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ ++#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ ++#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ ++#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ ++#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ ++#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ ++#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ ++#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ ++ ++#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ ++#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ ++ ++#define R_TILEGX_NUM 130 ++ ++#endif /* elf.h */ +--- a/scripts/mod/mk_elfconfig.c ++++ b/scripts/mod/mk_elfconfig.c +@@ -2,7 +2,11 @@ + #include + #include + #include ++#ifndef __APPLE__ + #include ++#else ++#include "elf.h" ++#endif + + int + main(int argc, char **argv) +--- a/scripts/mod/modpost.h ++++ b/scripts/mod/modpost.h +@@ -8,7 +8,11 @@ + #include + #include + #include ++#if !(defined(__APPLE__) || defined(__CYGWIN__)) + #include ++#else ++#include "elf.h" ++#endif + + #include "elfconfig.h" + diff --git a/target/linux/generic/hack-5.15/211-darwin-uuid-typedef-clash.patch b/target/linux/generic/hack-5.15/211-darwin-uuid-typedef-clash.patch new file mode 100644 index 0000000000..50a6227148 --- /dev/null +++ b/target/linux/generic/hack-5.15/211-darwin-uuid-typedef-clash.patch @@ -0,0 +1,22 @@ +From e44fc2af1ddc452b6659d08c16973d65c73b7d0a Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Wed, 5 Feb 2020 18:36:43 +0000 +Subject: [PATCH] file2alias: build on macos + +Signed-off-by: Kevin Darbyshire-Bryant +--- + scripts/mod/file2alias.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/scripts/mod/file2alias.c ++++ b/scripts/mod/file2alias.c +@@ -38,6 +38,9 @@ typedef struct { + __u8 b[16]; + } guid_t; + ++#ifdef __APPLE__ ++#define uuid_t compat_uuid_t ++#endif + /* backwards compatibility, don't use in new code */ + typedef struct { + __u8 b[16]; diff --git a/target/linux/generic/hack-5.15/212-tools_portability.patch b/target/linux/generic/hack-5.15/212-tools_portability.patch new file mode 100644 index 0000000000..0d8eb6fb9d --- /dev/null +++ b/target/linux/generic/hack-5.15/212-tools_portability.patch @@ -0,0 +1,110 @@ +From 48232d3d931c95953ce2ddfe7da7bb164aef6a73 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:03:16 +0200 +Subject: fix portability of some includes files in tools/ used on the host + +Signed-off-by: Felix Fietkau +--- + tools/include/tools/be_byteshift.h | 4 ++++ + tools/include/tools/le_byteshift.h | 4 ++++ + tools/include/tools/linux_types.h | 22 ++++++++++++++++++++++ + 3 files changed, 30 insertions(+) + create mode 100644 tools/include/tools/linux_types.h + +--- a/tools/include/tools/be_byteshift.h ++++ b/tools/include/tools/be_byteshift.h +@@ -2,6 +2,10 @@ + #ifndef _TOOLS_BE_BYTESHIFT_H + #define _TOOLS_BE_BYTESHIFT_H + ++#ifndef __linux__ ++#include "linux_types.h" ++#endif ++ + #include + + static inline uint16_t __get_unaligned_be16(const uint8_t *p) +--- a/tools/include/tools/le_byteshift.h ++++ b/tools/include/tools/le_byteshift.h +@@ -2,6 +2,10 @@ + #ifndef _TOOLS_LE_BYTESHIFT_H + #define _TOOLS_LE_BYTESHIFT_H + ++#ifndef __linux__ ++#include "linux_types.h" ++#endif ++ + #include + + static inline uint16_t __get_unaligned_le16(const uint8_t *p) +--- /dev/null ++++ b/tools/include/tools/linux_types.h +@@ -0,0 +1,26 @@ ++#ifndef __LINUX_TYPES_H ++#define __LINUX_TYPES_H ++ ++#include ++ ++typedef int8_t __s8; ++typedef uint8_t __u8; ++typedef uint8_t __be8; ++typedef uint8_t __le8; ++ ++typedef int16_t __s16; ++typedef uint16_t __u16; ++typedef uint16_t __be16; ++typedef uint16_t __le16; ++ ++typedef int32_t __s32; ++typedef uint32_t __u32; ++typedef uint32_t __be32; ++typedef uint32_t __le32; ++ ++typedef int64_t __s64; ++typedef uint64_t __u64; ++typedef uint64_t __be64; ++typedef uint64_t __le64; ++ ++#endif +--- a/tools/include/linux/types.h ++++ b/tools/include/linux/types.h +@@ -7,8 +7,12 @@ + #include + + #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ ++#ifndef __linux__ ++#include ++#else + #include + #include ++#endif + + struct page; + struct kmem_cache; +--- a/tools/perf/pmu-events/jevents.c ++++ b/tools/perf/pmu-events/jevents.c +@@ -1,4 +1,6 @@ ++#ifdef __linux__ + #define _XOPEN_SOURCE 500 /* needed for nftw() */ ++#endif + #define _GNU_SOURCE /* needed for asprintf() */ + + /* Parse event JSON files */ +@@ -35,6 +37,7 @@ + #include + #include + #include ++#include + #include + #include + #include +--- a/tools/perf/pmu-events/json.c ++++ b/tools/perf/pmu-events/json.c +@@ -38,7 +38,6 @@ + #include + #include "jsmn.h" + #include "json.h" +-#include + + + static char *mapfile(const char *fn, size_t *size) diff --git a/target/linux/generic/hack-5.15/214-spidev_h_portability.patch b/target/linux/generic/hack-5.15/214-spidev_h_portability.patch new file mode 100644 index 0000000000..506d50ad4d --- /dev/null +++ b/target/linux/generic/hack-5.15/214-spidev_h_portability.patch @@ -0,0 +1,24 @@ +From be9be95ff10e16a5b4ad36f903978d0cc5747024 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:04:08 +0200 +Subject: kernel: fix linux/spi/spidev.h portability issues with musl + +Felix will try to get this define included into musl + +lede-commit: 795e7cf60de19e7a076a46874fab7bb88b43bbff +Signed-off-by: Felix Fietkau +--- + include/uapi/linux/spi/spidev.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/uapi/linux/spi/spidev.h ++++ b/include/uapi/linux/spi/spidev.h +@@ -121,7 +121,7 @@ struct spi_ioc_transfer { + + /* not all platforms use or _IOC_TYPECHECK() ... */ + #define SPI_MSGSIZE(N) \ +- ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ ++ ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << 13)) \ + ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0) + #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) + diff --git a/target/linux/generic/hack-5.15/220-arm-gc_sections.patch b/target/linux/generic/hack-5.15/220-arm-gc_sections.patch new file mode 100644 index 0000000000..5b36c5ebae --- /dev/null +++ b/target/linux/generic/hack-5.15/220-arm-gc_sections.patch @@ -0,0 +1,123 @@ +From e3d8676f5722b7622685581e06e8f53e6138e3ab Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 15 Jul 2017 23:42:36 +0200 +Subject: use -ffunction-sections, -fdata-sections and --gc-sections + +In combination with kernel symbol export stripping this significantly reduces +the kernel image size. Used on both ARM and MIPS architectures. + +Signed-off-by: Felix Fietkau +Signed-off-by: Jonas Gorski +Signed-off-by: Gabor Juhos +--- +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -114,6 +114,7 @@ config ARM + select HAVE_UID16 + select HAVE_VIRT_CPU_ACCOUNTING_GEN + select IRQ_FORCED_THREADING ++ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION + select MODULES_USE_ELF_REL + select NEED_DMA_MAP_STATE + select OF_EARLY_FLATTREE if OF +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -100,6 +100,7 @@ $(foreach o, $(libfdt_objs) atags_to_fdt + ifdef building_out_of_srctree + $(shell rm -f $(addprefix $(obj)/, fdt_rw.c fdt_ro.c fdt_wip.c fdt.c)) + endif ++KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL)) + + targets := vmlinux vmlinux.lds piggy_data piggy.o \ + lib1funcs.o ashldi3.o bswapsdi2.o \ +--- a/arch/arm/kernel/vmlinux.lds.S ++++ b/arch/arm/kernel/vmlinux.lds.S +@@ -75,7 +75,7 @@ SECTIONS + . = ALIGN(4); + __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { + __start___ex_table = .; +- ARM_MMU_KEEP(*(__ex_table)) ++ KEEP(*(__ex_table)) + __stop___ex_table = .; + } + +@@ -100,24 +100,24 @@ SECTIONS + } + .init.arch.info : { + __arch_info_begin = .; +- *(.arch.info.init) ++ KEEP(*(.arch.info.init)) + __arch_info_end = .; + } + .init.tagtable : { + __tagtable_begin = .; +- *(.taglist.init) ++ KEEP(*(.taglist.init)) + __tagtable_end = .; + } + #ifdef CONFIG_SMP_ON_UP + .init.smpalt : { + __smpalt_begin = .; +- *(.alt.smp.init) ++ KEEP(*(.alt.smp.init)) + __smpalt_end = .; + } + #endif + .init.pv_table : { + __pv_table_begin = .; +- *(.pv_table) ++ KEEP(*(.pv_table)) + __pv_table_end = .; + } + +--- a/arch/arm/include/asm/vmlinux.lds.h ++++ b/arch/arm/include/asm/vmlinux.lds.h +@@ -42,13 +42,13 @@ + #define PROC_INFO \ + . = ALIGN(4); \ + __proc_info_begin = .; \ +- *(.proc.info.init) \ ++ KEEP(*(.proc.info.init)) \ + __proc_info_end = .; + + #define IDMAP_TEXT \ + ALIGN_FUNCTION(); \ + __idmap_text_start = .; \ +- *(.idmap.text) \ ++ KEEP(*(.idmap.text)) \ + __idmap_text_end = .; \ + + #define ARM_DISCARD \ +@@ -109,12 +109,12 @@ + . = ALIGN(8); \ + .ARM.unwind_idx : { \ + __start_unwind_idx = .; \ +- *(.ARM.exidx*) \ ++ KEEP(*(.ARM.exidx*)) \ + __stop_unwind_idx = .; \ + } \ + .ARM.unwind_tab : { \ + __start_unwind_tab = .; \ +- *(.ARM.extab*) \ ++ KEEP(*(.ARM.extab*)) \ + __stop_unwind_tab = .; \ + } + +@@ -126,7 +126,7 @@ + __vectors_lma = .; \ + OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \ + .vectors { \ +- *(.vectors) \ ++ KEEP(*(.vectors)) \ + } \ + .vectors.bhb.loop8 { \ + *(.vectors.bhb.loop8) \ +@@ -144,7 +144,7 @@ + \ + __stubs_lma = .; \ + .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) { \ +- *(.stubs) \ ++ KEEP(*(.stubs)) \ + } \ + ARM_LMA(__stubs, .stubs); \ + . = __stubs_lma + SIZEOF(.stubs); \ diff --git a/target/linux/generic/hack-5.15/221-module_exports.patch b/target/linux/generic/hack-5.15/221-module_exports.patch new file mode 100644 index 0000000000..cd38125f28 --- /dev/null +++ b/target/linux/generic/hack-5.15/221-module_exports.patch @@ -0,0 +1,102 @@ +From b14784e7883390c20ed3ff904892255404a5914b Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:05:53 +0200 +Subject: add an optional config option for stripping all unnecessary symbol exports from the kernel image + +lede-commit: bb5a40c64b7c4f4848509fa0a6625055fc9e66cc +Signed-off-by: Felix Fietkau +--- + include/asm-generic/vmlinux.lds.h | 18 +++++++++++++++--- + include/linux/export.h | 9 ++++++++- + scripts/Makefile.build | 2 +- + 3 files changed, 24 insertions(+), 5 deletions(-) + +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -81,6 +81,16 @@ + #define RO_EXCEPTION_TABLE + #endif + ++#ifndef SYMTAB_KEEP ++#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*))) ++#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*))) ++#endif ++ ++#ifndef SYMTAB_DISCARD ++#define SYMTAB_DISCARD ++#define SYMTAB_DISCARD_GPL ++#endif ++ + /* Align . to a 8 byte boundary equals to maximum function alignment. */ + #define ALIGN_FUNCTION() . = ALIGN(8) + +@@ -473,14 +483,14 @@ + /* Kernel symbol table: Normal symbols */ \ + __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ + __start___ksymtab = .; \ +- KEEP(*(SORT(___ksymtab+*))) \ ++ SYMTAB_KEEP \ + __stop___ksymtab = .; \ + } \ + \ + /* Kernel symbol table: GPL-only symbols */ \ + __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \ + __start___ksymtab_gpl = .; \ +- KEEP(*(SORT(___ksymtab_gpl+*))) \ ++ SYMTAB_KEEP_GPL \ + __stop___ksymtab_gpl = .; \ + } \ + \ +@@ -542,7 +552,7 @@ + \ + /* Kernel symbol table: strings */ \ + __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ +- *(__ksymtab_strings) \ ++ *(__ksymtab_strings+*) \ + } \ + \ + /* __*init sections */ \ +@@ -1019,6 +1029,8 @@ + + #define COMMON_DISCARDS \ + SANITIZER_DISCARDS \ ++ SYMTAB_DISCARD \ ++ SYMTAB_DISCARD_GPL \ + *(.discard) \ + *(.discard.*) \ + *(.modinfo) \ +--- a/include/linux/export.h ++++ b/include/linux/export.h +@@ -82,6 +82,12 @@ struct kernel_symbol { + + #else + ++#ifdef MODULE ++#define __EXPORT_SUFFIX(sym) ++#else ++#define __EXPORT_SUFFIX(sym) "+" #sym ++#endif ++ + /* + * For every exported symbol, do the following: + * +@@ -99,7 +105,7 @@ struct kernel_symbol { + extern const char __kstrtab_##sym[]; \ + extern const char __kstrtabns_##sym[]; \ + __CRC_SYMBOL(sym, sec); \ +- asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \ ++ asm(" .section \"__ksymtab_strings" __EXPORT_SUFFIX(sym) "\",\"aMS\",%progbits,1 \n" \ + "__kstrtab_" #sym ": \n" \ + " .asciz \"" #sym "\" \n" \ + "__kstrtabns_" #sym ": \n" \ +--- a/scripts/Makefile.build ++++ b/scripts/Makefile.build +@@ -367,7 +367,7 @@ targets += $(lib-y) $(always-y) $(MAKECM + # Linker scripts preprocessor (.lds.S -> .lds) + # --------------------------------------------------------------------------- + quiet_cmd_cpp_lds_S = LDS $@ +- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \ ++ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -U$(ARCH) \ + -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< + + $(obj)/%.lds: $(src)/%.lds.S FORCE diff --git a/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch b/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch new file mode 100644 index 0000000000..906527faf9 --- /dev/null +++ b/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch @@ -0,0 +1,34 @@ +From b3d00b452467f621317953d9e4c6f9ae8dcfd271 Mon Sep 17 00:00:00 2001 +From: Imre Kaloz +Date: Fri, 7 Jul 2017 17:06:55 +0200 +Subject: use the openwrt lzma options for now + +lede-commit: 548de949f392049420a6a1feeef118b30ab8ea8c +Signed-off-by: Imre Kaloz +--- + lib/decompress.c | 1 + + scripts/Makefile.lib | 2 +- + usr/gen_initramfs_list.sh | 10 +++++----- + 3 files changed, 7 insertions(+), 6 deletions(-) + +--- a/lib/decompress.c ++++ b/lib/decompress.c +@@ -53,6 +53,7 @@ static const struct compress_format comp + { {0x1f, 0x9e}, "gzip", gunzip }, + { {0x42, 0x5a}, "bzip2", bunzip2 }, + { {0x5d, 0x00}, "lzma", unlzma }, ++ { {0x6d, 0x00}, "lzma-openwrt", unlzma }, + { {0xfd, 0x37}, "xz", unxz }, + { {0x89, 0x4c}, "lzo", unlzo }, + { {0x02, 0x21}, "lz4", unlz4 }, +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -370,7 +370,7 @@ quiet_cmd_bzip2 = BZIP2 $@ + # --------------------------------------------------------------------------- + + quiet_cmd_lzma = LZMA $@ +- cmd_lzma = { cat $(real-prereqs) | $(LZMA) -9; $(size_append); } > $@ ++ cmd_lzma = { cat $(real-prereqs) | $(LZMA) e -d20 -lc1 -lp2 -pb2 -eos -si -so; $(size_append); } > $@ + + quiet_cmd_lzo = LZO $@ + cmd_lzo = { cat $(real-prereqs) | $(KLZOP) -9; $(size_append); } > $@ diff --git a/target/linux/generic/hack-5.15/249-udp-tunnel-selection.patch b/target/linux/generic/hack-5.15/249-udp-tunnel-selection.patch new file mode 100644 index 0000000000..2c74298dfe --- /dev/null +++ b/target/linux/generic/hack-5.15/249-udp-tunnel-selection.patch @@ -0,0 +1,11 @@ +--- a/net/ipv4/Kconfig ++++ b/net/ipv4/Kconfig +@@ -315,7 +315,7 @@ config NET_IPVTI + on top. + + config NET_UDP_TUNNEL +- tristate ++ tristate "IP: UDP tunneling support" + select NET_IP_TUNNEL + default n + diff --git a/target/linux/generic/hack-5.15/250-netfilter_depends.patch b/target/linux/generic/hack-5.15/250-netfilter_depends.patch new file mode 100644 index 0000000000..b27b440157 --- /dev/null +++ b/target/linux/generic/hack-5.15/250-netfilter_depends.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Subject: hack: net: remove bogus netfilter dependencies + +lede-commit: 589d2a377dee27d206fc3725325309cf649e4df6 +Signed-off-by: Felix Fietkau +--- + net/netfilter/Kconfig | 2 -- + 1 file changed, 2 deletions(-) + +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -228,7 +228,6 @@ config NF_CONNTRACK_FTP + + config NF_CONNTRACK_H323 + tristate "H.323 protocol support" +- depends on IPV6 || IPV6=n + depends on NETFILTER_ADVANCED + help + H.323 is a VoIP signalling protocol from ITU-T. As one of the most +@@ -1072,7 +1071,6 @@ config NETFILTER_XT_TARGET_SECMARK + + config NETFILTER_XT_TARGET_TCPMSS + tristate '"TCPMSS" target support' +- depends on IPV6 || IPV6=n + default m if NETFILTER_ADVANCED=n + help + This option adds a `TCPMSS' target, which allows you to alter the diff --git a/target/linux/generic/hack-5.15/251-kconfig.patch b/target/linux/generic/hack-5.15/251-kconfig.patch new file mode 100644 index 0000000000..34a63eaa7c --- /dev/null +++ b/target/linux/generic/hack-5.15/251-kconfig.patch @@ -0,0 +1,199 @@ +From da3c50704f14132f4adf80d48e9a4cd5d46e54c9 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 7 Jul 2017 17:09:21 +0200 +Subject: kconfig: owrt specifc dependencies + +Signed-off-by: John Crispin +--- + crypto/Kconfig | 10 +++++----- + drivers/bcma/Kconfig | 1 + + drivers/ssb/Kconfig | 3 ++- + lib/Kconfig | 8 ++++---- + net/netfilter/Kconfig | 2 +- + net/wireless/Kconfig | 17 ++++++++++------- + sound/core/Kconfig | 4 ++-- + 7 files changed, 25 insertions(+), 20 deletions(-) + +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -33,7 +33,7 @@ config CRYPTO_FIPS + this is. + + config CRYPTO_ALGAPI +- tristate ++ tristate "ALGAPI" + select CRYPTO_ALGAPI2 + help + This option provides the API for cryptographic algorithms. +@@ -42,7 +42,7 @@ config CRYPTO_ALGAPI2 + tristate + + config CRYPTO_AEAD +- tristate ++ tristate "AEAD" + select CRYPTO_AEAD2 + select CRYPTO_ALGAPI + +@@ -53,7 +53,7 @@ config CRYPTO_AEAD2 + select CRYPTO_RNG2 + + config CRYPTO_SKCIPHER +- tristate ++ tristate "SKCIPHER" + select CRYPTO_SKCIPHER2 + select CRYPTO_ALGAPI + +@@ -63,7 +63,7 @@ config CRYPTO_SKCIPHER2 + select CRYPTO_RNG2 + + config CRYPTO_HASH +- tristate ++ tristate "HASH" + select CRYPTO_HASH2 + select CRYPTO_ALGAPI + +@@ -72,7 +72,7 @@ config CRYPTO_HASH2 + select CRYPTO_ALGAPI2 + + config CRYPTO_RNG +- tristate ++ tristate "RNG" + select CRYPTO_RNG2 + select CRYPTO_ALGAPI + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -16,6 +16,7 @@ if BCMA + # Support for Block-I/O. SELECT this from the driver that needs it. + config BCMA_BLOCKIO + bool ++ default y + + config BCMA_HOST_PCI_POSSIBLE + bool +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -29,6 +29,7 @@ config SSB_SPROM + config SSB_BLOCKIO + bool + depends on SSB ++ default y + + config SSB_PCIHOST_POSSIBLE + bool +@@ -49,7 +50,7 @@ config SSB_PCIHOST + config SSB_B43_PCI_BRIDGE + bool + depends on SSB_PCIHOST +- default n ++ default y + + config SSB_PCMCIAHOST_POSSIBLE + bool +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -418,16 +418,16 @@ config BCH_CONST_T + # Textsearch support is select'ed if needed + # + config TEXTSEARCH +- bool ++ bool "Textsearch support" + + config TEXTSEARCH_KMP +- tristate ++ tristate "Textsearch KMP" + + config TEXTSEARCH_BM +- tristate ++ tristate "Textsearch BM" + + config TEXTSEARCH_FSM +- tristate ++ tristate "Textsearch FSM" + + config BTREE + bool +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -11,7 +11,7 @@ config NETFILTER_INGRESS + infrastructure. + + config NETFILTER_NETLINK +- tristate ++ tristate "Netfilter NFNETLINK interface" + + config NETFILTER_FAMILY_BRIDGE + bool +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config WIRELESS_EXT +- bool ++ bool "Wireless extensions" + + config WEXT_CORE + def_bool y +@@ -12,10 +12,10 @@ config WEXT_PROC + depends on WEXT_CORE + + config WEXT_SPY +- bool ++ bool "WEXT_SPY" + + config WEXT_PRIV +- bool ++ bool "WEXT_PRIV" + + config CFG80211 + tristate "cfg80211 - wireless configuration API" +@@ -204,7 +204,7 @@ config CFG80211_WEXT_EXPORT + endif # CFG80211 + + config LIB80211 +- tristate ++ tristate "LIB80211" + default n + help + This options enables a library of common routines used +@@ -213,17 +213,17 @@ config LIB80211 + Drivers should select this themselves if needed. + + config LIB80211_CRYPT_WEP +- tristate ++ tristate "LIB80211_CRYPT_WEP" + select CRYPTO_LIB_ARC4 + + config LIB80211_CRYPT_CCMP +- tristate ++ tristate "LIB80211_CRYPT_CCMP" + select CRYPTO + select CRYPTO_AES + select CRYPTO_CCM + + config LIB80211_CRYPT_TKIP +- tristate ++ tristate "LIB80211_CRYPT_TKIP" + select CRYPTO_LIB_ARC4 + + config LIB80211_DEBUG +--- a/sound/core/Kconfig ++++ b/sound/core/Kconfig +@@ -17,7 +17,7 @@ config SND_DMAENGINE_PCM + tristate + + config SND_HWDEP +- tristate ++ tristate "Sound hardware support" + + config SND_SEQ_DEVICE + tristate +@@ -27,7 +27,7 @@ config SND_RAWMIDI + select SND_SEQ_DEVICE if SND_SEQUENCER != n + + config SND_COMPRESS_OFFLOAD +- tristate ++ tristate "Compression offloading support" + + config SND_JACK + bool diff --git a/target/linux/generic/hack-5.15/252-SATA_PMP.patch b/target/linux/generic/hack-5.15/252-SATA_PMP.patch new file mode 100644 index 0000000000..6502d1d6ed --- /dev/null +++ b/target/linux/generic/hack-5.15/252-SATA_PMP.patch @@ -0,0 +1,23 @@ +From 8c817e33be829c7249c2cfd59ff48ad5fac6a31d Mon Sep 17 00:00:00 2001 +From: Sungbo Eo +Date: Fri, 7 Jul 2017 17:09:21 +0200 +Subject: [PATCH] kconfig: solidify SATA_PMP config + +SATA_PMP option in kernel config file disappears for every kernel_oldconfig refresh. +To prevent this, SATA_HOST is now selected automatically when SATA_PMP is enabled. +This patch can be dropped if SATA_MV is ever re-added into the config. +--- + drivers/ata/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -112,7 +112,7 @@ config SATA_ZPODD + + config SATA_PMP + bool "SATA Port Multiplier support" +- depends on SATA_HOST ++ select SATA_HOST + default y + help + This option adds support for SATA Port Multipliers diff --git a/target/linux/generic/hack-5.15/253-ksmbd-config.patch b/target/linux/generic/hack-5.15/253-ksmbd-config.patch new file mode 100644 index 0000000000..c2b2a96b9c --- /dev/null +++ b/target/linux/generic/hack-5.15/253-ksmbd-config.patch @@ -0,0 +1,22 @@ +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -2379,7 +2379,7 @@ config PADATA + bool + + config ASN1 +- tristate ++ tristate "ASN1" + help + Build a simple ASN.1 grammar compiler that produces a bytecode output + that can be interpreted by the ASN.1 stream decoder and used to +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -589,7 +589,7 @@ config LIBFDT + bool + + config OID_REGISTRY +- tristate ++ tristate "OID" + help + Enable fast lookup object identifier registry. + diff --git a/target/linux/generic/hack-5.15/259-regmap_dynamic.patch b/target/linux/generic/hack-5.15/259-regmap_dynamic.patch new file mode 100644 index 0000000000..bc81a7285c --- /dev/null +++ b/target/linux/generic/hack-5.15/259-regmap_dynamic.patch @@ -0,0 +1,135 @@ +From 811d9e2268a62b830cfe93cd8bc929afcb8b198b Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 15 Jul 2017 21:12:38 +0200 +Subject: kernel: move regmap bloat out of the kernel image if it is only being used in modules + +lede-commit: 96f39119815028073583e4fca3a9c5fe9141e998 +Signed-off-by: Felix Fietkau +--- + drivers/base/regmap/Kconfig | 15 ++++++++++----- + drivers/base/regmap/Makefile | 12 ++++++++---- + drivers/base/regmap/regmap.c | 3 +++ + include/linux/regmap.h | 2 +- + 4 files changed, 22 insertions(+), 10 deletions(-) + +--- a/drivers/base/regmap/Kconfig ++++ b/drivers/base/regmap/Kconfig +@@ -4,9 +4,8 @@ + # subsystems should select the appropriate symbols. + + config REGMAP +- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM) + select IRQ_DOMAIN if REGMAP_IRQ +- bool ++ tristate + + config REGCACHE_COMPRESSED + select LZO_COMPRESS +@@ -14,46 +13,59 @@ config REGCACHE_COMPRESSED + bool + + config REGMAP_AC97 ++ select REGMAP + tristate + + config REGMAP_I2C + tristate ++ select REGMAP + depends on I2C + + config REGMAP_SLIMBUS + tristate ++ select REGMAP + depends on SLIMBUS + + config REGMAP_SPI + tristate ++ select REGMAP ++ depends on SPI_MASTER + depends on SPI + + config REGMAP_SPMI + tristate ++ select REGMAP + depends on SPMI + + config REGMAP_W1 + tristate ++ select REGMAP + depends on W1 + + config REGMAP_MMIO + tristate ++ select REGMAP + + config REGMAP_IRQ + bool ++ select REGMAP + + config REGMAP_SOUNDWIRE + tristate ++ select REGMAP + depends on SOUNDWIRE + + config REGMAP_SCCB + tristate ++ select REGMAP + depends on I2C + + config REGMAP_I3C + tristate ++ select REGMAP + depends on I3C + + config REGMAP_SPI_AVMM + tristate ++ select REGMAP + depends on SPI +--- a/drivers/base/regmap/Makefile ++++ b/drivers/base/regmap/Makefile +@@ -2,10 +2,14 @@ + # For include/trace/define_trace.h to include trace.h + CFLAGS_regmap.o := -I$(src) + +-obj-$(CONFIG_REGMAP) += regmap.o regcache.o +-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o +-obj-$(CONFIG_REGCACHE_COMPRESSED) += regcache-lzo.o +-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o ++regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-flat.o ++ifdef CONFIG_DEBUG_FS ++regmap-core-objs += regmap-debugfs.o ++endif ++ifdef CONFIG_REGCACHE_COMPRESSED ++regmap-core-objs += regcache-lzo.o ++endif ++obj-$(CONFIG_REGMAP) += regmap-core.o + obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o + obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o + obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3298,3 +3299,5 @@ static int __init regmap_initcall(void) + return 0; + } + postcore_initcall(regmap_initcall); ++ ++MODULE_LICENSE("GPL"); +--- a/include/linux/regmap.h ++++ b/include/linux/regmap.h +@@ -179,7 +179,7 @@ struct reg_sequence { + __ret ?: __tmp; \ + }) + +-#ifdef CONFIG_REGMAP ++#if IS_REACHABLE(CONFIG_REGMAP) + + enum regmap_endian { + /* Unspecified -> 0 -> Backwards compatible default */ diff --git a/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch b/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch new file mode 100644 index 0000000000..1eab709c46 --- /dev/null +++ b/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch @@ -0,0 +1,52 @@ +From fd1799b0bf5efa46dd3e6dfbbf3955564807e508 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:12:51 +0200 +Subject: kernel: prevent cryptomgr from pulling in useless extra dependencies for tests that are not run + +Reduces kernel size after LZMA by about 5k on MIPS + +lede-commit: 044c316167e076479a344c59905e5b435b84a77f +Signed-off-by: Felix Fietkau +--- + crypto/Kconfig | 13 ++++++------- + crypto/algboss.c | 4 ++++ + 2 files changed, 10 insertions(+), 7 deletions(-) + +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -120,13 +120,13 @@ config CRYPTO_MANAGER + cbc(aes). + + config CRYPTO_MANAGER2 +- def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y) +- select CRYPTO_AEAD2 +- select CRYPTO_HASH2 +- select CRYPTO_SKCIPHER2 +- select CRYPTO_AKCIPHER2 +- select CRYPTO_KPP2 +- select CRYPTO_ACOMP2 ++ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y && !CRYPTO_MANAGER_DISABLE_TESTS) ++ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_SKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS ++ select CRYPTO_ACOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS + + config CRYPTO_USER + tristate "Userspace cryptographic algorithm configuration" +--- a/crypto/algboss.c ++++ b/crypto/algboss.c +@@ -230,8 +230,12 @@ static int cryptomgr_schedule_test(struc + type = alg->cra_flags; + + /* Do not test internal algorithms. */ ++#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS ++ type |= CRYPTO_ALG_TESTED; ++#else + if (type & CRYPTO_ALG_INTERNAL) + type |= CRYPTO_ALG_TESTED; ++#endif + + param->type = type; + diff --git a/target/linux/generic/hack-5.15/261-lib-arc4-unhide.patch b/target/linux/generic/hack-5.15/261-lib-arc4-unhide.patch new file mode 100644 index 0000000000..a7668acfad --- /dev/null +++ b/target/linux/generic/hack-5.15/261-lib-arc4-unhide.patch @@ -0,0 +1,15 @@ +This makes it possible to select CONFIG_CRYPTO_LIB_ARC4 directly. We +need this to be able to compile this into the kernel and make use of it +from backports. + +--- a/lib/crypto/Kconfig ++++ b/lib/crypto/Kconfig +@@ -6,7 +6,7 @@ config CRYPTO_LIB_AES + tristate + + config CRYPTO_LIB_ARC4 +- tristate ++ tristate "ARC4 cipher library" + + config CRYPTO_ARCH_HAVE_LIB_BLAKE2S + tristate diff --git a/target/linux/generic/hack-5.15/280-rfkill-stubs.patch b/target/linux/generic/hack-5.15/280-rfkill-stubs.patch new file mode 100644 index 0000000000..2e48aea1cf --- /dev/null +++ b/target/linux/generic/hack-5.15/280-rfkill-stubs.patch @@ -0,0 +1,84 @@ +From 236c1acdfef5958010ac9814a9872e0a46fd78ee Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 7 Jul 2017 17:13:44 +0200 +Subject: rfkill: add fake rfkill support + +allow building of modules depending on RFKILL even if RFKILL is not enabled. + +Signed-off-by: John Crispin +--- + include/linux/rfkill.h | 2 +- + net/Makefile | 2 +- + net/rfkill/Kconfig | 14 +++++++++----- + net/rfkill/Makefile | 2 +- + 4 files changed, 12 insertions(+), 8 deletions(-) + +--- a/include/linux/rfkill.h ++++ b/include/linux/rfkill.h +@@ -64,7 +64,7 @@ struct rfkill_ops { + int (*set_block)(void *data, bool blocked); + }; + +-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) ++#if defined(CONFIG_RFKILL_FULL) || defined(CONFIG_RFKILL_FULL_MODULE) + /** + * rfkill_alloc - Allocate rfkill structure + * @name: name of the struct -- the string is not copied internally +--- a/net/Makefile ++++ b/net/Makefile +@@ -53,7 +53,7 @@ obj-$(CONFIG_TIPC) += tipc/ + obj-$(CONFIG_NETLABEL) += netlabel/ + obj-$(CONFIG_IUCV) += iucv/ + obj-$(CONFIG_SMC) += smc/ +-obj-$(CONFIG_RFKILL) += rfkill/ ++obj-$(CONFIG_RFKILL_FULL) += rfkill/ + obj-$(CONFIG_NET_9P) += 9p/ + obj-$(CONFIG_CAIF) += caif/ + ifneq ($(CONFIG_DCB),) +--- a/net/rfkill/Kconfig ++++ b/net/rfkill/Kconfig +@@ -2,7 +2,11 @@ + # + # RF switch subsystem configuration + # +-menuconfig RFKILL ++config RFKILL ++ bool ++ default y ++ ++menuconfig RFKILL_FULL + tristate "RF switch subsystem support" + help + Say Y here if you want to have control over RF switches +@@ -14,19 +18,19 @@ menuconfig RFKILL + # LED trigger support + config RFKILL_LEDS + bool +- depends on RFKILL ++ depends on RFKILL_FULL + depends on LEDS_TRIGGERS = y || RFKILL = LEDS_TRIGGERS + default y + + config RFKILL_INPUT + bool "RF switch input support" if EXPERT +- depends on RFKILL ++ depends on RFKILL_FULL + depends on INPUT = y || RFKILL = INPUT + default y if !EXPERT + + config RFKILL_GPIO + tristate "GPIO RFKILL driver" +- depends on RFKILL ++ depends on RFKILL_FULL + depends on GPIOLIB || COMPILE_TEST + default n + help +--- a/net/rfkill/Makefile ++++ b/net/rfkill/Makefile +@@ -5,5 +5,5 @@ + + rfkill-y += core.o + rfkill-$(CONFIG_RFKILL_INPUT) += input.o +-obj-$(CONFIG_RFKILL) += rfkill.o ++obj-$(CONFIG_RFKILL_FULL) += rfkill.o + obj-$(CONFIG_RFKILL_GPIO) += rfkill-gpio.o diff --git a/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch new file mode 100644 index 0000000000..fe89de7e08 --- /dev/null +++ b/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch @@ -0,0 +1,64 @@ +From: Ben Menchaca +Date: Fri, 7 Jun 2013 18:35:22 -0500 +Subject: MIPS: r4k_cache: use more efficient cache blast + +Optimize the compiler output for larger cache blast cases that are +common for DMA-based networking. + +Signed-off-by: Ben Menchaca +Signed-off-by: Felix Fietkau +--- +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -296,14 +296,46 @@ static inline void prot##extra##blast_## + unsigned long end) \ + { \ + unsigned long lsize = cpu_##desc##_line_size(); \ ++ unsigned long lsize_2 = lsize * 2; \ ++ unsigned long lsize_3 = lsize * 3; \ ++ unsigned long lsize_4 = lsize * 4; \ ++ unsigned long lsize_5 = lsize * 5; \ ++ unsigned long lsize_6 = lsize * 6; \ ++ unsigned long lsize_7 = lsize * 7; \ ++ unsigned long lsize_8 = lsize * 8; \ + unsigned long addr = start & ~(lsize - 1); \ +- unsigned long aend = (end - 1) & ~(lsize - 1); \ ++ unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ ++ int lines = (aend - addr) / lsize; \ + \ +- while (1) { \ ++ while (lines >= 8) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ prot##cache_op(hitop, addr + lsize_2); \ ++ prot##cache_op(hitop, addr + lsize_3); \ ++ prot##cache_op(hitop, addr + lsize_4); \ ++ prot##cache_op(hitop, addr + lsize_5); \ ++ prot##cache_op(hitop, addr + lsize_6); \ ++ prot##cache_op(hitop, addr + lsize_7); \ ++ addr += lsize_8; \ ++ lines -= 8; \ ++ } \ ++ \ ++ if (lines & 0x4) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ prot##cache_op(hitop, addr + lsize_2); \ ++ prot##cache_op(hitop, addr + lsize_3); \ ++ addr += lsize_4; \ ++ } \ ++ \ ++ if (lines & 0x2) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ addr += lsize_2; \ ++ } \ ++ \ ++ if (lines & 0x1) { \ + prot##cache_op(hitop, addr); \ +- if (addr == aend) \ +- break; \ +- addr += lsize; \ + } \ + } + diff --git a/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch b/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch new file mode 100644 index 0000000000..4edf527246 --- /dev/null +++ b/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch @@ -0,0 +1,38 @@ +From: John Crispin +Subject: hack: kernel: add generic image_cmdline hack to MIPS targets + +lede-commit: d59f5b3a987a48508257a0ddbaeadc7909f9f976 +Signed-off-by: Gabor Juhos +--- + arch/mips/Kconfig | 4 ++++ + arch/mips/kernel/head.S | 6 ++++++ + 2 files changed, 10 insertions(+) + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -1170,6 +1170,10 @@ config MIPS_MSC + config SYNC_R4K + bool + ++config IMAGE_CMDLINE_HACK ++ bool "OpenWrt specific image command line hack" ++ default n ++ + config NO_IOPORT_MAP + def_bool n + +--- a/arch/mips/kernel/head.S ++++ b/arch/mips/kernel/head.S +@@ -79,6 +79,12 @@ FEXPORT(__kernel_entry) + j kernel_entry + #endif /* CONFIG_BOOT_RAW */ + ++#ifdef CONFIG_IMAGE_CMDLINE_HACK ++ .ascii "CMDLINE:" ++EXPORT(__image_cmdline) ++ .fill 0x400 ++#endif /* CONFIG_IMAGE_CMDLINE_HACK */ ++ + __REF + + NESTED(kernel_entry, 16, sp) # kernel entry point diff --git a/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch b/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch new file mode 100644 index 0000000000..4bb438295d --- /dev/null +++ b/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch @@ -0,0 +1,38 @@ +From 107c0964cb8db7ca28ac5199426414fdab3c274d Mon Sep 17 00:00:00 2001 +From: "Alexandros C. Couloumbis" +Date: Fri, 7 Jul 2017 17:14:51 +0200 +Subject: hack: arch: powerpc: drop register save/restore library from modules + +Upstream GCC uses a libgcc function for saving/restoring registers. This +makes the code bigger, and upstream kernels need to carry that function +for every single kernel module. Our GCC is patched to avoid those +references, so we can drop the extra bloat for modules. + +lede-commit: e8e1084654f50904e6bf77b70b2de3f137d7b3ec +Signed-off-by: Alexandros C. Couloumbis +--- + arch/powerpc/Makefile | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/powerpc/Makefile ++++ b/arch/powerpc/Makefile +@@ -61,19 +61,6 @@ machine-$(CONFIG_PPC64) += 64 + machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le + UTS_MACHINE := $(subst $(space),,$(machine-y)) + +-# XXX This needs to be before we override LD below +-ifdef CONFIG_PPC32 +-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o +-else +-ifeq ($(call ld-ifversion, -ge, 225000000, y),y) +-# Have the linker provide sfpr if possible. +-# There is a corresponding test in arch/powerpc/lib/Makefile +-KBUILD_LDFLAGS_MODULE += --save-restore-funcs +-else +-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o +-endif +-endif +- + ifdef CONFIG_CPU_LITTLE_ENDIAN + KBUILD_CFLAGS += -mlittle-endian + KBUILD_LDFLAGS += -EL diff --git a/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch b/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch new file mode 100644 index 0000000000..04cf52b096 --- /dev/null +++ b/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch @@ -0,0 +1,85 @@ +From f9760b158f610b1792a222cc924073724c061bfb Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 7 Apr 2021 22:37:57 +0100 +Subject: [PATCH 1/2] mtd: super: don't reply on mtdblock device minor +To: linux-mtd@lists.infradead.org +Cc: Vignesh Raghavendra , + Richard Weinberger , + Miquel Raynal , + David Woodhouse + +For blktrans devices with partitions (ie. part_bits != 0) the +assumption that the minor number of the mtdblock device matches +the mtdnum doesn't hold true. +Properly resolve mtd device from blktrans layer instead. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/mtdsuper.c | 33 ++++++++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/mtdsuper.c ++++ b/drivers/mtd/mtdsuper.c +@@ -9,6 +9,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -121,7 +122,8 @@ int get_tree_mtd(struct fs_context *fc, + { + #ifdef CONFIG_BLOCK + struct block_device *bdev; +- int ret, major; ++ struct mtd_blktrans_dev *blktrans_dev; ++ int ret, major, part_bits; + #endif + int mtdnr; + +@@ -169,21 +171,38 @@ int get_tree_mtd(struct fs_context *fc, + /* try the old way - the hack where we allowed users to mount + * /dev/mtdblock$(n) but didn't actually _use_ the blockdev + */ +- bdev = lookup_bdev(fc->source); ++ bdev = blkdev_get_by_path(fc->source, FMODE_READ, NULL); + if (IS_ERR(bdev)) { + ret = PTR_ERR(bdev); + errorf(fc, "MTD: Couldn't look up '%s': %d", fc->source, ret); + return ret; + } +- pr_debug("MTDSB: lookup_bdev() returned 0\n"); ++ pr_debug("MTDSB: blkdev_get_by_path() returned 0\n"); + + major = MAJOR(bdev->bd_dev); +- mtdnr = MINOR(bdev->bd_dev); +- bdput(bdev); + +- if (major == MTD_BLOCK_MAJOR) +- return mtd_get_sb_by_nr(fc, mtdnr, fill_super); ++ if (major == MTD_BLOCK_MAJOR) { ++ if (!bdev->bd_disk) { ++ blkdev_put(bdev, FMODE_READ); ++ BUG(); ++ return -EINVAL; ++ } ++ ++ blktrans_dev = (struct mtd_blktrans_dev *)(bdev->bd_disk->private_data); ++ if (!blktrans_dev || !blktrans_dev->tr) { ++ blkdev_put(bdev, FMODE_READ); ++ BUG(); ++ return -EINVAL; ++ } ++ mtdnr = blktrans_dev->devnum; ++ part_bits = blktrans_dev->tr->part_bits; ++ blkdev_put(bdev, FMODE_READ); ++ if (MINOR(bdev->bd_dev) != (mtdnr << part_bits)) ++ return -EINVAL; + ++ return mtd_get_sb_by_nr(fc, mtdnr, fill_super); ++ } ++ blkdev_put(bdev, FMODE_READ); + #endif /* CONFIG_BLOCK */ + + if (!(fc->sb_flags & SB_SILENT)) diff --git a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch new file mode 100644 index 0000000000..988d900b31 --- /dev/null +++ b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -0,0 +1,98 @@ +From 0bccc3722bdd88e8ae995e77ef9f7b77ee4cbdee Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 7 Apr 2021 22:45:54 +0100 +Subject: [PATCH 2/2] mtd: blktrans: call add disks after mtd device +To: linux-mtd@lists.infradead.org +Cc: Vignesh Raghavendra , + Richard Weinberger , + Miquel Raynal , + David Woodhouse + +Calling device_add_disk while holding mtd_table_mutex leads +to deadlock in case part_bits!=0 as block partition parsers +will try to open the newly created disks, trying to acquire +mutex once again. +Move device_add_disk to additional function called after +add partitions of an MTD device have been added and locks +have been released. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/mtd_blkdevs.c | 33 ++++++++++++++++++++++++++------- + drivers/mtd/mtdcore.c | 3 +++ + include/linux/mtd/blktrans.h | 1 + + 3 files changed, 30 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -457,13 +457,6 @@ int add_mtd_blktrans_dev(struct mtd_blkt + if (new->readonly) + set_disk_ro(gd, 1); + +- device_add_disk(&new->mtd->dev, gd, NULL); +- +- if (new->disk_attributes) { +- ret = sysfs_create_group(&disk_to_dev(gd)->kobj, +- new->disk_attributes); +- WARN_ON(ret); +- } + return 0; + error4: + kfree(new->tag_set); +@@ -475,6 +468,27 @@ error1: + return ret; + } + ++void register_mtd_blktrans_devs(void) ++{ ++ struct mtd_blktrans_ops *tr; ++ struct mtd_blktrans_dev *dev, *next; ++ int ret; ++ ++ list_for_each_entry(tr, &blktrans_majors, list) { ++ list_for_each_entry_safe(dev, next, &tr->devs, list) { ++ if (dev->disk->flags & GENHD_FL_UP) ++ continue; ++ ++ device_add_disk(&dev->mtd->dev, dev->disk, NULL); ++ if (dev->disk_attributes) { ++ ret = sysfs_create_group(&disk_to_dev(dev->disk)->kobj, ++ dev->disk_attributes); ++ WARN_ON(ret); ++ } ++ } ++ } ++} ++ + int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) + { + unsigned long flags; +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -31,6 +31,7 @@ + + #include + #include ++#include + + #include "mtdcore.h" + +@@ -851,6 +852,8 @@ int mtd_device_parse_register(struct mtd + register_reboot_notifier(&mtd->reboot_notifier); + } + ++ register_mtd_blktrans_devs(); ++ + out: + if (ret && device_is_registered(&mtd->dev)) + del_mtd_device(mtd); +--- a/include/linux/mtd/blktrans.h ++++ b/include/linux/mtd/blktrans.h +@@ -76,6 +76,6 @@ extern int deregister_mtd_blktrans(struc + extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); + extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); + extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev); +- ++extern void register_mtd_blktrans_devs(void); + + #endif /* __MTD_TRANS_H__ */ diff --git a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch new file mode 100644 index 0000000000..7816356227 --- /dev/null +++ b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch @@ -0,0 +1,224 @@ +--- a/block/blk.h ++++ b/block/blk.h +@@ -361,6 +361,8 @@ char *disk_name(struct gendisk *hd, int + #define ADDPART_FLAG_NONE 0 + #define ADDPART_FLAG_RAID 1 + #define ADDPART_FLAG_WHOLEDISK 2 ++#define ADDPART_FLAG_READONLY 4 ++#define ADDPART_FLAG_ROOTDEV 8 + void delete_partition(struct hd_struct *part); + int bdev_add_partition(struct block_device *bdev, int partno, + sector_t start, sector_t length); +--- a/block/partitions/Kconfig ++++ b/block/partitions/Kconfig +@@ -101,6 +101,13 @@ config ATARI_PARTITION + Say Y here if you would like to use hard disks under Linux which + were partitioned under the Atari OS. + ++config FIT_PARTITION ++ bool "Flattened-Image-Tree (FIT) partition support" if PARTITION_ADVANCED ++ default n ++ help ++ Say Y here if your system needs to mount the filesystem part of ++ a Flattened-Image-Tree (FIT) image commonly used with Das U-Boot. ++ + config IBM_PARTITION + bool "IBM disk label and partition support" + depends on PARTITION_ADVANCED && S390 +--- a/block/partitions/Makefile ++++ b/block/partitions/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o + obj-$(CONFIG_AMIGA_PARTITION) += amiga.o + obj-$(CONFIG_ATARI_PARTITION) += atari.o + obj-$(CONFIG_AIX_PARTITION) += aix.o ++obj-$(CONFIG_FIT_PARTITION) += fit.o + obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o + obj-$(CONFIG_MAC_PARTITION) += mac.o + obj-$(CONFIG_LDM_PARTITION) += ldm.o +--- a/block/partitions/check.h ++++ b/block/partitions/check.h +@@ -58,6 +58,7 @@ int amiga_partition(struct parsed_partit + int atari_partition(struct parsed_partitions *state); + int cmdline_partition(struct parsed_partitions *state); + int efi_partition(struct parsed_partitions *state); ++int fit_partition(struct parsed_partitions *state); + int ibm_partition(struct parsed_partitions *); + int karma_partition(struct parsed_partitions *state); + int ldm_partition(struct parsed_partitions *state); +@@ -68,3 +69,5 @@ int sgi_partition(struct parsed_partitio + int sun_partition(struct parsed_partitions *state); + int sysv68_partition(struct parsed_partitions *state); + int ultrix_partition(struct parsed_partitions *state); ++ ++int parse_fit_partitions(struct parsed_partitions *state, u64 start_sector, u64 nr_sectors, int *slot, int add_remain); +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -10,6 +10,10 @@ + #include + #include + #include ++#ifdef CONFIG_FIT_PARTITION ++#include ++#endif ++ + #include "check.h" + + static int (*check_part[])(struct parsed_partitions *) = { +@@ -46,6 +50,9 @@ static int (*check_part[])(struct parsed + #ifdef CONFIG_EFI_PARTITION + efi_partition, /* this must come before msdos */ + #endif ++#ifdef CONFIG_FIT_PARTITION ++ fit_partition, ++#endif + #ifdef CONFIG_SGI_PARTITION + sgi_partition, + #endif +@@ -694,6 +701,14 @@ static bool blk_add_partition(struct gen + (state->parts[p].flags & ADDPART_FLAG_RAID)) + md_autodetect_dev(part_to_dev(part)->devt); + ++#ifdef CONFIG_FIT_PARTITION ++ if ((state->parts[p].flags & ADDPART_FLAG_ROOTDEV) && ROOT_DEV == 0) ++ ROOT_DEV = part_to_dev(part)->devt; ++ ++ if (state->parts[p].flags & ADDPART_FLAG_READONLY) ++ part->policy = true; ++#endif ++ + return true; + } + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -396,7 +396,11 @@ int ubiblock_create(struct ubi_volume_in + dev->leb_size = vi->usable_leb_size; + + /* Initialize the gendisk of this ubiblock device */ ++#ifdef CONFIG_FIT_PARTITION ++ gd = alloc_disk(0); ++#else + gd = alloc_disk(1); ++#endif + if (!gd) { + pr_err("UBI: block: alloc_disk failed\n"); + ret = -ENODEV; +@@ -413,6 +417,9 @@ int ubiblock_create(struct ubi_volume_in + goto out_put_disk; + } + gd->private_data = dev; ++#ifdef CONFIG_FIT_PARTITION ++ gd->flags |= GENHD_FL_EXT_DEVT; ++#endif + sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); + set_capacity(gd, disk_capacity); + dev->gd = gd; +--- a/block/partitions/efi.c ++++ b/block/partitions/efi.c +@@ -706,6 +706,9 @@ int efi_partition(struct parsed_partitio + gpt_entry *ptes = NULL; + u32 i; + unsigned ssz = bdev_logical_block_size(state->bdev) / 512; ++#ifdef CONFIG_FIT_PARTITION ++ u32 extra_slot = 64; ++#endif + + if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { + kfree(gpt); +@@ -739,6 +742,11 @@ int efi_partition(struct parsed_partitio + ARRAY_SIZE(ptes[i].partition_name)); + utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname); + state->parts[i + 1].has_info = true; ++#ifdef CONFIG_FIT_PARTITION ++ /* If this is a U-Boot FIT volume it may have subpartitions */ ++ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_FIT_GUID)) ++ (void) parse_fit_partitions(state, start * ssz, size * ssz, &extra_slot, 1); ++#endif + } + kfree(ptes); + kfree(gpt); +--- a/block/partitions/efi.h ++++ b/block/partitions/efi.h +@@ -52,6 +52,9 @@ + #define PARTITION_LINUX_LVM_GUID \ + EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \ + 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28) ++#define PARTITION_LINUX_FIT_GUID \ ++ EFI_GUID( 0xcae9be83, 0xb15f, 0x49cc, \ ++ 0x86, 0x3f, 0x08, 0x1b, 0x74, 0x4a, 0x2d, 0x93) + + typedef struct _gpt_header { + __le64 signature; +--- a/drivers/mtd/mtdblock.c ++++ b/drivers/mtd/mtdblock.c +@@ -334,7 +334,11 @@ static void mtdblock_remove_dev(struct m + static struct mtd_blktrans_ops mtdblock_tr = { + .name = "mtdblock", + .major = MTD_BLOCK_MAJOR, ++#ifdef CONFIG_FIT_PARTITION ++ .part_bits = 2, ++#else + .part_bits = 0, ++#endif + .blksize = 512, + .open = mtdblock_open, + .flush = mtdblock_flush, +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -407,18 +407,8 @@ int add_mtd_blktrans_dev(struct mtd_blkt + gd->first_minor = (new->devnum) << tr->part_bits; + gd->fops = &mtd_block_ops; + +- if (tr->part_bits) +- if (new->devnum < 26) +- snprintf(gd->disk_name, sizeof(gd->disk_name), +- "%s%c", tr->name, 'a' + new->devnum); +- else +- snprintf(gd->disk_name, sizeof(gd->disk_name), +- "%s%c%c", tr->name, +- 'a' - 1 + new->devnum / 26, +- 'a' + new->devnum % 26); +- else +- snprintf(gd->disk_name, sizeof(gd->disk_name), +- "%s%d", tr->name, new->devnum); ++ snprintf(gd->disk_name, sizeof(gd->disk_name), ++ "%s%d", tr->name, new->devnum); + + set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); + +--- a/block/partitions/msdos.c ++++ b/block/partitions/msdos.c +@@ -563,6 +563,15 @@ static void parse_minix(struct parsed_pa + #endif /* CONFIG_MINIX_SUBPARTITION */ + } + ++static void parse_fit_mbr(struct parsed_partitions *state, ++ sector_t offset, sector_t size, int origin) ++{ ++#ifdef CONFIG_FIT_PARTITION ++ u32 extra_slot = 64; ++ (void) parse_fit_partitions(state, offset, size, &extra_slot, 1); ++#endif /* CONFIG_FIT_PARTITION */ ++} ++ + static struct { + unsigned char id; + void (*parse)(struct parsed_partitions *, sector_t, sector_t, int); +@@ -574,6 +583,7 @@ static struct { + {UNIXWARE_PARTITION, parse_unixware}, + {SOLARIS_X86_PARTITION, parse_solaris_x86}, + {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86}, ++ {FIT_PARTITION, parse_fit_mbr}, + {0, NULL}, + }; + +--- a/include/linux/msdos_partition.h ++++ b/include/linux/msdos_partition.h +@@ -31,6 +31,7 @@ enum msdos_sys_ind { + LINUX_LVM_PARTITION = 0x8e, + LINUX_RAID_PARTITION = 0xfd, /* autodetect RAID partition */ + ++ FIT_PARTITION = 0x2e, /* U-Boot uImage.FIT */ + SOLARIS_X86_PARTITION = 0x82, /* also Linux swap partitions */ + NEW_SOLARIS_X86_PARTITION = 0xbf, + diff --git a/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch b/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch new file mode 100644 index 0000000000..b071ac61ec --- /dev/null +++ b/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch @@ -0,0 +1,42 @@ +From: Gabor Juhos +Subject: kernel/3.1[02]: move MTD root device setup code to mtdcore + +The current code only allows to automatically set +root device on MTD partitions. Move the code to MTD +core to allow to use it with all MTD devices. + +Signed-off-by: Gabor Juhos +--- + drivers/mtd/mtdcore.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -694,6 +695,19 @@ int add_mtd_device(struct mtd_info *mtd) + of this try_ nonsense, and no bitching about it + either. :) */ + __module_get(THIS_MODULE); ++ ++ if (!strcmp(mtd->name, "rootfs") && ++ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && ++ ROOT_DEV == 0) { ++ unsigned int index = mtd->index; ++ pr_notice("mtd: device %d (%s) set to be root filesystem\n", ++ mtd->index, mtd->name); ++#ifdef CONFIG_FIT_PARTITION ++ index <<= 2; ++#endif ++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, index); ++ } ++ + return 0; + + fail_nvmem_add: diff --git a/target/linux/generic/hack-5.15/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch b/target/linux/generic/hack-5.15/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch new file mode 100644 index 0000000000..965a331a19 --- /dev/null +++ b/target/linux/generic/hack-5.15/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch @@ -0,0 +1,120 @@ +From 6fa9e3678eb002246df1280322b6a024853950a5 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Mon, 11 Oct 2021 00:53:14 +0200 +Subject: [PATCH] drivers: mtd: parsers: add nvmem support to cmdlinepart + +Assuming cmdlinepart is only one level deep partition scheme and that +static partition are also defined in DTS, we can assign an of_node for +partition declared from bootargs. cmdlinepart have priority than +fiexed-partition parser so in this specific case the parser doesn't +assign an of_node. Fix this by searching a defined of_node using a +similar fixed_partition parser and if a partition is found with the same +label, check that it has the same offset and size and return the DT +of_node to correctly use NVMEM cells. + +Signed-off-by: Ansuel Smith +--- + drivers/mtd/parsers/cmdlinepart.c | 71 +++++++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +--- a/drivers/mtd/parsers/cmdlinepart.c ++++ b/drivers/mtd/parsers/cmdlinepart.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + /* debug macro */ + #if 0 +@@ -323,6 +324,68 @@ static int mtdpart_setup_real(char *s) + return 0; + } + ++static int search_fixed_partition(struct mtd_info *master, ++ struct mtd_partition *target_part, ++ struct mtd_partition *fixed_part) ++{ ++ struct device_node *mtd_node; ++ struct device_node *ofpart_node; ++ struct device_node *pp; ++ struct mtd_partition part; ++ const char *partname; ++ ++ mtd_node = mtd_get_of_node(master); ++ if (!mtd_node) ++ return -EINVAL; ++ ++ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); ++ ++ for_each_child_of_node(ofpart_node, pp) { ++ const __be32 *reg; ++ int len; ++ int a_cells, s_cells; ++ ++ reg = of_get_property(pp, "reg", &len); ++ if (!reg) { ++ pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n", ++ master->name, pp, ++ mtd_node); ++ continue; ++ } ++ ++ a_cells = of_n_addr_cells(pp); ++ s_cells = of_n_size_cells(pp); ++ if (len / 4 != a_cells + s_cells) { ++ pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n", ++ master->name, pp, ++ mtd_node); ++ continue; ++ } ++ ++ part.offset = of_read_number(reg, a_cells); ++ part.size = of_read_number(reg + a_cells, s_cells); ++ part.of_node = pp; ++ ++ partname = of_get_property(pp, "label", &len); ++ if (!partname) ++ partname = of_get_property(pp, "name", &len); ++ part.name = partname; ++ ++ if (!strncmp(target_part->name, part.name, len)) { ++ if (part.offset != target_part->offset) ++ return -EINVAL; ++ ++ if (part.size != target_part->size) ++ return -EINVAL; ++ ++ memcpy(fixed_part, &part, sizeof(struct mtd_partition)); ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ + /* + * Main function to be called from the MTD mapping driver/device to + * obtain the partitioning information. At this point the command line +@@ -338,6 +401,7 @@ static int parse_cmdline_partitions(stru + int i, err; + struct cmdline_mtd_partition *part; + const char *mtd_id = master->name; ++ struct mtd_partition fixed_part; + + /* parse command line */ + if (!cmdline_parsed) { +@@ -382,6 +446,13 @@ static int parse_cmdline_partitions(stru + sizeof(*part->parts) * (part->num_parts - i)); + i--; + } ++ ++ err = search_fixed_partition(master, &part->parts[i], &fixed_part); ++ if (!err) { ++ part->parts[i].of_node = fixed_part.of_node; ++ pr_info("Found partition defined in DT for %s. Assigning OF node to support nvmem.", ++ part->parts[i].name); ++ } + } + + *pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts, diff --git a/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch b/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch new file mode 100644 index 0000000000..62ddd66bf2 --- /dev/null +++ b/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch @@ -0,0 +1,23 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -15,6 +15,10 @@ config MTD_NAND_ECC + bool + depends on MTD_NAND_CORE + ++config MTD_NAND_MTK_BMT ++ bool "Support MediaTek NAND Bad-block Management Table" ++ default n ++ + endmenu + + endmenu +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -2,6 +2,7 @@ + + nandcore-objs := core.o bbt.o + obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o ++obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o + + obj-y += onenand/ + obj-y += raw/ diff --git a/target/linux/generic/hack-5.15/531-debloat_lzma.patch b/target/linux/generic/hack-5.15/531-debloat_lzma.patch new file mode 100644 index 0000000000..2f70eee3e9 --- /dev/null +++ b/target/linux/generic/hack-5.15/531-debloat_lzma.patch @@ -0,0 +1,1040 @@ +From 3fd297761ac246c54d7723c57fca95c112b99465 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 15 Jul 2017 21:15:44 +0200 +Subject: lzma: de-bloat the lzma library used by jffs2 + +lede-commit: 3fd1dd08fbcbb78b34efefd32c3032e5c99108d6 +Signed-off-by: Felix Fietkau +--- + include/linux/lzma/LzFind.h | 17 --- + include/linux/lzma/LzmaDec.h | 101 --------------- + include/linux/lzma/LzmaEnc.h | 20 --- + lib/lzma/LzFind.c | 287 ++++--------------------------------------- + lib/lzma/LzmaDec.c | 86 +------------ + lib/lzma/LzmaEnc.c | 172 ++------------------------ + 6 files changed, 42 insertions(+), 641 deletions(-) + +--- a/include/linux/lzma/LzFind.h ++++ b/include/linux/lzma/LzFind.h +@@ -55,11 +55,6 @@ typedef struct _CMatchFinder + + #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +-int MatchFinder_NeedMove(CMatchFinder *p); +-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +-void MatchFinder_MoveBlock(CMatchFinder *p); +-void MatchFinder_ReadIfRequired(CMatchFinder *p); +- + void MatchFinder_Construct(CMatchFinder *p); + + /* Conditions: +@@ -70,12 +65,6 @@ int MatchFinder_Create(CMatchFinder *p, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc); + void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); +- +-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, +- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, +- UInt32 *distances, UInt32 maxLen); + + /* + Conditions: +@@ -102,12 +91,6 @@ typedef struct _IMatchFinder + + void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +-void MatchFinder_Init(CMatchFinder *p); +-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +- + #ifdef __cplusplus + } + #endif +--- a/include/linux/lzma/LzmaDec.h ++++ b/include/linux/lzma/LzmaDec.h +@@ -31,14 +31,6 @@ typedef struct _CLzmaProps + UInt32 dicSize; + } CLzmaProps; + +-/* LzmaProps_Decode - decodes properties +-Returns: +- SZ_OK +- SZ_ERROR_UNSUPPORTED - Unsupported properties +-*/ +- +-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); +- + + /* ---------- LZMA Decoder state ---------- */ + +@@ -70,8 +62,6 @@ typedef struct + + #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +-void LzmaDec_Init(CLzmaDec *p); +- + /* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ +@@ -108,97 +98,6 @@ typedef enum + + /* ELzmaStatus is used only as output value for function call */ + +- +-/* ---------- Interfaces ---------- */ +- +-/* There are 3 levels of interfaces: +- 1) Dictionary Interface +- 2) Buffer Interface +- 3) One Call Interface +- You can select any of these interfaces, but don't mix functions from different +- groups for same object. */ +- +- +-/* There are two variants to allocate state for Dictionary Interface: +- 1) LzmaDec_Allocate / LzmaDec_Free +- 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs +- You can use variant 2, if you set dictionary buffer manually. +- For Buffer Interface you must always use variant 1. +- +-LzmaDec_Allocate* can return: +- SZ_OK +- SZ_ERROR_MEM - Memory allocation error +- SZ_ERROR_UNSUPPORTED - Unsupported properties +-*/ +- +-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); +- +-SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +-void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); +- +-/* ---------- Dictionary Interface ---------- */ +- +-/* You can use it, if you want to eliminate the overhead for data copying from +- dictionary to some other external buffer. +- You must work with CLzmaDec variables directly in this interface. +- +- STEPS: +- LzmaDec_Constr() +- LzmaDec_Allocate() +- for (each new stream) +- { +- LzmaDec_Init() +- while (it needs more decompression) +- { +- LzmaDec_DecodeToDic() +- use data from CLzmaDec::dic and update CLzmaDec::dicPos +- } +- } +- LzmaDec_Free() +-*/ +- +-/* LzmaDec_DecodeToDic +- +- The decoding to internal dictionary buffer (CLzmaDec::dic). +- You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! +- +-finishMode: +- It has meaning only if the decoding reaches output limit (dicLimit). +- LZMA_FINISH_ANY - Decode just dicLimit bytes. +- LZMA_FINISH_END - Stream must be finished after dicLimit. +- +-Returns: +- SZ_OK +- status: +- LZMA_STATUS_FINISHED_WITH_MARK +- LZMA_STATUS_NOT_FINISHED +- LZMA_STATUS_NEEDS_MORE_INPUT +- LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK +- SZ_ERROR_DATA - Data error +-*/ +- +-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, +- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); +- +- +-/* ---------- Buffer Interface ---------- */ +- +-/* It's zlib-like interface. +- See LzmaDec_DecodeToDic description for information about STEPS and return results, +- but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need +- to work with CLzmaDec variables manually. +- +-finishMode: +- It has meaning only if the decoding reaches output limit (*destLen). +- LZMA_FINISH_ANY - Decode just destLen bytes. +- LZMA_FINISH_END - Stream must be finished after (*destLen). +-*/ +- +-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, +- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); +- +- + /* ---------- One Call Interface ---------- */ + + /* LzmaDecode +--- a/include/linux/lzma/LzmaEnc.h ++++ b/include/linux/lzma/LzmaEnc.h +@@ -31,9 +31,6 @@ typedef struct _CLzmaEncProps + } CLzmaEncProps; + + void LzmaEncProps_Init(CLzmaEncProps *p); +-void LzmaEncProps_Normalize(CLzmaEncProps *p); +-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); +- + + /* ---------- CLzmaEncHandle Interface ---------- */ + +@@ -53,26 +50,9 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc * + void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); + SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); + SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +-SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, +- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +-/* ---------- One Call Interface ---------- */ +- +-/* LzmaEncode +-Return code: +- SZ_OK - OK +- SZ_ERROR_MEM - Memory allocation error +- SZ_ERROR_PARAM - Incorrect paramater +- SZ_ERROR_OUTPUT_EOF - output buffer overflow +- SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +-*/ +- +-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, +- const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, +- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +- + #ifdef __cplusplus + } + #endif +--- a/lib/lzma/LzFind.c ++++ b/lib/lzma/LzFind.c +@@ -14,9 +14,15 @@ + + #define kStartMaxLen 3 + ++#if 0 ++#define DIRECT_INPUT p->directInput ++#else ++#define DIRECT_INPUT 1 ++#endif ++ + static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) + { +- if (!p->directInput) ++ if (!DIRECT_INPUT) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; +@@ -28,7 +34,7 @@ static void LzInWindow_Free(CMatchFinder + static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) + { + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; +- if (p->directInput) ++ if (DIRECT_INPUT) + { + p->blockSize = blockSize; + return 1; +@@ -42,12 +48,12 @@ static int LzInWindow_Create(CMatchFinde + return (p->bufferBase != 0); + } + +-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +-Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } ++static Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } ++static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } + +-UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } ++static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) ++static void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) + { + p->posLimit -= subValue; + p->pos -= subValue; +@@ -58,7 +64,7 @@ static void MatchFinder_ReadBlock(CMatch + { + if (p->streamEndWasReached || p->result != SZ_OK) + return; +- if (p->directInput) ++ if (DIRECT_INPUT) + { + UInt32 curSize = 0xFFFFFFFF - p->streamPos; + if (curSize > p->directInputRem) +@@ -89,7 +95,7 @@ static void MatchFinder_ReadBlock(CMatch + } + } + +-void MatchFinder_MoveBlock(CMatchFinder *p) ++static void MatchFinder_MoveBlock(CMatchFinder *p) + { + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, +@@ -97,22 +103,14 @@ void MatchFinder_MoveBlock(CMatchFinder + p->buffer = p->bufferBase + p->keepSizeBefore; + } + +-int MatchFinder_NeedMove(CMatchFinder *p) ++static int MatchFinder_NeedMove(CMatchFinder *p) + { +- if (p->directInput) ++ if (DIRECT_INPUT) + return 0; + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); + } + +-void MatchFinder_ReadIfRequired(CMatchFinder *p) +-{ +- if (p->streamEndWasReached) +- return; +- if (p->keepSizeAfter >= p->streamPos - p->pos) +- MatchFinder_ReadBlock(p); +-} +- + static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) + { + if (MatchFinder_NeedMove(p)) +@@ -268,7 +266,7 @@ static void MatchFinder_SetLimits(CMatch + p->posLimit = p->pos + limit; + } + +-void MatchFinder_Init(CMatchFinder *p) ++static void MatchFinder_Init(CMatchFinder *p) + { + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) +@@ -287,7 +285,7 @@ static UInt32 MatchFinder_GetSubValue(CM + return (p->pos - p->historySize - 1) & kNormalizeMask; + } + +-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) ++static void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) + { + UInt32 i; + for (i = 0; i < numItems; i++) +@@ -319,38 +317,7 @@ static void MatchFinder_CheckLimits(CMat + MatchFinder_SetLimits(p); + } + +-static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, +- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, +- UInt32 *distances, UInt32 maxLen) +-{ +- son[_cyclicBufferPos] = curMatch; +- for (;;) +- { +- UInt32 delta = pos - curMatch; +- if (cutValue-- == 0 || delta >= _cyclicBufferSize) +- return distances; +- { +- const Byte *pb = cur - delta; +- curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; +- if (pb[maxLen] == cur[maxLen] && *pb == *cur) +- { +- UInt32 len = 0; +- while (++len != lenLimit) +- if (pb[len] != cur[len]) +- break; +- if (maxLen < len) +- { +- *distances++ = maxLen = len; +- *distances++ = delta - 1; +- if (len == lenLimit) +- return distances; +- } +- } +- } +- } +-} +- +-UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++static UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) + { +@@ -460,10 +427,10 @@ static void SkipMatchesSpec(UInt32 lenLi + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +-#define MOVE_POS_RET MOVE_POS return offset; +- + static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + ++#define MOVE_POS_RET MatchFinder_MovePos(p); return offset; ++ + #define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ +@@ -479,62 +446,7 @@ static void MatchFinder_MovePos(CMatchFi + distances + offset, maxLen) - distances); MOVE_POS_RET; + + #define SKIP_FOOTER \ +- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; +- +-static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +-{ +- UInt32 offset; +- GET_MATCHES_HEADER(2) +- HASH2_CALC; +- curMatch = p->hash[hashValue]; +- p->hash[hashValue] = p->pos; +- offset = 0; +- GET_MATCHES_FOOTER(offset, 1) +-} +- +-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +-{ +- UInt32 offset; +- GET_MATCHES_HEADER(3) +- HASH_ZIP_CALC; +- curMatch = p->hash[hashValue]; +- p->hash[hashValue] = p->pos; +- offset = 0; +- GET_MATCHES_FOOTER(offset, 2) +-} +- +-static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +-{ +- UInt32 hash2Value, delta2, maxLen, offset; +- GET_MATCHES_HEADER(3) +- +- HASH3_CALC; +- +- delta2 = p->pos - p->hash[hash2Value]; +- curMatch = p->hash[kFix3HashSize + hashValue]; +- +- p->hash[hash2Value] = +- p->hash[kFix3HashSize + hashValue] = p->pos; +- +- +- maxLen = 2; +- offset = 0; +- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) +- { +- for (; maxLen != lenLimit; maxLen++) +- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) +- break; +- distances[0] = maxLen; +- distances[1] = delta2 - 1; +- offset = 2; +- if (maxLen == lenLimit) +- { +- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); +- MOVE_POS_RET; +- } +- } +- GET_MATCHES_FOOTER(offset, maxLen) +-} ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MatchFinder_MovePos(p); + + static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + { +@@ -583,108 +495,6 @@ static UInt32 Bt4_MatchFinder_GetMatches + GET_MATCHES_FOOTER(offset, maxLen) + } + +-static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +-{ +- UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; +- GET_MATCHES_HEADER(4) +- +- HASH4_CALC; +- +- delta2 = p->pos - p->hash[ hash2Value]; +- delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; +- curMatch = p->hash[kFix4HashSize + hashValue]; +- +- p->hash[ hash2Value] = +- p->hash[kFix3HashSize + hash3Value] = +- p->hash[kFix4HashSize + hashValue] = p->pos; +- +- maxLen = 1; +- offset = 0; +- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) +- { +- distances[0] = maxLen = 2; +- distances[1] = delta2 - 1; +- offset = 2; +- } +- if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) +- { +- maxLen = 3; +- distances[offset + 1] = delta3 - 1; +- offset += 2; +- delta2 = delta3; +- } +- if (offset != 0) +- { +- for (; maxLen != lenLimit; maxLen++) +- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) +- break; +- distances[offset - 2] = maxLen; +- if (maxLen == lenLimit) +- { +- p->son[p->cyclicBufferPos] = curMatch; +- MOVE_POS_RET; +- } +- } +- if (maxLen < 3) +- maxLen = 3; +- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), +- distances + offset, maxLen) - (distances)); +- MOVE_POS_RET +-} +- +-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +-{ +- UInt32 offset; +- GET_MATCHES_HEADER(3) +- HASH_ZIP_CALC; +- curMatch = p->hash[hashValue]; +- p->hash[hashValue] = p->pos; +- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), +- distances, 2) - (distances)); +- MOVE_POS_RET +-} +- +-static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +-{ +- do +- { +- SKIP_HEADER(2) +- HASH2_CALC; +- curMatch = p->hash[hashValue]; +- p->hash[hashValue] = p->pos; +- SKIP_FOOTER +- } +- while (--num != 0); +-} +- +-void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +-{ +- do +- { +- SKIP_HEADER(3) +- HASH_ZIP_CALC; +- curMatch = p->hash[hashValue]; +- p->hash[hashValue] = p->pos; +- SKIP_FOOTER +- } +- while (--num != 0); +-} +- +-static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +-{ +- do +- { +- UInt32 hash2Value; +- SKIP_HEADER(3) +- HASH3_CALC; +- curMatch = p->hash[kFix3HashSize + hashValue]; +- p->hash[hash2Value] = +- p->hash[kFix3HashSize + hashValue] = p->pos; +- SKIP_FOOTER +- } +- while (--num != 0); +-} +- + static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) + { + do +@@ -701,61 +511,12 @@ static void Bt4_MatchFinder_Skip(CMatchF + while (--num != 0); + } + +-static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +-{ +- do +- { +- UInt32 hash2Value, hash3Value; +- SKIP_HEADER(4) +- HASH4_CALC; +- curMatch = p->hash[kFix4HashSize + hashValue]; +- p->hash[ hash2Value] = +- p->hash[kFix3HashSize + hash3Value] = +- p->hash[kFix4HashSize + hashValue] = p->pos; +- p->son[p->cyclicBufferPos] = curMatch; +- MOVE_POS +- } +- while (--num != 0); +-} +- +-void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +-{ +- do +- { +- SKIP_HEADER(3) +- HASH_ZIP_CALC; +- curMatch = p->hash[hashValue]; +- p->hash[hashValue] = p->pos; +- p->son[p->cyclicBufferPos] = curMatch; +- MOVE_POS +- } +- while (--num != 0); +-} +- + void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) + { + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; +- if (!p->btMode) +- { +- vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; +- vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; +- } +- else if (p->numHashBytes == 2) +- { +- vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; +- vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; +- } +- else if (p->numHashBytes == 3) +- { +- vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; +- vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; +- } +- else +- { +- vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; +- vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; +- } ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +--- a/lib/lzma/LzmaDec.c ++++ b/lib/lzma/LzmaDec.c +@@ -682,7 +682,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, + p->needFlush = 0; + } + +-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) ++static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) + { + p->needFlush = 1; + p->remainLen = 0; +@@ -698,7 +698,7 @@ void LzmaDec_InitDicAndState(CLzmaDec *p + p->needInitState = 1; + } + +-void LzmaDec_Init(CLzmaDec *p) ++static void LzmaDec_Init(CLzmaDec *p) + { + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +@@ -716,7 +716,7 @@ static void LzmaDec_InitStateReal(CLzmaD + p->needInitState = 0; + } + +-SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ++static SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) + { + SizeT inSize = *srcLen; +@@ -837,65 +837,13 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, Si + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; + } + +-SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +-{ +- SizeT outSize = *destLen; +- SizeT inSize = *srcLen; +- *srcLen = *destLen = 0; +- for (;;) +- { +- SizeT inSizeCur = inSize, outSizeCur, dicPos; +- ELzmaFinishMode curFinishMode; +- SRes res; +- if (p->dicPos == p->dicBufSize) +- p->dicPos = 0; +- dicPos = p->dicPos; +- if (outSize > p->dicBufSize - dicPos) +- { +- outSizeCur = p->dicBufSize; +- curFinishMode = LZMA_FINISH_ANY; +- } +- else +- { +- outSizeCur = dicPos + outSize; +- curFinishMode = finishMode; +- } +- +- res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); +- src += inSizeCur; +- inSize -= inSizeCur; +- *srcLen += inSizeCur; +- outSizeCur = p->dicPos - dicPos; +- memcpy(dest, p->dic + dicPos, outSizeCur); +- dest += outSizeCur; +- outSize -= outSizeCur; +- *destLen += outSizeCur; +- if (res != 0) +- return res; +- if (outSizeCur == 0 || outSize == 0) +- return SZ_OK; +- } +-} +- +-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) ++static void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) + { + alloc->Free(alloc, p->probs); + p->probs = 0; + } + +-static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +-{ +- alloc->Free(alloc, p->dic); +- p->dic = 0; +-} +- +-void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +-{ +- LzmaDec_FreeProbs(p, alloc); +- LzmaDec_FreeDict(p, alloc); +-} +- +-SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) ++static SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) + { + UInt32 dicSize; + Byte d; +@@ -935,7 +883,7 @@ static SRes LzmaDec_AllocateProbs2(CLzma + return SZ_OK; + } + +-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++static SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) + { + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); +@@ -943,28 +891,6 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p, + p->prop = propNew; + return SZ_OK; + } +- +-SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +-{ +- CLzmaProps propNew; +- SizeT dicBufSize; +- RINOK(LzmaProps_Decode(&propNew, props, propsSize)); +- RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); +- dicBufSize = propNew.dicSize; +- if (p->dic == 0 || dicBufSize != p->dicBufSize) +- { +- LzmaDec_FreeDict(p, alloc); +- p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); +- if (p->dic == 0) +- { +- LzmaDec_FreeProbs(p, alloc); +- return SZ_ERROR_MEM; +- } +- } +- p->dicBufSize = dicBufSize; +- p->prop = propNew; +- return SZ_OK; +-} + + SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, +--- a/lib/lzma/LzmaEnc.c ++++ b/lib/lzma/LzmaEnc.c +@@ -53,7 +53,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) + p->writeEndMark = 0; + } + +-void LzmaEncProps_Normalize(CLzmaEncProps *p) ++static void LzmaEncProps_Normalize(CLzmaEncProps *p) + { + int level = p->level; + if (level < 0) level = 5; +@@ -76,7 +76,7 @@ void LzmaEncProps_Normalize(CLzmaEncProp + #endif + } + +-UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) ++static UInt32 __maybe_unused LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) + { + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); +@@ -93,7 +93,7 @@ UInt32 LzmaEncProps_GetDictSize(const CL + + #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } + +-UInt32 GetPosSlot1(UInt32 pos) ++static UInt32 GetPosSlot1(UInt32 pos) + { + UInt32 res; + BSR2_RET(pos, res); +@@ -107,7 +107,7 @@ UInt32 GetPosSlot1(UInt32 pos) + #define kNumLogBits (9 + (int)sizeof(size_t) / 2) + #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +-void LzmaEnc_FastPosInit(Byte *g_FastPos) ++static void LzmaEnc_FastPosInit(Byte *g_FastPos) + { + int c = 2, slotFast; + g_FastPos[0] = 0; +@@ -339,58 +339,6 @@ typedef struct + CSaveState saveState; + } CLzmaEnc; + +-void LzmaEnc_SaveState(CLzmaEncHandle pp) +-{ +- CLzmaEnc *p = (CLzmaEnc *)pp; +- CSaveState *dest = &p->saveState; +- int i; +- dest->lenEnc = p->lenEnc; +- dest->repLenEnc = p->repLenEnc; +- dest->state = p->state; +- +- for (i = 0; i < kNumStates; i++) +- { +- memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); +- memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); +- } +- for (i = 0; i < kNumLenToPosStates; i++) +- memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); +- memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); +- memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); +- memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); +- memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); +- memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); +- memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); +- memcpy(dest->reps, p->reps, sizeof(p->reps)); +- memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +-} +- +-void LzmaEnc_RestoreState(CLzmaEncHandle pp) +-{ +- CLzmaEnc *dest = (CLzmaEnc *)pp; +- const CSaveState *p = &dest->saveState; +- int i; +- dest->lenEnc = p->lenEnc; +- dest->repLenEnc = p->repLenEnc; +- dest->state = p->state; +- +- for (i = 0; i < kNumStates; i++) +- { +- memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); +- memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); +- } +- for (i = 0; i < kNumLenToPosStates; i++) +- memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); +- memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); +- memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); +- memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); +- memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); +- memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); +- memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); +- memcpy(dest->reps, p->reps, sizeof(p->reps)); +- memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +-} +- + SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) + { + CLzmaEnc *p = (CLzmaEnc *)pp; +@@ -600,7 +548,7 @@ static void LitEnc_EncodeMatched(CRangeE + while (symbol < 0x10000); + } + +-void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) ++static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) + { + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) +@@ -1676,7 +1624,7 @@ static void FillDistancesPrices(CLzmaEnc + p->matchPriceCount = 0; + } + +-void LzmaEnc_Construct(CLzmaEnc *p) ++static void LzmaEnc_Construct(CLzmaEnc *p) + { + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); +@@ -1709,7 +1657,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc * + return p; + } + +-void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) ++static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) + { + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); +@@ -1717,7 +1665,7 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAl + p->saveState.litProbs = 0; + } + +-void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) ++static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) + { + #ifndef _7ZIP_ST + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); +@@ -1947,7 +1895,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, U + return SZ_OK; + } + +-void LzmaEnc_Init(CLzmaEnc *p) ++static void LzmaEnc_Init(CLzmaEnc *p) + { + UInt32 i; + p->state = 0; +@@ -2005,7 +1953,7 @@ void LzmaEnc_Init(CLzmaEnc *p) + p->lpMask = (1 << p->lp) - 1; + } + +-void LzmaEnc_InitPrices(CLzmaEnc *p) ++static void LzmaEnc_InitPrices(CLzmaEnc *p) + { + if (!p->fastMode) + { +@@ -2037,26 +1985,6 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEn + return SZ_OK; + } + +-static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, +- ISzAlloc *alloc, ISzAlloc *allocBig) +-{ +- CLzmaEnc *p = (CLzmaEnc *)pp; +- p->matchFinderBase.stream = inStream; +- p->needInit = 1; +- p->rc.outStream = outStream; +- return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +-} +- +-SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, +- ISeqInStream *inStream, UInt32 keepWindowSize, +- ISzAlloc *alloc, ISzAlloc *allocBig) +-{ +- CLzmaEnc *p = (CLzmaEnc *)pp; +- p->matchFinderBase.stream = inStream; +- p->needInit = 1; +- return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +-} +- + static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) + { + p->matchFinderBase.directInput = 1; +@@ -2064,7 +1992,7 @@ static void LzmaEnc_SetInputBuf(CLzmaEnc + p->matchFinderBase.directInputRem = srcLen; + } + +-SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, ++static SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) + { + CLzmaEnc *p = (CLzmaEnc *)pp; +@@ -2074,7 +2002,7 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle p + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); + } + +-void LzmaEnc_Finish(CLzmaEncHandle pp) ++static void LzmaEnc_Finish(CLzmaEncHandle pp) + { + #ifndef _7ZIP_ST + CLzmaEnc *p = (CLzmaEnc *)pp; +@@ -2107,53 +2035,6 @@ static size_t MyWrite(void *pp, const vo + return size; + } + +- +-UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +-{ +- const CLzmaEnc *p = (CLzmaEnc *)pp; +- return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +-} +- +-const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +-{ +- const CLzmaEnc *p = (CLzmaEnc *)pp; +- return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +-} +- +-SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, +- Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +-{ +- CLzmaEnc *p = (CLzmaEnc *)pp; +- UInt64 nowPos64; +- SRes res; +- CSeqOutStreamBuf outStream; +- +- outStream.funcTable.Write = MyWrite; +- outStream.data = dest; +- outStream.rem = *destLen; +- outStream.overflow = False; +- +- p->writeEndMark = False; +- p->finished = False; +- p->result = SZ_OK; +- +- if (reInit) +- LzmaEnc_Init(p); +- LzmaEnc_InitPrices(p); +- nowPos64 = p->nowPos64; +- RangeEnc_Init(&p->rc); +- p->rc.outStream = &outStream.funcTable; +- +- res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); +- +- *unpackSize = (UInt32)(p->nowPos64 - nowPos64); +- *destLen -= outStream.rem; +- if (outStream.overflow) +- return SZ_ERROR_OUTPUT_EOF; +- +- return res; +-} +- + static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) + { + SRes res = SZ_OK; +@@ -2184,13 +2065,6 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, + return res; + } + +-SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, +- ISzAlloc *alloc, ISzAlloc *allocBig) +-{ +- RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); +- return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +-} +- + SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) + { + CLzmaEnc *p = (CLzmaEnc *)pp; +@@ -2247,25 +2121,3 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp + return SZ_ERROR_OUTPUT_EOF; + return res; + } +- +-SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, +- const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, +- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +-{ +- CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); +- SRes res; +- if (p == 0) +- return SZ_ERROR_MEM; +- +- res = LzmaEnc_SetProps(p, props); +- if (res == SZ_OK) +- { +- res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); +- if (res == SZ_OK) +- res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, +- writeEndMark, progress, alloc, allocBig); +- } +- +- LzmaEnc_Destroy(p, alloc, allocBig); +- return res; +-} diff --git a/target/linux/generic/hack-5.15/600-bridge_offload.patch b/target/linux/generic/hack-5.15/600-bridge_offload.patch new file mode 100644 index 0000000000..586353816c --- /dev/null +++ b/target/linux/generic/hack-5.15/600-bridge_offload.patch @@ -0,0 +1,817 @@ +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -57,6 +57,7 @@ struct br_ip_list { + #define BR_MRP_LOST_CONT BIT(18) + #define BR_MRP_LOST_IN_CONT BIT(19) + #define BR_BPDU_FILTER BIT(20) ++#define BR_OFFLOAD BIT(21) + + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + +--- a/net/bridge/Makefile ++++ b/net/bridge/Makefile +@@ -5,7 +5,7 @@ + + obj-$(CONFIG_BRIDGE) += bridge.o + +-bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \ ++bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o br_offload.o \ + br_ioctl.o br_stp.o br_stp_bpdu.o \ + br_stp_if.o br_stp_timer.o br_netlink.o \ + br_netlink_tunnel.o br_arp_nd_proxy.o +--- a/net/bridge/br.c ++++ b/net/bridge/br.c +@@ -18,6 +18,7 @@ + #include + + #include "br_private.h" ++#include "br_private_offload.h" + + /* + * Handle changes in state of network devices enslaved to a bridge. +@@ -332,6 +333,10 @@ static int __init br_init(void) + if (err) + goto err_out; + ++ err = br_offload_init(); ++ if (err) ++ goto err_out0; ++ + err = register_pernet_subsys(&br_net_ops); + if (err) + goto err_out1; +@@ -375,6 +380,8 @@ err_out3: + err_out2: + unregister_pernet_subsys(&br_net_ops); + err_out1: ++ br_offload_fini(); ++err_out0: + br_fdb_fini(); + err_out: + stp_proto_unregister(&br_stp_proto); +@@ -396,6 +403,7 @@ static void __exit br_deinit(void) + #if IS_ENABLED(CONFIG_ATM_LANE) + br_fdb_test_addr_hook = NULL; + #endif ++ br_offload_fini(); + br_fdb_fini(); + } + +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -529,6 +529,8 @@ void br_dev_setup(struct net_device *dev + br->bridge_hello_time = br->hello_time = 2 * HZ; + br->bridge_forward_delay = br->forward_delay = 15 * HZ; + br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME; ++ br->offload_cache_size = 128; ++ br->offload_cache_reserved = 8; + dev->max_mtu = ETH_MAX_MTU; + + br_netfilter_rtable_init(br); +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -23,6 +23,7 @@ + #include + #include + #include "br_private.h" ++#include "br_private_offload.h" + + static const struct rhashtable_params br_fdb_rht_params = { + .head_offset = offsetof(struct net_bridge_fdb_entry, rhnode), +@@ -513,6 +514,8 @@ static struct net_bridge_fdb_entry *fdb_ + fdb->key.vlan_id = vid; + fdb->flags = flags; + fdb->updated = fdb->used = jiffies; ++ INIT_HLIST_HEAD(&fdb->offload_in); ++ INIT_HLIST_HEAD(&fdb->offload_out); + if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl, + &fdb->rhnode, + br_fdb_rht_params)) { +@@ -734,6 +737,8 @@ static void fdb_notify(struct net_bridge + struct sk_buff *skb; + int err = -ENOBUFS; + ++ br_offload_fdb_update(fdb); ++ + if (swdev_notify) + br_switchdev_fdb_notify(br, fdb, type); + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -16,6 +16,7 @@ + #include + #include + #include "br_private.h" ++#include "br_private_offload.h" + + /* Don't forward packets to originating port or forwarding disabled */ + static inline int should_deliver(const struct net_bridge_port *p, +@@ -32,6 +33,8 @@ static inline int should_deliver(const s + + int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) + { ++ br_offload_output(skb); ++ + skb_push(skb, ETH_HLEN); + if (!is_skb_forwardable(skb->dev, skb)) + goto drop; +--- a/net/bridge/br_if.c ++++ b/net/bridge/br_if.c +@@ -25,6 +25,7 @@ + #include + + #include "br_private.h" ++#include "br_private_offload.h" + + /* + * Determine initial path cost based on speed. +@@ -427,7 +428,7 @@ static struct net_bridge_port *new_nbp(s + p->path_cost = port_cost(dev); + p->priority = 0x8000 >> BR_PORT_BITS; + p->port_no = index; +- p->flags = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; ++ p->flags = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD | BR_OFFLOAD; + br_init_port(p); + br_set_state(p, BR_STATE_DISABLED); + br_stp_port_timer_init(p); +@@ -777,6 +778,9 @@ void br_port_flags_change(struct net_bri + + if (mask & BR_NEIGH_SUPPRESS) + br_recalculate_neigh_suppress_enabled(br); ++ ++ if (mask & BR_OFFLOAD) ++ br_offload_port_state(p); + } + + bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag) +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -22,6 +22,7 @@ + #include + #include "br_private.h" + #include "br_private_tunnel.h" ++#include "br_private_offload.h" + + static int + br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) +@@ -162,6 +163,7 @@ int br_handle_frame_finish(struct net *n + dst->used = now; + br_forward(dst->dst, skb, local_rcv, false); + } else { ++ br_offload_skb_disable(skb); + if (!mcast_hit) + br_flood(br, skb, pkt_type, local_rcv, false); + else +@@ -280,6 +282,9 @@ static rx_handler_result_t br_handle_fra + memset(skb->cb, 0, sizeof(struct br_input_skb_cb)); + + p = br_port_get_rcu(skb->dev); ++ if (br_offload_input(p, skb)) ++ return RX_HANDLER_CONSUMED; ++ + if (p->flags & BR_VLAN_TUNNEL) { + if (br_handle_ingress_vlan_tunnel(skb, p, + nbp_vlan_group_rcu(p))) +--- /dev/null ++++ b/net/bridge/br_offload.c +@@ -0,0 +1,436 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++#include ++#include ++#include "br_private.h" ++#include "br_private_offload.h" ++ ++static DEFINE_SPINLOCK(offload_lock); ++ ++struct bridge_flow_key { ++ u8 dest[ETH_ALEN]; ++ u8 src[ETH_ALEN]; ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ u16 vlan_tag; ++ bool vlan_present; ++#endif ++}; ++ ++struct bridge_flow { ++ struct net_bridge_port *port; ++ struct rhash_head node; ++ struct bridge_flow_key key; ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ bool vlan_out_present; ++ u16 vlan_out; ++#endif ++ ++ unsigned long used; ++ struct net_bridge_fdb_entry *fdb_in, *fdb_out; ++ struct hlist_node fdb_list_in, fdb_list_out; ++ ++ struct rcu_head rcu; ++}; ++ ++static const struct rhashtable_params flow_params = { ++ .automatic_shrinking = true, ++ .head_offset = offsetof(struct bridge_flow, node), ++ .key_len = sizeof(struct bridge_flow_key), ++ .key_offset = offsetof(struct bridge_flow, key), ++}; ++ ++static struct kmem_cache *offload_cache __read_mostly; ++ ++static void ++flow_rcu_free(struct rcu_head *head) ++{ ++ struct bridge_flow *flow; ++ ++ flow = container_of(head, struct bridge_flow, rcu); ++ kmem_cache_free(offload_cache, flow); ++} ++ ++static void ++__br_offload_flow_free(struct bridge_flow *flow) ++{ ++ flow->used = 0; ++ hlist_del(&flow->fdb_list_in); ++ hlist_del(&flow->fdb_list_out); ++ ++ call_rcu(&flow->rcu, flow_rcu_free); ++} ++ ++static void ++br_offload_flow_free(struct bridge_flow *flow) ++{ ++ if (rhashtable_remove_fast(&flow->port->offload.rht, &flow->node, ++ flow_params) != 0) ++ return; ++ ++ __br_offload_flow_free(flow); ++} ++ ++static bool ++br_offload_flow_fdb_refresh_time(struct bridge_flow *flow, ++ struct net_bridge_fdb_entry *fdb) ++{ ++ if (!time_after(flow->used, fdb->updated)) ++ return false; ++ ++ fdb->updated = flow->used; ++ ++ return true; ++} ++ ++ ++static void ++br_offload_flow_refresh_time(struct bridge_flow *flow) ++{ ++ br_offload_flow_fdb_refresh_time(flow, flow->fdb_in); ++ br_offload_flow_fdb_refresh_time(flow, flow->fdb_out); ++} ++ ++static void ++br_offload_destroy_cb(void *ptr, void *arg) ++{ ++ struct bridge_flow *flow = ptr; ++ ++ __br_offload_flow_free(flow); ++} ++ ++static bool ++br_offload_need_gc(struct net_bridge_port *p) ++{ ++ return (atomic_read(&p->offload.rht.nelems) + ++ p->br->offload_cache_reserved) >= p->br->offload_cache_size; ++} ++ ++static void ++br_offload_gc_work(struct work_struct *work) ++{ ++ struct rhashtable_iter hti; ++ struct net_bridge_port *p; ++ struct bridge_flow *gc_flow = NULL; ++ struct bridge_flow *flow; ++ unsigned long gc_used; ++ ++ p = container_of(work, struct net_bridge_port, offload.gc_work); ++ ++ if (!br_offload_need_gc(p)) ++ return; ++ ++ rhashtable_walk_enter(&p->offload.rht, &hti); ++ rhashtable_walk_start(&hti); ++ while ((flow = rhashtable_walk_next(&hti)) != NULL) { ++ unsigned long used; ++ ++ if (IS_ERR(flow)) ++ continue; ++ ++ used = READ_ONCE(flow->used); ++ if (!used) ++ continue; ++ ++ if (gc_flow && !time_before(used, gc_used)) ++ continue; ++ ++ gc_flow = flow; ++ gc_used = used; ++ } ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++ ++ if (!gc_flow) ++ return; ++ ++ spin_lock_bh(&offload_lock); ++ if (br_offload_need_gc(p) && gc_flow && ++ gc_flow->used == gc_used) ++ br_offload_flow_free(gc_flow); ++ if (p->offload.enabled && br_offload_need_gc(p)) ++ queue_work(system_long_wq, work); ++ spin_unlock_bh(&offload_lock); ++ ++} ++ ++void br_offload_port_state(struct net_bridge_port *p) ++{ ++ struct net_bridge_port_offload *o = &p->offload; ++ bool enabled = true; ++ bool flush = false; ++ ++ if (p->state != BR_STATE_FORWARDING || ++ !(p->flags & BR_OFFLOAD)) ++ enabled = false; ++ ++ spin_lock_bh(&offload_lock); ++ if (o->enabled == enabled) ++ goto out; ++ ++ if (enabled) { ++ if (!o->gc_work.func) ++ INIT_WORK(&o->gc_work, br_offload_gc_work); ++ rhashtable_init(&o->rht, &flow_params); ++ } else { ++ flush = true; ++ rhashtable_free_and_destroy(&o->rht, br_offload_destroy_cb, o); ++ } ++ ++ o->enabled = enabled; ++ ++out: ++ spin_unlock_bh(&offload_lock); ++ ++ if (flush) ++ flush_work(&o->gc_work); ++} ++ ++void br_offload_fdb_update(const struct net_bridge_fdb_entry *fdb) ++{ ++ struct bridge_flow *f; ++ struct hlist_node *tmp; ++ ++ spin_lock_bh(&offload_lock); ++ ++ hlist_for_each_entry_safe(f, tmp, &fdb->offload_in, fdb_list_in) ++ br_offload_flow_free(f); ++ ++ hlist_for_each_entry_safe(f, tmp, &fdb->offload_out, fdb_list_out) ++ br_offload_flow_free(f); ++ ++ spin_unlock_bh(&offload_lock); ++} ++ ++static void ++br_offload_prepare_key(struct net_bridge_port *p, struct bridge_flow_key *key, ++ struct sk_buff *skb) ++{ ++ memset(key, 0, sizeof(*key)); ++ memcpy(key, eth_hdr(skb), 2 * ETH_ALEN); ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ if (!br_opt_get(p->br, BROPT_VLAN_ENABLED)) ++ return; ++ ++ if (!skb_vlan_tag_present(skb) || skb->vlan_proto != p->br->vlan_proto) ++ return; ++ ++ key->vlan_present = true; ++ key->vlan_tag = skb_vlan_tag_get_id(skb); ++#endif ++} ++ ++void br_offload_output(struct sk_buff *skb) ++{ ++ struct net_bridge_port_offload *o; ++ struct br_input_skb_cb *cb = (struct br_input_skb_cb *)skb->cb; ++ struct net_bridge_port *p, *inp; ++ struct net_device *dev; ++ struct net_bridge_fdb_entry *fdb_in, *fdb_out; ++ struct net_bridge_vlan_group *vg; ++ struct bridge_flow_key key; ++ struct bridge_flow *flow; ++ u16 vlan; ++ ++ if (!cb->offload) ++ return; ++ ++ rcu_read_lock(); ++ ++ p = br_port_get_rcu(skb->dev); ++ if (!p) ++ goto out; ++ ++ o = &p->offload; ++ if (!o->enabled) ++ goto out; ++ ++ if (atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size) ++ goto out; ++ ++ dev = dev_get_by_index_rcu(dev_net(p->br->dev), cb->input_ifindex); ++ if (!dev) ++ goto out; ++ ++ inp = br_port_get_rcu(dev); ++ if (!inp) ++ goto out; ++ ++ vg = nbp_vlan_group_rcu(inp); ++ vlan = cb->input_vlan_present ? cb->input_vlan_tag : br_get_pvid(vg); ++ fdb_in = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_source, vlan); ++ if (!fdb_in) ++ goto out; ++ ++ vg = nbp_vlan_group_rcu(p); ++ vlan = skb_vlan_tag_present(skb) ? skb_vlan_tag_get_id(skb) : br_get_pvid(vg); ++ fdb_out = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_dest, vlan); ++ if (!fdb_out) ++ goto out; ++ ++ br_offload_prepare_key(p, &key, skb); ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ key.vlan_present = cb->input_vlan_present; ++ key.vlan_tag = cb->input_vlan_tag; ++#endif ++ ++ flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC); ++ flow->port = fdb_in->dst; ++ memcpy(&flow->key, &key, sizeof(key)); ++ ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ flow->vlan_out_present = skb_vlan_tag_present(skb); ++ flow->vlan_out = skb_vlan_tag_get(skb); ++#endif ++ ++ flow->fdb_in = fdb_in; ++ flow->fdb_out = fdb_out; ++ flow->used = jiffies; ++ ++ spin_lock_bh(&offload_lock); ++ if (!o->enabled || ++ atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size || ++ rhashtable_insert_fast(&flow->port->offload.rht, &flow->node, flow_params)) { ++ kmem_cache_free(offload_cache, flow); ++ goto out_unlock; ++ } ++ ++ hlist_add_head(&flow->fdb_list_in, &fdb_in->offload_in); ++ hlist_add_head(&flow->fdb_list_out, &fdb_out->offload_out); ++ ++ if (br_offload_need_gc(p)) ++ queue_work(system_long_wq, &p->offload.gc_work); ++ ++out_unlock: ++ spin_unlock_bh(&offload_lock); ++ ++out: ++ rcu_read_unlock(); ++} ++ ++bool br_offload_input(struct net_bridge_port *p, struct sk_buff *skb) ++{ ++ struct net_bridge_port_offload *o = &p->offload; ++ struct br_input_skb_cb *cb = (struct br_input_skb_cb *)skb->cb; ++ struct bridge_flow_key key; ++ struct net_bridge_port *dst; ++ struct bridge_flow *flow; ++ unsigned long now = jiffies; ++ bool ret = false; ++ ++ if (skb->len < sizeof(key)) ++ return false; ++ ++ if (!o->enabled) ++ return false; ++ ++ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) ++ return false; ++ ++ br_offload_prepare_key(p, &key, skb); ++ ++ rcu_read_lock(); ++ flow = rhashtable_lookup(&o->rht, &key, flow_params); ++ if (!flow) { ++ cb->offload = 1; ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ cb->input_vlan_present = key.vlan_present != 0; ++ cb->input_vlan_tag = key.vlan_tag; ++ cb->input_ifindex = p->dev->ifindex; ++#endif ++ goto out; ++ } ++ ++ if (flow->fdb_in->dst != p) ++ goto out; ++ ++ dst = flow->fdb_out->dst; ++ if (!dst) ++ goto out; ++ ++ ret = true; ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ if (!flow->vlan_out_present && key.vlan_present) { ++ __vlan_hwaccel_clear_tag(skb); ++ } else if (flow->vlan_out_present) { ++ if (skb_vlan_tag_present(skb) && ++ skb->vlan_proto != p->br->vlan_proto) { ++ /* Protocol-mismatch, empty out vlan_tci for new tag */ ++ skb_push(skb, ETH_HLEN); ++ skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, ++ skb_vlan_tag_get(skb)); ++ if (unlikely(!skb)) ++ goto out; ++ ++ skb_pull(skb, ETH_HLEN); ++ skb_reset_mac_len(skb); ++ } ++ ++ __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, ++ flow->vlan_out); ++ } ++#endif ++ ++ skb->dev = dst->dev; ++ skb_push(skb, ETH_HLEN); ++ ++ if (skb_warn_if_lro(skb) || !is_skb_forwardable(skb->dev, skb)) { ++ kfree_skb(skb); ++ goto out; ++ } ++ ++ if (now - flow->used >= HZ) { ++ flow->used = now; ++ br_offload_flow_refresh_time(flow); ++ } ++ ++ skb_forward_csum(skb); ++ dev_queue_xmit(skb); ++ ++out: ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static void ++br_offload_check_gc(struct net_bridge *br) ++{ ++ struct net_bridge_port *p; ++ ++ spin_lock_bh(&br->lock); ++ list_for_each_entry(p, &br->port_list, list) ++ if (br_offload_need_gc(p)) ++ queue_work(system_long_wq, &p->offload.gc_work); ++ spin_unlock_bh(&br->lock); ++} ++ ++ ++int br_offload_set_cache_size(struct net_bridge *br, unsigned long val) ++{ ++ br->offload_cache_size = val; ++ br_offload_check_gc(br); ++ ++ return 0; ++} ++ ++int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val) ++{ ++ br->offload_cache_reserved = val; ++ br_offload_check_gc(br); ++ ++ return 0; ++} ++ ++int __init br_offload_init(void) ++{ ++ offload_cache = kmem_cache_create("bridge_offload_cache", ++ sizeof(struct bridge_flow), ++ 0, SLAB_HWCACHE_ALIGN, NULL); ++ if (!offload_cache) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++void br_offload_fini(void) ++{ ++ kmem_cache_destroy(offload_cache); ++} +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -207,7 +207,13 @@ struct net_bridge_fdb_entry { + unsigned long updated ____cacheline_aligned_in_smp; + unsigned long used; + +- struct rcu_head rcu; ++ union { ++ struct { ++ struct hlist_head offload_in; ++ struct hlist_head offload_out; ++ }; ++ struct rcu_head rcu; ++ }; + }; + + #define MDB_PG_FLAGS_PERMANENT BIT(0) +@@ -280,6 +286,12 @@ struct net_bridge_mdb_entry { + struct rcu_head rcu; + }; + ++struct net_bridge_port_offload { ++ struct rhashtable rht; ++ struct work_struct gc_work; ++ bool enabled; ++}; ++ + struct net_bridge_port { + struct net_bridge *br; + struct net_device *dev; +@@ -337,6 +349,7 @@ struct net_bridge_port { + u16 backup_redirected_cnt; + + struct bridge_stp_xstats stp_xstats; ++ struct net_bridge_port_offload offload; + }; + + #define kobj_to_brport(obj) container_of(obj, struct net_bridge_port, kobj) +@@ -475,6 +488,9 @@ struct net_bridge { + struct kobject *ifobj; + u32 auto_cnt; + ++ u32 offload_cache_size; ++ u32 offload_cache_reserved; ++ + #ifdef CONFIG_NET_SWITCHDEV + int offload_fwd_mark; + #endif +@@ -501,6 +517,10 @@ struct br_input_skb_cb { + #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE + u8 br_netfilter_broute:1; + #endif ++ u8 offload:1; ++ u8 input_vlan_present:1; ++ u16 input_vlan_tag; ++ int input_ifindex; + + #ifdef CONFIG_NET_SWITCHDEV + int offload_fwd_mark; +--- /dev/null ++++ b/net/bridge/br_private_offload.h +@@ -0,0 +1,21 @@ ++#ifndef __BR_OFFLOAD_H ++#define __BR_OFFLOAD_H ++ ++bool br_offload_input(struct net_bridge_port *p, struct sk_buff *skb); ++void br_offload_output(struct sk_buff *skb); ++void br_offload_port_state(struct net_bridge_port *p); ++void br_offload_fdb_update(const struct net_bridge_fdb_entry *fdb); ++int br_offload_init(void); ++void br_offload_fini(void); ++int br_offload_set_cache_size(struct net_bridge *br, unsigned long val); ++int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val); ++ ++static inline void br_offload_skb_disable(struct sk_buff *skb) ++{ ++ struct br_input_skb_cb *cb = (struct br_input_skb_cb *)skb->cb; ++ ++ if (cb->offload) ++ cb->offload = 0; ++} ++ ++#endif +--- a/net/bridge/br_stp.c ++++ b/net/bridge/br_stp.c +@@ -12,6 +12,7 @@ + + #include "br_private.h" + #include "br_private_stp.h" ++#include "br_private_offload.h" + + /* since time values in bpdu are in jiffies and then scaled (1/256) + * before sending, make sure that is at least one STP tick. +@@ -52,6 +53,8 @@ void br_set_state(struct net_bridge_port + (unsigned int) p->port_no, p->dev->name, + br_port_state_names[p->state]); + ++ br_offload_port_state(p); ++ + if (p->br->stp_enabled == BR_KERNEL_STP) { + switch (p->state) { + case BR_STATE_BLOCKING: +--- a/net/bridge/br_sysfs_br.c ++++ b/net/bridge/br_sysfs_br.c +@@ -18,6 +18,7 @@ + #include + + #include "br_private.h" ++#include "br_private_offload.h" + + #define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd))) + +@@ -842,6 +843,38 @@ static ssize_t vlan_stats_per_port_store + static DEVICE_ATTR_RW(vlan_stats_per_port); + #endif + ++static ssize_t offload_cache_size_show(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct net_bridge *br = to_bridge(d); ++ return sprintf(buf, "%u\n", br->offload_cache_size); ++} ++ ++static ssize_t offload_cache_size_store(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ return store_bridge_parm(d, buf, len, br_offload_set_cache_size); ++} ++static DEVICE_ATTR_RW(offload_cache_size); ++ ++static ssize_t offload_cache_reserved_show(struct device *d, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct net_bridge *br = to_bridge(d); ++ return sprintf(buf, "%u\n", br->offload_cache_reserved); ++} ++ ++static ssize_t offload_cache_reserved_store(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ return store_bridge_parm(d, buf, len, br_offload_set_cache_reserved); ++} ++static DEVICE_ATTR_RW(offload_cache_reserved); ++ + static struct attribute *bridge_attrs[] = { + &dev_attr_forward_delay.attr, + &dev_attr_hello_time.attr, +@@ -896,6 +929,8 @@ static struct attribute *bridge_attrs[] + &dev_attr_vlan_stats_enabled.attr, + &dev_attr_vlan_stats_per_port.attr, + #endif ++ &dev_attr_offload_cache_size.attr, ++ &dev_attr_offload_cache_reserved.attr, + NULL + }; + +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -234,6 +234,7 @@ BRPORT_ATTR_FLAG(broadcast_flood, BR_BCA + BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); + BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); + BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER); ++BRPORT_ATTR_FLAG(offload, BR_OFFLOAD); + + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +@@ -288,6 +289,7 @@ static const struct brport_attribute *br + &brport_attr_isolated, + &brport_attr_bpdu_filter, + &brport_attr_backup_port, ++ &brport_attr_offload, + NULL + }; + +--- a/net/bridge/br_vlan_tunnel.c ++++ b/net/bridge/br_vlan_tunnel.c +@@ -15,6 +15,7 @@ + + #include "br_private.h" + #include "br_private_tunnel.h" ++#include "br_private_offload.h" + + static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg, + const void *ptr) +@@ -180,6 +181,7 @@ int br_handle_ingress_vlan_tunnel(struct + skb_dst_drop(skb); + + __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid); ++ br_offload_skb_disable(skb); + + return 0; + } +@@ -203,6 +205,7 @@ int br_handle_egress_vlan_tunnel(struct + if (err) + return err; + ++ br_offload_skb_disable(skb); + tunnel_dst = rcu_dereference(vlan->tinfo.tunnel_dst); + if (tunnel_dst && dst_hold_safe(&tunnel_dst->dst)) + skb_dst_set(skb, &tunnel_dst->dst); diff --git a/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch b/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch new file mode 100644 index 0000000000..2d3fe01a75 --- /dev/null +++ b/target/linux/generic/hack-5.15/645-netfilter-connmark-introduce-set-dscpmark.patch @@ -0,0 +1,212 @@ +From eda40b8c8c82e0f2789d6bc8bf63846dce2e8f32 Mon Sep 17 00:00:00 2001 +From: Kevin Darbyshire-Bryant +Date: Sat, 23 Mar 2019 09:29:49 +0000 +Subject: [PATCH] netfilter: connmark: introduce set-dscpmark + +set-dscpmark is a method of storing the DSCP of an ip packet into +conntrack mark. In combination with a suitable tc filter action +(act_ctinfo) DSCP values are able to be stored in the mark on egress and +restored on ingress across links that otherwise alter or bleach DSCP. + +This is useful for qdiscs such as CAKE which are able to shape according +to policies based on DSCP. + +Ingress classification is traditionally a challenging task since +iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT +lookups, hence are unable to see internal IPv4 addresses as used on the +typical home masquerading gateway. + +x_tables CONNMARK set-dscpmark target solves the problem of storing the +DSCP to the conntrack mark in a way suitable for the new act_ctinfo tc +action to restore. + +The set-dscpmark option accepts 2 parameters, a 32bit 'dscpmask' and a +32bit 'statemask'. The dscp mask must be 6 contiguous bits and +represents the area where the DSCP will be stored in the connmark. The +state mask is a minimum 1 bit length mask that must not overlap with the +dscpmask. It represents a flag which is set when the DSCP has been +stored in the conntrack mark. This is useful to implement a 'one shot' +iptables based classification where the 'complicated' iptables rules are +only run once to classify the connection on initial (egress) packet and +subsequent packets are all marked/restored with the same DSCP. A state +mask of zero disables the setting of a status bit/s. + +example syntax with a suitably modified iptables user space application: + +iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000 + +Would store the DSCP in the top 6 bits of the 32bit mark field, and use +the LSB of the top byte as the 'DSCP has been stored' marker. + +|----0xFC----conntrack mark----000000---| +| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +| DSCP | unused | flag |unused | +|-----------------------0x01---000000---| + ^ ^ + | | + ---| Conditional flag + | set this when dscp +|-ip diffserv-| stored in mark +| 6 bits | +|-------------| + +an identically configured tc action to restore looks like: + +tc filter show dev eth0 ingress +filter parent ffff: protocol all pref 10 u32 chain 0 +filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1 +filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1: not_in_hw + match 00000000/00000000 at 0 + action order 1: ctinfo zone 0 pipe + index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000 + + action order 2: mirred (Egress Redirect to device ifb4eth0) stolen + index 1 ref 1 bind 1 + +|----0xFC----conntrack mark----000000---| +| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +| DSCP | unused | flag |unused | +|-----------------------0x01---000000---| + | | + | | + ---| Conditional flag + v only restore if set +|-ip diffserv-| +| 6 bits | +|-------------| + +Signed-off-by: Kevin Darbyshire-Bryant +--- + include/uapi/linux/netfilter/xt_connmark.h | 10 ++++ + net/netfilter/xt_connmark.c | 55 ++++++++++++++++++---- + 2 files changed, 57 insertions(+), 8 deletions(-) + +--- a/include/uapi/linux/netfilter/xt_connmark.h ++++ b/include/uapi/linux/netfilter/xt_connmark.h +@@ -20,6 +20,11 @@ enum { + }; + + enum { ++ XT_CONNMARK_VALUE = (1 << 0), ++ XT_CONNMARK_DSCP = (1 << 1) ++}; ++ ++enum { + D_SHIFT_LEFT = 0, + D_SHIFT_RIGHT, + }; +@@ -34,6 +39,11 @@ struct xt_connmark_tginfo2 { + __u8 shift_dir, shift_bits, mode; + }; + ++struct xt_connmark_tginfo3 { ++ __u32 ctmark, ctmask, nfmask; ++ __u8 shift_dir, shift_bits, mode, func; ++}; ++ + struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +--- a/net/netfilter/xt_connmark.c ++++ b/net/netfilter/xt_connmark.c +@@ -24,12 +24,13 @@ MODULE_ALIAS("ipt_connmark"); + MODULE_ALIAS("ip6t_connmark"); + + static unsigned int +-connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) ++connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo3 *info) + { + enum ip_conntrack_info ctinfo; + u_int32_t new_targetmark; + struct nf_conn *ct; + u_int32_t newmark; ++ u_int8_t dscp; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) +@@ -37,12 +38,24 @@ connmark_tg_shift(struct sk_buff *skb, c + + switch (info->mode) { + case XT_CONNMARK_SET: +- newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; +- if (info->shift_dir == D_SHIFT_RIGHT) +- newmark >>= info->shift_bits; +- else +- newmark <<= info->shift_bits; ++ newmark = ct->mark; ++ if (info->func & XT_CONNMARK_VALUE) { ++ newmark = (newmark & ~info->ctmask) ^ info->ctmark; ++ if (info->shift_dir == D_SHIFT_RIGHT) ++ newmark >>= info->shift_bits; ++ else ++ newmark <<= info->shift_bits; ++ } else if (info->func & XT_CONNMARK_DSCP) { ++ if (skb->protocol == htons(ETH_P_IP)) ++ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2; ++ else if (skb->protocol == htons(ETH_P_IPV6)) ++ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; ++ else /* protocol doesn't have diffserv */ ++ break; + ++ newmark = (newmark & ~info->ctmark) | ++ (info->ctmask | (dscp << info->shift_bits)); ++ } + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); +@@ -81,20 +94,36 @@ static unsigned int + connmark_tg(struct sk_buff *skb, const struct xt_action_param *par) + { + const struct xt_connmark_tginfo1 *info = par->targinfo; +- const struct xt_connmark_tginfo2 info2 = { ++ const struct xt_connmark_tginfo3 info3 = { + .ctmark = info->ctmark, + .ctmask = info->ctmask, + .nfmask = info->nfmask, + .mode = info->mode, ++ .func = XT_CONNMARK_VALUE + }; + +- return connmark_tg_shift(skb, &info2); ++ return connmark_tg_shift(skb, &info3); + } + + static unsigned int + connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par) + { + const struct xt_connmark_tginfo2 *info = par->targinfo; ++ const struct xt_connmark_tginfo3 info3 = { ++ .ctmark = info->ctmark, ++ .ctmask = info->ctmask, ++ .nfmask = info->nfmask, ++ .mode = info->mode, ++ .func = XT_CONNMARK_VALUE ++ }; ++ ++ return connmark_tg_shift(skb, &info3); ++} ++ ++static unsigned int ++connmark_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ const struct xt_connmark_tginfo3 *info = par->targinfo; + + return connmark_tg_shift(skb, info); + } +@@ -165,6 +194,16 @@ static struct xt_target connmark_tg_reg[ + .targetsize = sizeof(struct xt_connmark_tginfo2), + .destroy = connmark_tg_destroy, + .me = THIS_MODULE, ++ }, ++ { ++ .name = "CONNMARK", ++ .revision = 3, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_tg_check, ++ .target = connmark_tg_v3, ++ .targetsize = sizeof(struct xt_connmark_tginfo3), ++ .destroy = connmark_tg_destroy, ++ .me = THIS_MODULE, + } + }; + diff --git a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch new file mode 100644 index 0000000000..23332534bb --- /dev/null +++ b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -0,0 +1,819 @@ +From: Felix Fietkau +Date: Tue, 20 Feb 2018 15:56:02 +0100 +Subject: [PATCH] netfilter: add xt_FLOWOFFLOAD target + +Signed-off-by: Felix Fietkau +--- + create mode 100644 net/netfilter/xt_OFFLOAD.c + +--- a/net/ipv4/netfilter/Kconfig ++++ b/net/ipv4/netfilter/Kconfig +@@ -56,8 +56,6 @@ config NF_TABLES_ARP + help + This option enables the ARP support for nf_tables. + +-endif # NF_TABLES +- + config NF_FLOW_TABLE_IPV4 + tristate "Netfilter flow table IPv4 module" + depends on NF_FLOW_TABLE +@@ -66,6 +64,8 @@ config NF_FLOW_TABLE_IPV4 + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_DUP_IPV4 + tristate "Netfilter IPv4 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/ipv6/netfilter/Kconfig ++++ b/net/ipv6/netfilter/Kconfig +@@ -45,7 +45,6 @@ config NFT_FIB_IPV6 + multicast or blackhole. + + endif # NF_TABLES_IPV6 +-endif # NF_TABLES + + config NF_FLOW_TABLE_IPV6 + tristate "Netfilter flow table IPv6 module" +@@ -55,6 +54,8 @@ config NF_FLOW_TABLE_IPV6 + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_DUP_IPV6 + tristate "Netfilter IPv6 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -683,8 +683,6 @@ config NFT_FIB_NETDEV + + endif # NF_TABLES_NETDEV + +-endif # NF_TABLES +- + config NF_FLOW_TABLE_INET + tristate "Netfilter flow table mixed IPv4/IPv6 module" + depends on NF_FLOW_TABLE +@@ -693,11 +691,12 @@ config NF_FLOW_TABLE_INET + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_FLOW_TABLE + tristate "Netfilter flow table module" + depends on NETFILTER_INGRESS + depends on NF_CONNTRACK +- depends on NF_TABLES + help + This option adds the flow table core infrastructure. + +@@ -977,6 +976,15 @@ config NETFILTER_XT_TARGET_NOTRACK + depends on NETFILTER_ADVANCED + select NETFILTER_XT_TARGET_CT + ++config NETFILTER_XT_TARGET_FLOWOFFLOAD ++ tristate '"FLOWOFFLOAD" target support' ++ depends on NF_FLOW_TABLE ++ depends on NETFILTER_INGRESS ++ help ++ This option adds a `FLOWOFFLOAD' target, which uses the nf_flow_offload ++ module to speed up processing of packets by bypassing the usual ++ netfilter chains ++ + config NETFILTER_XT_TARGET_RATEEST + tristate '"RATEEST" target support' + depends on NETFILTER_ADVANCED +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -145,6 +145,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF + obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o + obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o ++obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o +--- /dev/null ++++ b/net/netfilter/xt_FLOWOFFLOAD.c +@@ -0,0 +1,657 @@ ++/* ++ * Copyright (C) 2018-2021 Felix Fietkau ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct xt_flowoffload_hook { ++ struct hlist_node list; ++ struct nf_hook_ops ops; ++ struct net *net; ++ bool registered; ++ bool used; ++}; ++ ++struct xt_flowoffload_table { ++ struct nf_flowtable ft; ++ struct hlist_head hooks; ++ struct delayed_work work; ++}; ++ ++static DEFINE_SPINLOCK(hooks_lock); ++ ++struct xt_flowoffload_table flowtable[2]; ++ ++static unsigned int ++xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct nf_flowtable *ft = priv; ++ ++ if (!atomic_read(&ft->rhashtable.nelems)) ++ return NF_ACCEPT; ++ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ return nf_flow_offload_ip_hook(priv, skb, state); ++ case htons(ETH_P_IPV6): ++ return nf_flow_offload_ipv6_hook(priv, skb, state); ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static int ++xt_flowoffload_create_hook(struct xt_flowoffload_table *table, ++ struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ struct nf_hook_ops *ops; ++ ++ hook = kzalloc(sizeof(*hook), GFP_ATOMIC); ++ if (!hook) ++ return -ENOMEM; ++ ++ ops = &hook->ops; ++ ops->pf = NFPROTO_NETDEV; ++ ops->hooknum = NF_NETDEV_INGRESS; ++ ops->priority = 10; ++ ops->priv = &table->ft; ++ ops->hook = xt_flowoffload_net_hook; ++ ops->dev = dev; ++ ++ hlist_add_head(&hook->list, &table->hooks); ++ mod_delayed_work(system_power_efficient_wq, &table->work, 0); ++ ++ return 0; ++} ++ ++static struct xt_flowoffload_hook * ++flow_offload_lookup_hook(struct xt_flowoffload_table *table, ++ struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->ops.dev == dev) ++ return hook; ++ } ++ ++ return NULL; ++} ++ ++static void ++xt_flowoffload_check_device(struct xt_flowoffload_table *table, ++ struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ if (!dev) ++ return; ++ ++ spin_lock_bh(&hooks_lock); ++ hook = flow_offload_lookup_hook(table, dev); ++ if (hook) ++ hook->used = true; ++ else ++ xt_flowoffload_create_hook(table, dev); ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_register_hooks(struct xt_flowoffload_table *table) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++restart: ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->registered) ++ continue; ++ ++ hook->registered = true; ++ hook->net = dev_net(hook->ops.dev); ++ spin_unlock_bh(&hooks_lock); ++ nf_register_net_hook(hook->net, &hook->ops); ++ if (table->ft.flags & NF_FLOWTABLE_HW_OFFLOAD) ++ table->ft.type->setup(&table->ft, hook->ops.dev, ++ FLOW_BLOCK_BIND); ++ spin_lock_bh(&hooks_lock); ++ goto restart; ++ } ++ ++} ++ ++static bool ++xt_flowoffload_cleanup_hooks(struct xt_flowoffload_table *table) ++{ ++ struct xt_flowoffload_hook *hook; ++ bool active = false; ++ ++restart: ++ spin_lock_bh(&hooks_lock); ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->used || !hook->registered) { ++ active = true; ++ continue; ++ } ++ ++ hlist_del(&hook->list); ++ spin_unlock_bh(&hooks_lock); ++ if (table->ft.flags & NF_FLOWTABLE_HW_OFFLOAD) ++ table->ft.type->setup(&table->ft, hook->ops.dev, ++ FLOW_BLOCK_UNBIND); ++ nf_unregister_net_hook(hook->net, &hook->ops); ++ kfree(hook); ++ goto restart; ++ } ++ spin_unlock_bh(&hooks_lock); ++ ++ return active; ++} ++ ++static void ++xt_flowoffload_check_hook(struct flow_offload *flow, void *data) ++{ ++ struct xt_flowoffload_table *table = data; ++ struct flow_offload_tuple *tuple0 = &flow->tuplehash[0].tuple; ++ struct flow_offload_tuple *tuple1 = &flow->tuplehash[1].tuple; ++ struct xt_flowoffload_hook *hook; ++ ++ spin_lock_bh(&hooks_lock); ++ hlist_for_each_entry(hook, &table->hooks, list) { ++ if (hook->ops.dev->ifindex != tuple0->iifidx && ++ hook->ops.dev->ifindex != tuple1->iifidx) ++ continue; ++ ++ hook->used = true; ++ } ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_hook_work(struct work_struct *work) ++{ ++ struct xt_flowoffload_table *table; ++ struct xt_flowoffload_hook *hook; ++ int err; ++ ++ table = container_of(work, struct xt_flowoffload_table, work.work); ++ ++ spin_lock_bh(&hooks_lock); ++ xt_flowoffload_register_hooks(table); ++ hlist_for_each_entry(hook, &table->hooks, list) ++ hook->used = false; ++ spin_unlock_bh(&hooks_lock); ++ ++ err = nf_flow_table_iterate(&table->ft, xt_flowoffload_check_hook, ++ table); ++ if (err && err != -EAGAIN) ++ goto out; ++ ++ if (!xt_flowoffload_cleanup_hooks(table)) ++ return; ++ ++out: ++ queue_delayed_work(system_power_efficient_wq, &table->work, HZ); ++} ++ ++static bool ++xt_flowoffload_skip(struct sk_buff *skb, int family) ++{ ++ if (skb_sec_path(skb)) ++ return true; ++ ++ if (family == NFPROTO_IPV4) { ++ const struct ip_options *opt = &(IPCB(skb)->opt); ++ ++ if (unlikely(opt->optlen)) ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool flow_is_valid_ether_device(const struct net_device *dev) ++{ ++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || ++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) ++ return false; ++ ++ return true; ++} ++ ++static void ++xt_flowoffload_route_check_path(struct nf_flow_route *route, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct net_device **out_dev) ++{ ++ const struct dst_entry *dst = route->tuple[dir].dst; ++ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; ++ struct net_device_path_stack stack; ++ enum net_device_path_type prev_type; ++ struct net_device *dev = dst->dev; ++ struct neighbour *n; ++ bool last = false; ++ u8 nud_state; ++ int i; ++ ++ route->tuple[!dir].in.ifindex = dev->ifindex; ++ route->tuple[dir].out.ifindex = dev->ifindex; ++ ++ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM) ++ return; ++ ++ if ((dev->flags & IFF_LOOPBACK) || ++ dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || ++ !is_valid_ether_addr(dev->dev_addr)) ++ return; ++ ++ n = dst_neigh_lookup(dst, daddr); ++ if (!n) ++ return; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ memcpy(route->tuple[dir].out.h_dest, n->ha, ETH_ALEN); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); ++ ++ if (!(nud_state & NUD_VALID)) ++ return; ++ ++ if (dev_fill_forward_path(dev, route->tuple[dir].out.h_dest, &stack) || ++ !stack.num_paths) ++ return; ++ ++ prev_type = DEV_PATH_ETHERNET; ++ for (i = 0; i <= stack.num_paths; i++) { ++ const struct net_device_path *path = &stack.path[i]; ++ int n_encaps = route->tuple[!dir].in.num_encaps; ++ ++ dev = (struct net_device *)path->dev; ++ if (flow_is_valid_ether_device(dev)) { ++ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) { ++ memcpy(route->tuple[dir].out.h_source, ++ dev->dev_addr, ETH_ALEN); ++ route->tuple[dir].out.ifindex = dev->ifindex; ++ } ++ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; ++ } ++ ++ switch (path->type) { ++ case DEV_PATH_PPPOE: ++ case DEV_PATH_VLAN: ++ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || ++ i == stack.num_paths) { ++ last = true; ++ break; ++ } ++ ++ route->tuple[!dir].in.num_encaps++; ++ route->tuple[!dir].in.encap[n_encaps].id = path->encap.id; ++ route->tuple[!dir].in.encap[n_encaps].proto = path->encap.proto; ++ if (path->type == DEV_PATH_PPPOE) ++ memcpy(route->tuple[dir].out.h_dest, ++ path->encap.h_dest, ETH_ALEN); ++ break; ++ case DEV_PATH_BRIDGE: ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_TAG: ++ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || ++ i == stack.num_paths) { ++ last = true; ++ break; ++ } ++ ++ route->tuple[!dir].in.num_encaps++; ++ route->tuple[!dir].in.encap[n_encaps].id = ++ path->bridge.vlan_id; ++ route->tuple[!dir].in.encap[n_encaps].proto = ++ path->bridge.vlan_proto; ++ break; ++ case DEV_PATH_BR_VLAN_UNTAG: ++ route->tuple[!dir].in.num_encaps--; ++ break; ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ route->tuple[!dir].in.ingress_vlans |= BIT(n_encaps - 1); ++ break; ++ case DEV_PATH_BR_VLAN_KEEP: ++ break; ++ } ++ break; ++ default: ++ last = true; ++ break; ++ } ++ ++ if (last) ++ break; ++ } ++ ++ *out_dev = dev; ++ route->tuple[dir].out.hw_ifindex = dev->ifindex; ++ route->tuple[!dir].in.ifindex = dev->ifindex; ++} ++ ++static int ++xt_flowoffload_route_dir(struct nf_flow_route *route, const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ const struct xt_action_param *par, int ifindex) ++{ ++ struct dst_entry *dst = NULL; ++ struct flowi fl; ++ ++ memset(&fl, 0, sizeof(fl)); ++ switch (xt_family(par)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.src.u3.ip; ++ fl.u.ip4.flowi4_oif = ifindex; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.saddr = ct->tuplehash[!dir].tuple.dst.u3.in6; ++ fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.src.u3.in6; ++ fl.u.ip6.flowi6_oif = ifindex; ++ break; ++ } ++ ++ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); ++ if (!dst) ++ return -ENOENT; ++ ++ route->tuple[dir].dst = dst; ++ if (dst_xfrm(dst)) ++ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_XFRM; ++ else ++ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_NEIGH; ++ ++ return 0; ++} ++ ++static int ++xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct, ++ const struct xt_action_param *par, ++ struct nf_flow_route *route, enum ip_conntrack_dir dir, ++ struct net_device **dev) ++{ ++ int ret; ++ ++ ret = xt_flowoffload_route_dir(route, ct, dir, par, ++ dev[dir]->ifindex); ++ if (ret) ++ return ret; ++ ++ ret = xt_flowoffload_route_dir(route, ct, !dir, par, ++ dev[!dir]->ifindex); ++ if (ret) ++ return ret; ++ ++ xt_flowoffload_route_check_path(route, ct, dir, &dev[!dir]); ++ xt_flowoffload_route_check_path(route, ct, !dir, &dev[dir]); ++ ++ return 0; ++} ++ ++static unsigned int ++flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ struct xt_flowoffload_table *table; ++ const struct xt_flowoffload_target_info *info = par->targinfo; ++ struct tcphdr _tcph, *tcph = NULL; ++ enum ip_conntrack_info ctinfo; ++ enum ip_conntrack_dir dir; ++ struct nf_flow_route route = {}; ++ struct flow_offload *flow = NULL; ++ struct net_device *devs[2] = {}; ++ struct nf_conn *ct; ++ struct net *net; ++ ++ if (xt_flowoffload_skip(skb, xt_family(par))) ++ return XT_CONTINUE; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct == NULL) ++ return XT_CONTINUE; ++ ++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { ++ case IPPROTO_TCP: ++ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) ++ return XT_CONTINUE; ++ ++ tcph = skb_header_pointer(skb, par->thoff, ++ sizeof(_tcph), &_tcph); ++ if (unlikely(!tcph || tcph->fin || tcph->rst)) ++ return XT_CONTINUE; ++ break; ++ case IPPROTO_UDP: ++ break; ++ default: ++ return XT_CONTINUE; ++ } ++ ++ if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || ++ ct->status & IPS_SEQ_ADJUST) ++ return XT_CONTINUE; ++ ++ if (!nf_ct_is_confirmed(ct)) ++ return XT_CONTINUE; ++ ++ devs[dir] = xt_out(par); ++ devs[!dir] = xt_in(par); ++ ++ if (!devs[dir] || !devs[!dir]) ++ return XT_CONTINUE; ++ ++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ return XT_CONTINUE; ++ ++ dir = CTINFO2DIR(ctinfo); ++ ++ if (xt_flowoffload_route(skb, ct, par, &route, dir, devs) < 0) ++ goto err_flow_route; ++ ++ flow = flow_offload_alloc(ct); ++ if (!flow) ++ goto err_flow_alloc; ++ ++ if (flow_offload_route_init(flow, &route) < 0) ++ goto err_flow_add; ++ ++ if (tcph) { ++ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; ++ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; ++ } ++ ++ table = &flowtable[!!(info->flags & XT_FLOWOFFLOAD_HW)]; ++ ++ net = read_pnet(&table->ft.net); ++ if (!net) ++ write_pnet(&table->ft.net, xt_net(par)); ++ ++ if (flow_offload_add(&table->ft, flow) < 0) ++ goto err_flow_add; ++ ++ xt_flowoffload_check_device(table, devs[0]); ++ xt_flowoffload_check_device(table, devs[1]); ++ ++ dst_release(route.tuple[dir].dst); ++ dst_release(route.tuple[!dir].dst); ++ ++ return XT_CONTINUE; ++ ++err_flow_add: ++ flow_offload_free(flow); ++err_flow_alloc: ++ dst_release(route.tuple[dir].dst); ++ dst_release(route.tuple[!dir].dst); ++err_flow_route: ++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); ++ ++ return XT_CONTINUE; ++} ++ ++static int flowoffload_chk(const struct xt_tgchk_param *par) ++{ ++ struct xt_flowoffload_target_info *info = par->targinfo; ++ ++ if (info->flags & ~XT_FLOWOFFLOAD_MASK) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static struct xt_target offload_tg_reg __read_mostly = { ++ .family = NFPROTO_UNSPEC, ++ .name = "FLOWOFFLOAD", ++ .revision = 0, ++ .targetsize = sizeof(struct xt_flowoffload_target_info), ++ .usersize = sizeof(struct xt_flowoffload_target_info), ++ .checkentry = flowoffload_chk, ++ .target = flowoffload_tg, ++ .me = THIS_MODULE, ++}; ++ ++static int flow_offload_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct xt_flowoffload_hook *hook0, *hook1; ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_UNREGISTER) ++ return NOTIFY_DONE; ++ ++ spin_lock_bh(&hooks_lock); ++ hook0 = flow_offload_lookup_hook(&flowtable[0], dev); ++ if (hook0) ++ hlist_del(&hook0->list); ++ ++ hook1 = flow_offload_lookup_hook(&flowtable[1], dev); ++ if (hook1) ++ hlist_del(&hook1->list); ++ spin_unlock_bh(&hooks_lock); ++ ++ if (hook0) { ++ nf_unregister_net_hook(hook0->net, &hook0->ops); ++ kfree(hook0); ++ } ++ ++ if (hook1) { ++ nf_unregister_net_hook(hook1->net, &hook1->ops); ++ kfree(hook1); ++ } ++ ++ nf_flow_table_cleanup(dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = flow_offload_netdev_event, ++}; ++ ++static unsigned int ++nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ return nf_flow_offload_ip_hook(priv, skb, state); ++ case htons(ETH_P_IPV6): ++ return nf_flow_offload_ipv6_hook(priv, skb, state); ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static int nf_flow_rule_route_inet(struct net *net, ++ const struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir, ++ struct nf_flow_rule *flow_rule) ++{ ++ const struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; ++ int err; ++ ++ switch (flow_tuple->l3proto) { ++ case NFPROTO_IPV4: ++ err = nf_flow_rule_route_ipv4(net, flow, dir, flow_rule); ++ break; ++ case NFPROTO_IPV6: ++ err = nf_flow_rule_route_ipv6(net, flow, dir, flow_rule); ++ break; ++ default: ++ err = -1; ++ break; ++ } ++ ++ return err; ++} ++ ++static struct nf_flowtable_type flowtable_inet = { ++ .family = NFPROTO_INET, ++ .init = nf_flow_table_init, ++ .setup = nf_flow_table_offload_setup, ++ .action = nf_flow_rule_route_inet, ++ .free = nf_flow_table_free, ++ .hook = nf_flow_offload_inet_hook, ++ .owner = THIS_MODULE, ++}; ++ ++static int init_flowtable(struct xt_flowoffload_table *tbl) ++{ ++ INIT_DELAYED_WORK(&tbl->work, xt_flowoffload_hook_work); ++ tbl->ft.type = &flowtable_inet; ++ ++ return nf_flow_table_init(&tbl->ft); ++} ++ ++static int __init xt_flowoffload_tg_init(void) ++{ ++ int ret; ++ ++ register_netdevice_notifier(&flow_offload_netdev_notifier); ++ ++ ret = init_flowtable(&flowtable[0]); ++ if (ret) ++ return ret; ++ ++ ret = init_flowtable(&flowtable[1]); ++ if (ret) ++ goto cleanup; ++ ++ flowtable[1].ft.flags = NF_FLOWTABLE_HW_OFFLOAD; ++ ++ ret = xt_register_target(&offload_tg_reg); ++ if (ret) ++ goto cleanup2; ++ ++ return 0; ++ ++cleanup2: ++ nf_flow_table_free(&flowtable[1].ft); ++cleanup: ++ nf_flow_table_free(&flowtable[0].ft); ++ return ret; ++} ++ ++static void __exit xt_flowoffload_tg_exit(void) ++{ ++ xt_unregister_target(&offload_tg_reg); ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ nf_flow_table_free(&flowtable[0].ft); ++ nf_flow_table_free(&flowtable[1].ft); ++} ++ ++MODULE_LICENSE("GPL"); ++module_init(xt_flowoffload_tg_init); ++module_exit(xt_flowoffload_tg_exit); +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -7,7 +7,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -395,8 +394,7 @@ flow_offload_lookup(struct nf_flowtable + } + EXPORT_SYMBOL_GPL(flow_offload_lookup); + +-static int +-nf_flow_table_iterate(struct nf_flowtable *flow_table, ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, + void (*iter)(struct flow_offload *flow, void *data), + void *data) + { +@@ -428,6 +426,7 @@ nf_flow_table_iterate(struct nf_flowtabl + + return err; + } ++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); + + static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple) + { +--- /dev/null ++++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _XT_FLOWOFFLOAD_H ++#define _XT_FLOWOFFLOAD_H ++ ++#include ++ ++enum { ++ XT_FLOWOFFLOAD_HW = 1 << 0, ++ ++ XT_FLOWOFFLOAD_MASK = XT_FLOWOFFLOAD_HW ++}; ++ ++struct xt_flowoffload_target_info { ++ __u32 flags; ++}; ++ ++#endif /* _XT_FLOWOFFLOAD_H */ +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -270,6 +270,10 @@ void nf_flow_table_free(struct nf_flowta + + void flow_offload_teardown(struct flow_offload *flow); + ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data); ++ + void nf_flow_snat_port(const struct flow_offload *flow, + struct sk_buff *skb, unsigned int thoff, + u8 protocol, enum flow_offload_tuple_dir dir); diff --git a/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch b/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch new file mode 100644 index 0000000000..0639ad4e48 --- /dev/null +++ b/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch @@ -0,0 +1,24 @@ +From 6d3bc769657b0ee7c7506dad9911111c4226a7ea Mon Sep 17 00:00:00 2001 +From: Imre Kaloz +Date: Fri, 7 Jul 2017 17:21:05 +0200 +Subject: mac80211: increase wireless mesh header size + +lede-commit 3d4466cfd8f75f717efdb1f96fdde3c70d865fc1 +Signed-off-by: Imre Kaloz +--- + include/linux/netdevice.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -144,8 +144,8 @@ static inline bool dev_xmit_complete(int + + #if defined(CONFIG_HYPERV_NET) + # define LL_MAX_HEADER 128 +-#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) +-# if defined(CONFIG_MAC80211_MESH) ++#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) || 1 ++# if defined(CONFIG_MAC80211_MESH) || 1 + # define LL_MAX_HEADER 128 + # else + # define LL_MAX_HEADER 96 diff --git a/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch b/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch new file mode 100644 index 0000000000..5541c0bc89 --- /dev/null +++ b/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch @@ -0,0 +1,27 @@ +From a6ccb238939b25851474a279b20367fd24a0e816 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:21:53 +0200 +Subject: hack: net: fq_codel: tune defaults for small devices + +Assume that x86_64 devices always have a big memory and do not need this +optimization compared to devices with only 32 MB or 64 MB RAM. + +Signed-off-by: Felix Fietkau +--- + net/sched/sch_fq_codel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -469,7 +469,11 @@ static int fq_codel_init(struct Qdisc *s + + sch->limit = 10*1024; + q->flows_cnt = 1024; ++#ifdef CONFIG_X86_64 + q->memory_limit = 32 << 20; /* 32 MBytes */ ++#else ++ q->memory_limit = 4 << 20; /* 4 MBytes */ ++#endif + q->drop_batch_size = 64; + q->quantum = psched_mtu(qdisc_dev(sch)); + INIT_LIST_HEAD(&q->new_flows); diff --git a/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch b/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch new file mode 100644 index 0000000000..b90e1fc441 --- /dev/null +++ b/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch @@ -0,0 +1,129 @@ +From 36e516290611e613aa92996cb4339561452695b4 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:24:23 +0200 +Subject: net: swconfig: adds openwrt switch layer + +Signed-off-by: Felix Fietkau +--- + drivers/net/phy/Kconfig | 83 +++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/Makefile | 15 +++++++++ + include/uapi/linux/Kbuild | 1 + + 3 files changed, 99 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -61,6 +61,80 @@ config SFP + depends on HWMON || HWMON=n + select MDIO_I2C + ++comment "Switch configuration API + drivers" ++ ++config SWCONFIG ++ tristate "Switch configuration API" ++ help ++ Switch configuration API using netlink. This allows ++ you to configure the VLAN features of certain switches. ++ ++config SWCONFIG_LEDS ++ bool "Switch LED trigger support" ++ depends on (SWCONFIG && LEDS_TRIGGERS) ++ ++config ADM6996_PHY ++ tristate "Driver for ADM6996 switches" ++ select SWCONFIG ++ help ++ Currently supports the ADM6996FC and ADM6996M switches. ++ Support for FC is very limited. ++ ++config AR8216_PHY ++ tristate "Driver for Atheros AR8216 switches" ++ select SWCONFIG ++ select ETHERNET_PACKET_MANGLE ++ ++config AR8216_PHY_LEDS ++ bool "Atheros AR8216 switch LED support" ++ depends on (AR8216_PHY && LEDS_CLASS) ++ ++source "drivers/net/phy/b53/Kconfig" ++ ++config IP17XX_PHY ++ tristate "Driver for IC+ IP17xx switches" ++ select SWCONFIG ++ ++config PSB6970_PHY ++ tristate "Lantiq XWAY Tantos (PSB6970) Ethernet switch" ++ select SWCONFIG ++ ++config RTL8306_PHY ++ tristate "Driver for Realtek RTL8306S switches" ++ select SWCONFIG ++ ++config RTL8366_SMI ++ tristate "Driver for the RTL8366 SMI interface" ++ depends on GPIOLIB ++ help ++ This module implements the SMI interface protocol which is used ++ by some RTL8366 ethernet switch devices via the generic GPIO API. ++ ++if RTL8366_SMI ++ ++config RTL8366_SMI_DEBUG_FS ++ bool "RTL8366 SMI interface debugfs support" ++ depends on DEBUG_FS ++ default n ++ ++config RTL8366S_PHY ++ tristate "Driver for the Realtek RTL8366S switch" ++ select SWCONFIG ++ ++config RTL8366RB_PHY ++ tristate "Driver for the Realtek RTL8366RB switch" ++ select SWCONFIG ++ ++config RTL8367_PHY ++ tristate "Driver for the Realtek RTL8367R/M switches" ++ select SWCONFIG ++ ++config RTL8367B_PHY ++ tristate "Driver fot the Realtek RTL8367R-VB switch" ++ select SWCONFIG ++ ++endif # RTL8366_SMI ++ + comment "MII PHY device drivers" + + config AMD_PHY +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -24,6 +24,19 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ + obj-$(CONFIG_PHYLINK) += phylink.o + obj-$(CONFIG_PHYLIB) += libphy.o + ++obj-$(CONFIG_SWCONFIG) += swconfig.o ++obj-$(CONFIG_ADM6996_PHY) += adm6996.o ++obj-$(CONFIG_AR8216_PHY) += ar8216.o ar8327.o ++obj-$(CONFIG_SWCONFIG_B53) += b53/ ++obj-$(CONFIG_IP17XX_PHY) += ip17xx.o ++obj-$(CONFIG_PSB6970_PHY) += psb6970.o ++obj-$(CONFIG_RTL8306_PHY) += rtl8306.o ++obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o ++obj-$(CONFIG_RTL8366S_PHY) += rtl8366s.o ++obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb.o ++obj-$(CONFIG_RTL8367_PHY) += rtl8367.o ++obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o ++ + obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o + + obj-$(CONFIG_SFP) += sfp.o +--- a/include/linux/platform_data/b53.h ++++ b/include/linux/platform_data/b53.h +@@ -29,6 +29,9 @@ struct b53_platform_data { + u32 chip_id; + u16 enabled_ports; + ++ /* allow to specify an ethX alias */ ++ const char *alias; ++ + /* only used by MMAP'd driver */ + unsigned big_endian:1; + void __iomem *regs; diff --git a/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch b/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch new file mode 100644 index 0000000000..03725653f9 --- /dev/null +++ b/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -2097,6 +2097,7 @@ static int mv88e6xxx_port_fdb_add(struct + struct mv88e6xxx_chip *chip = ds->priv; + int err; + ++ vid = vid ? : 1; + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, + MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); +@@ -2111,6 +2112,7 @@ static int mv88e6xxx_port_fdb_del(struct + struct mv88e6xxx_chip *chip = ds->priv; + int err; + ++ vid = vid ? : 1; + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 0); + mv88e6xxx_reg_unlock(chip); diff --git a/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch new file mode 100644 index 0000000000..68cac73935 --- /dev/null +++ b/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch @@ -0,0 +1,12 @@ +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -2659,6 +2659,9 @@ static int mv88e6xxx_setup_port(struct m + if (dsa_is_cpu_port(ds, port)) + reg = 0; + ++ /* Disable ATU member violation interrupt */ ++ reg |= MV88E6XXX_PORT_ASSOC_VECTOR_IGNORE_WRONG; ++ + err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, + reg); + if (err) diff --git a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch new file mode 100644 index 0000000000..4d4420aa2f --- /dev/null +++ b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch @@ -0,0 +1,142 @@ +From: Birger Koblitz +Date: Sun, 5 Sep 2021 15:13:10 +0200 +Subject: [PATCH] kernel: Add AQR113C and AQR813 support + +This hack adds support for the Aquantia 4th generation, 10GBit +PHYs AQR113C and AQR813. + +Signed-off-by: Birger Koblitz + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -20,8 +20,10 @@ + #define PHY_ID_AQR105 0x03a1b4a2 + #define PHY_ID_AQR106 0x03a1b4d0 + #define PHY_ID_AQR107 0x03a1b4e0 ++#define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR813 0x31c31cb2 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -330,6 +332,49 @@ static int aqr107_read_rate(struct phy_d + return 0; + } + ++static int aqr113c_read_status(struct phy_device *phydev) ++{ ++ int val, ret; ++ ++ ret = aqr_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) ++ return 0; ++ ++ // On AQR113C, the speed returned by aqr_read_status is wrong ++ aqr107_read_rate(phydev); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); ++ if (val < 0) ++ return val; ++ ++ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: ++ phydev->interface = PHY_INTERFACE_MODE_10GKR; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: ++ phydev->interface = PHY_INTERFACE_MODE_10GBASER; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: ++ phydev->interface = PHY_INTERFACE_MODE_USXGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ default: ++ phydev->interface = PHY_INTERFACE_MODE_NA; ++ break; ++ } ++ ++ /* Read downshifted rate from vendor register */ ++ return aqr107_read_rate(phydev); ++} ++ + static int aqr107_read_status(struct phy_device *phydev) + { + int val, ret; +@@ -460,7 +505,7 @@ static void aqr107_chip_info(struct phy_ + build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); + prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); + +- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", ++ phydev_info(phydev, "FW %u.%u, Build %u, Provisioning %u\n", + fw_major, fw_minor, build_id, prov_id); + } + +@@ -632,6 +677,24 @@ static struct phy_driver aqr_driver[] = + .link_change_notify = aqr107_link_change_notify, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr113c_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), + .name = "Aquantia AQCS109", + .probe = aqr107_probe, +@@ -657,6 +720,24 @@ static struct phy_driver aqr_driver[] = + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR813), ++ .name = "Aquantia AQR813", ++ .probe = aqr107_probe, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr113c_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -667,8 +748,10 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { } + }; + diff --git a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch new file mode 100644 index 0000000000..67808c35f8 --- /dev/null +++ b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch @@ -0,0 +1,167 @@ +From ffe387740bbe88dd88bbe04d6375902708003d6e Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 7 Jul 2017 17:25:00 +0200 +Subject: net: add packet mangeling + +ar8216 switches have a hardware bug, which renders normal 802.1q support +unusable. Packet mangling is required to fix up the vlan for incoming +packets. + +Signed-off-by: Felix Fietkau +--- + include/linux/netdevice.h | 11 +++++++++++ + include/linux/skbuff.h | 14 ++++---------- + net/Kconfig | 6 ++++++ + net/core/dev.c | 20 +++++++++++++++----- + net/core/skbuff.c | 17 +++++++++++++++++ + net/ethernet/eth.c | 6 ++++++ + 6 files changed, 59 insertions(+), 15 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1618,6 +1618,7 @@ enum netdev_priv_flags { + IFF_FAILOVER_SLAVE = 1<<28, + IFF_L3MDEV_RX_HANDLER = 1<<29, + IFF_LIVE_RENAME_OK = 1<<30, ++ IFF_NO_IP_ALIGN = 1<<31, + }; + + #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN +@@ -1650,6 +1651,7 @@ enum netdev_priv_flags { + #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE + #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER + #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK ++#define IFF_NO_IP_ALIGN IFF_NO_IP_ALIGN + + /* Specifies the type of the struct net_device::ml_priv pointer */ + enum netdev_ml_priv_type { +@@ -1990,6 +1992,11 @@ struct net_device { + const struct tlsdev_ops *tlsdev_ops; + #endif + ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ void (*eth_mangle_rx)(struct net_device *dev, struct sk_buff *skb); ++ struct sk_buff *(*eth_mangle_tx)(struct net_device *dev, struct sk_buff *skb); ++#endif ++ + const struct header_ops *header_ops; + + unsigned int flags; +@@ -2080,6 +2087,10 @@ struct net_device { + struct mpls_dev __rcu *mpls_ptr; + #endif + ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ void *phy_ptr; /* PHY device specific data */ ++#endif ++ + /* + * Cache lines mostly used on receive path (including eth_type_trans()) + */ +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2710,6 +2710,10 @@ static inline int pskb_trim(struct sk_bu + return (len < skb->len) ? __pskb_trim(skb, len) : 0; + } + ++extern struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length, gfp_t gfp); ++ ++ + /** + * pskb_trim_unique - remove end from a paged unique (not cloned) buffer + * @skb: buffer to alter +@@ -2841,16 +2845,6 @@ static inline struct sk_buff *dev_alloc_ + } + + +-static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, +- unsigned int length, gfp_t gfp) +-{ +- struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); +- +- if (NET_IP_ALIGN && skb) +- skb_reserve(skb, NET_IP_ALIGN); +- return skb; +-} +- + static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, + unsigned int length) + { +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -26,6 +26,12 @@ menuconfig NET + + if NET + ++config ETHERNET_PACKET_MANGLE ++ bool ++ help ++ This option can be selected by phy drivers that need to mangle ++ packets going in or out of an ethernet device. ++ + config WANT_COMPAT_NETLINK_MESSAGES + bool + help +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3646,6 +3646,11 @@ static int xmit_one(struct sk_buff *skb, + if (dev_nit_active(dev)) + dev_queue_xmit_nit(skb, dev); + ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ if (dev->eth_mangle_tx && !(skb = dev->eth_mangle_tx(dev, skb))) ++ return NETDEV_TX_OK; ++#endif ++ + len = skb->len; + PRANDOM_ADD_NOISE(skb, dev, txq, len + jiffies); + trace_net_dev_start_xmit(skb, dev); +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -60,6 +60,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -553,6 +554,22 @@ skb_fail: + } + EXPORT_SYMBOL(__napi_alloc_skb); + ++struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length, gfp_t gfp) ++{ ++ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); ++ ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN)) ++ return skb; ++#endif ++ ++ if (NET_IP_ALIGN && skb) ++ skb_reserve(skb, NET_IP_ALIGN); ++ return skb; ++} ++EXPORT_SYMBOL(__netdev_alloc_skb_ip_align); ++ + void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, + int size, unsigned int truesize) + { +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -171,6 +171,12 @@ __be16 eth_type_trans(struct sk_buff *sk + const struct ethhdr *eth; + + skb->dev = dev; ++ ++#ifdef CONFIG_ETHERNET_PACKET_MANGLE ++ if (dev->eth_mangle_rx) ++ dev->eth_mangle_rx(dev, skb); ++#endif ++ + skb_reset_mac_header(skb); + + eth = (struct ethhdr *)skb->data; diff --git a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch new file mode 100644 index 0000000000..e3541400d7 --- /dev/null +++ b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -0,0 +1,154 @@ +From 5f62951fba63a9f9cfff564209426bdea5fcc371 Mon Sep 17 00:00:00 2001 +From: Alex Marginean +Date: Tue, 27 Aug 2019 15:16:56 +0300 +Subject: [PATCH] drivers: net: phy: aquantia: enable AQR112 and AQR412 + +Adds support for AQR112 and AQR412 which is mostly based on existing code +with the addition of code configuring the protocol on system side. +This allows changing the system side protocol without having to deploy a +different firmware on the PHY. + +Signed-off-by: Alex Marginean +--- + drivers/net/phy/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 88 insertions(+) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -20,9 +20,11 @@ + #define PHY_ID_AQR105 0x03a1b4a2 + #define PHY_ID_AQR106 0x03a1b4d0 + #define PHY_ID_AQR107 0x03a1b4e0 ++#define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR813 0x31c31cb2 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +@@ -123,6 +125,29 @@ + #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) + #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) + ++/* registers in MDIO_MMD_VEND1 region */ ++#define AQUANTIA_VND1_GLOBAL_SC 0x000 ++#define AQUANTIA_VND1_GLOBAL_SC_LP BIT(0xb) ++ ++/* global start rate, the protocol associated with this speed is used by default ++ * on SI. ++ */ ++#define AQUANTIA_VND1_GSTART_RATE 0x31a ++#define AQUANTIA_VND1_GSTART_RATE_OFF 0 ++#define AQUANTIA_VND1_GSTART_RATE_100M 1 ++#define AQUANTIA_VND1_GSTART_RATE_1G 2 ++#define AQUANTIA_VND1_GSTART_RATE_10G 3 ++#define AQUANTIA_VND1_GSTART_RATE_2_5G 4 ++#define AQUANTIA_VND1_GSTART_RATE_5G 5 ++ ++/* SYSCFG registers for 100M, 1G, 2.5G, 5G, 10G */ ++#define AQUANTIA_VND1_GSYSCFG_BASE 0x31b ++#define AQUANTIA_VND1_GSYSCFG_100M 0 ++#define AQUANTIA_VND1_GSYSCFG_1G 1 ++#define AQUANTIA_VND1_GSYSCFG_2_5G 2 ++#define AQUANTIA_VND1_GSYSCFG_5G 3 ++#define AQUANTIA_VND1_GSYSCFG_10G 4 ++ + struct aqr107_hw_stat { + const char *name; + int reg; +@@ -243,6 +268,51 @@ static int aqr_config_aneg(struct phy_de + return genphy_c45_check_and_restart_aneg(phydev, changed); + } + ++static struct { ++ u16 syscfg; ++ int cnt; ++ u16 start_rate; ++} aquantia_syscfg[PHY_INTERFACE_MODE_MAX] = { ++ [PHY_INTERFACE_MODE_SGMII] = {0x04b, AQUANTIA_VND1_GSYSCFG_1G, ++ AQUANTIA_VND1_GSTART_RATE_1G}, ++ [PHY_INTERFACE_MODE_2500BASEX] = {0x144, AQUANTIA_VND1_GSYSCFG_2_5G, ++ AQUANTIA_VND1_GSTART_RATE_2_5G}, ++ [PHY_INTERFACE_MODE_XGMII] = {0x100, AQUANTIA_VND1_GSYSCFG_10G, ++ AQUANTIA_VND1_GSTART_RATE_10G}, ++ [PHY_INTERFACE_MODE_USXGMII] = {0x080, AQUANTIA_VND1_GSYSCFG_10G, ++ AQUANTIA_VND1_GSTART_RATE_10G}, ++}; ++ ++/* Sets up protocol on system side before calling aqr_config_aneg */ ++static int aqr_config_aneg_set_prot(struct phy_device *phydev) ++{ ++ int if_type = phydev->interface; ++ int i; ++ ++ if (!aquantia_syscfg[if_type].cnt) ++ return 0; ++ ++ /* set PHY in low power mode so we can configure protocols */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, ++ AQUANTIA_VND1_GLOBAL_SC_LP); ++ mdelay(10); ++ ++ /* set the default rate to enable the SI link */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, ++ aquantia_syscfg[if_type].start_rate); ++ ++ for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ AQUANTIA_VND1_GSYSCFG_BASE + i, ++ aquantia_syscfg[if_type].syscfg); ++ ++ /* wake PHY back up */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); ++ mdelay(10); ++ ++ return aqr_config_aneg(phydev); ++} ++ + static int aqr_config_intr(struct phy_device *phydev) + { + bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; +@@ -738,6 +808,30 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112), ++ .name = "Aquantia AQR112", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR412), ++ .name = "Aquantia AQR412", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -748,9 +842,11 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { } + }; diff --git a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch new file mode 100644 index 0000000000..9c5df905bb --- /dev/null +++ b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -0,0 +1,34 @@ +From 5f008cb22f60da4e10375f22266c1a4e20b1252e Mon Sep 17 00:00:00 2001 +From: Alex Marginean +Date: Fri, 20 Sep 2019 18:22:52 +0300 +Subject: [PATCH] drivers: net: phy: aquantia: fix system side protocol + misconfiguration + +Do not set up protocols for speeds that are not supported by FW. Enabling +these protocols leads to link issues on system side. + +Signed-off-by: Alex Marginean +--- + drivers/net/phy/aquantia_main.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -301,10 +301,16 @@ static int aqr_config_aneg_set_prot(stru + phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, + aquantia_syscfg[if_type].start_rate); + +- for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) ++ for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) { ++ u16 reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ++ AQUANTIA_VND1_GSYSCFG_BASE + i); ++ if (!reg) ++ continue; ++ + phy_write_mmd(phydev, MDIO_MMD_VEND1, + AQUANTIA_VND1_GSYSCFG_BASE + i, + aquantia_syscfg[if_type].syscfg); ++ } + + /* wake PHY back up */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); diff --git a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch new file mode 100644 index 0000000000..7a661309f9 --- /dev/null +++ b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch @@ -0,0 +1,43 @@ +From 2e677e4ae8f8330f68013163b060d0fda3a43095 Mon Sep 17 00:00:00 2001 +From: "Langer, Thomas" +Date: Fri, 9 Jul 2021 17:36:46 +0200 +Subject: [PATCH] PONRTSYS-8842: aquantia: Add AQR113 driver support + +Add a new entry for AQR113 PHY_ID +--- + drivers/net/phy/aquantia_main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -21,6 +21,7 @@ + #define PHY_ID_AQR106 0x03a1b4d0 + #define PHY_ID_AQR107 0x03a1b4e0 + #define PHY_ID_AQR112 0x03a1b662 ++#define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 +@@ -827,6 +828,14 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113), ++ .name = "Aquantia AQR113", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR412), + .name = "Aquantia AQR412", + .probe = aqr107_probe, +@@ -849,6 +858,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, diff --git a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch new file mode 100644 index 0000000000..40ad0ff583 --- /dev/null +++ b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -0,0 +1,63 @@ +From 3b92ee7b7899b6beffb2b484c58326e36612a873 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 23 Dec 2021 14:52:56 +0000 +Subject: [PATCH] net: phy: aquantia: add PHY_ID for AQR112R + +As advised by Ian Chang this PHY is used in Puzzle devices. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/aquantia_main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -21,6 +21,8 @@ + #define PHY_ID_AQR106 0x03a1b4d0 + #define PHY_ID_AQR107 0x03a1b4e0 + #define PHY_ID_AQR112 0x03a1b662 ++#define PHY_ID_AQR112C 0x03a1b790 ++#define PHY_ID_AQR112R 0x31c31d12 + #define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQCS109 0x03a1b5c2 +@@ -828,6 +830,30 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112C), ++ .name = "Aquantia AQR112C", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR112R), ++ .name = "Aquantia AQR112R", ++ .probe = aqr107_probe, ++ .config_aneg = aqr_config_aneg_set_prot, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR113), + .name = "Aquantia AQR113", + .config_aneg = aqr_config_aneg, +@@ -858,6 +884,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, diff --git a/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch b/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch new file mode 100644 index 0000000000..f94d16c0ff --- /dev/null +++ b/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch @@ -0,0 +1,74 @@ +From 82985725e071f2a5735052f18e109a32aeac3a0b Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 02:38:31 +0200 +Subject: [PATCH] net: usb: r8152: add LED configuration from OF + +This adds the ability to configure the LED configuration register using +OF. This way, the correct value for board specific LED configuration can +be determined. + +Signed-off-by: David Bauer +--- + drivers/net/usb/r8152.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -5301,6 +5302,22 @@ static void rtl_tally_reset(struct r8152 + ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); + } + ++static int r8152_led_configuration(struct r8152 *tp) ++{ ++ u32 led_data; ++ int ret; ++ ++ ret = of_property_read_u32(tp->udev->dev.of_node, "realtek,led-data", ++ &led_data); ++ ++ if (ret) ++ return ret; ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_LEDSEL, led_data); ++ ++ return 0; ++} ++ + static void r8152b_init(struct r8152 *tp) + { + u32 ocp_data; +@@ -5342,6 +5359,8 @@ static void r8152b_init(struct r8152 *tp + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); + ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); + ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ r8152_led_configuration(tp); + } + + static void r8153_init(struct r8152 *tp) +@@ -5487,6 +5506,8 @@ static void r8153_init(struct r8152 *tp) + tp->coalesce = COALESCE_SLOW; + break; + } ++ ++ r8152_led_configuration(tp); + } + + static void r8153b_init(struct r8152 *tp) +@@ -5573,6 +5594,8 @@ static void r8153b_init(struct r8152 *tp + rtl_tally_reset(tp); + + tp->coalesce = 15000; /* 15 us */ ++ ++ r8152_led_configuration(tp); + } + + static int rtl8152_pre_reset(struct usb_interface *intf) diff --git a/target/linux/generic/hack-5.15/761-dt-bindings-net-add-RTL8152-binding-documentation.patch b/target/linux/generic/hack-5.15/761-dt-bindings-net-add-RTL8152-binding-documentation.patch new file mode 100644 index 0000000000..be262b993c --- /dev/null +++ b/target/linux/generic/hack-5.15/761-dt-bindings-net-add-RTL8152-binding-documentation.patch @@ -0,0 +1,54 @@ +From 3ee05f4aa64fc86af3be5bc176ba5808de9260a7 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 15:30:33 +0200 +Subject: [PATCH] dt-bindings: net: add RTL8152 binding documentation + +Add binding documentation for the Realtek RTL8152 / RTL8153 USB ethernet +adapters. + +Signed-off-by: David Bauer +--- + .../bindings/net/realtek,rtl8152.yaml | 36 +++++++++++++++++++ + 1 file changed, 36 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/realtek,rtl8152.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/realtek,rtl8152.yaml +@@ -0,0 +1,36 @@ ++# SPDX-License-Identifier: GPL-2.0 ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/realtek,rtl8152.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Realtek RTL8152/RTL8153 series USB ethernet ++ ++maintainers: ++ - David Bauer ++ ++properties: ++ compatible: ++ oneOf: ++ - items: ++ - enum: ++ - realtek,rtl8152 ++ - realtek,rtl8153 ++ ++ reg: ++ description: The device number on the USB bus ++ ++ realtek,led-data: ++ description: Value to be written to the LED configuration register. ++ ++required: ++ - compatible ++ - reg ++ ++examples: ++ - | ++ usb-eth@2 { ++ compatible = "realtek,rtl8153"; ++ reg = <2>; ++ realtek,led-data = <0x87>; ++ }; +\ No newline at end of file diff --git a/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch new file mode 100644 index 0000000000..bc377bdd82 --- /dev/null +++ b/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch @@ -0,0 +1,98 @@ +From 3cb240533ab787899dc7f17aa7d6c5b4810e2e58 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Fri, 7 Jul 2017 17:26:01 +0200 +Subject: bcm53xx: bgmac: use srab switch driver + +use the srab switch driver on these SoCs. + +Signed-off-by: Hauke Mehrtens +--- + drivers/net/ethernet/broadcom/bgmac-bcma.c | 1 + + drivers/net/ethernet/broadcom/bgmac.c | 24 ++++++++++++++++++++++++ + drivers/net/ethernet/broadcom/bgmac.h | 4 ++++ + 3 files changed, 29 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c +@@ -280,6 +280,7 @@ static int bgmac_probe(struct bcma_devic + bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; + bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; + bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; ++ bgmac->feature_flags |= BGMAC_FEAT_SRAB; + break; + default: + bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1408,6 +1409,17 @@ static const struct ethtool_ops bgmac_et + .set_link_ksettings = phy_ethtool_set_link_ksettings, + }; + ++static struct b53_platform_data bgmac_b53_pdata = { ++}; ++ ++static struct platform_device bgmac_b53_dev = { ++ .name = "b53-srab-switch", ++ .id = -1, ++ .dev = { ++ .platform_data = &bgmac_b53_pdata, ++ }, ++}; ++ + /************************************************** + * MII + **************************************************/ +@@ -1542,6 +1554,14 @@ int bgmac_enet_probe(struct bgmac *bgmac + /* Omit FCS from max MTU size */ + net_dev->max_mtu = BGMAC_RX_MAX_FRAME_SIZE - ETH_FCS_LEN; + ++ if ((bgmac->feature_flags & BGMAC_FEAT_SRAB) && !bgmac_b53_pdata.regs) { ++ bgmac_b53_pdata.regs = ioremap(0x18007000, 0x1000); ++ ++ err = platform_device_register(&bgmac_b53_dev); ++ if (!err) ++ bgmac->b53_device = &bgmac_b53_dev; ++ } ++ + err = register_netdev(bgmac->net_dev); + if (err) { + dev_err(bgmac->dev, "Cannot register net device\n"); +@@ -1564,6 +1584,10 @@ EXPORT_SYMBOL_GPL(bgmac_enet_probe); + + void bgmac_enet_remove(struct bgmac *bgmac) + { ++ if (bgmac->b53_device) ++ platform_device_unregister(&bgmac_b53_dev); ++ bgmac->b53_device = NULL; ++ + unregister_netdev(bgmac->net_dev); + phy_disconnect(bgmac->net_dev->phydev); + netif_napi_del(&bgmac->napi); +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -428,6 +428,7 @@ + #define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII BIT(18) + #define BGMAC_FEAT_CC7_IF_TYPE_RGMII BIT(19) + #define BGMAC_FEAT_IDM_MASK BIT(20) ++#define BGMAC_FEAT_SRAB BIT(21) + + struct bgmac_slot_info { + union { +@@ -533,6 +534,9 @@ struct bgmac { + void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask, + u32 set); + int (*phy_connect)(struct bgmac *bgmac); ++ ++ /* platform device for associated switch */ ++ struct platform_device *b53_device; + }; + + struct bgmac *bgmac_alloc(struct device *dev); diff --git a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch new file mode 100644 index 0000000000..cb6f46760b --- /dev/null +++ b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch @@ -0,0 +1,33 @@ +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1024,6 +1024,7 @@ static const struct usb_device_id produc + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ ++ {QMI_MATCH_FF_FF_FF(0x05c6, 0xf601)}, /* MeigLink SLM750 */ + + /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -243,6 +243,8 @@ static void option_instat_callback(struc + #define UBLOX_PRODUCT_R6XX 0x90fa + /* These Yuga products use Qualcomm's vendor ID */ + #define YUGA_PRODUCT_CLM920_NC5 0x9625 ++/* These MeigLink products use Qualcomm's vendor ID */ ++#define MEIGLINK_PRODUCT_SLM750 0xf601 + + #define QUECTEL_VENDOR_ID 0x2c7c + /* These Quectel products use Quectel's vendor ID */ +@@ -1127,6 +1129,11 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) }, + { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), + .driver_info = RSVD(4) }, ++ /* Meiglink products using Qualcomm vendor ID */ ++ // Works OK. In case of some issues check macros that are used by Quectel Products ++ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0xff, 0xff), ++ .driver_info = NUMEP2 }, ++ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), + .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, diff --git a/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch new file mode 100644 index 0000000000..76f89acdcd --- /dev/null +++ b/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,162 @@ +From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 30/36] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + #include "gpiolib-of.h" +@@ -1039,3 +1041,72 @@ void of_gpiochip_remove(struct gpio_chip + { + of_node_put(chip->of_node); + } ++ ++#ifdef CONFIG_GPIO_SYSFS ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ if (!gpio_is_valid(gpio)) ++ return gpio; ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++ .probe = of_gpio_export_probe, ++}; ++ ++module_platform_driver(gpio_export_driver); ++ ++#endif +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -125,6 +125,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -715,6 +715,7 @@ static inline void devm_acpi_dev_remove_ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -572,7 +572,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -634,6 +634,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -655,6 +657,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) diff --git a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch new file mode 100644 index 0000000000..247b50d536 --- /dev/null +++ b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch @@ -0,0 +1,162 @@ +From 3b6115d6b57a263bdc8c9b1df273bd4a7955eead Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 8 Jul 2017 08:16:31 +0200 +Subject: debloat: add some debloat patches, strip down procfs and make O_DIRECT support optional, saves ~15K after lzma on MIPS + +Signed-off-by: Felix Fietkau +--- + net/Kconfig | 3 +++ + net/core/Makefile | 3 ++- + net/core/sock.c | 2 ++ + net/ipv4/Kconfig | 1 + + net/netlink/Kconfig | 1 + + net/packet/Kconfig | 1 + + net/unix/Kconfig | 1 + + 7 files changed, 11 insertions(+), 1 deletion(-) + +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -104,6 +104,9 @@ source "net/mptcp/Kconfig" + + endif # if INET + ++config SOCK_DIAG ++ bool ++ + config NETWORK_SECMARK + bool "Security Marking" + help +--- a/net/core/Makefile ++++ b/net/core/Makefile +@@ -10,9 +10,10 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core. + + obj-y += dev.o dev_addr_lists.o dst.o netevent.o \ + neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ +- sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ ++ dev_ioctl.o tso.o sock_reuseport.o \ + fib_notifier.o xdp.o flow_offload.o + ++obj-$(CONFIG_SOCK_DIAG) += sock_diag.o + obj-y += net-sysfs.o + obj-$(CONFIG_PAGE_POOL) += page_pool.o + obj-$(CONFIG_PROC_FS) += net-procfs.o +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -114,6 +114,7 @@ + #include + #include + #include ++#include + + #include + +@@ -141,6 +142,7 @@ + + static DEFINE_MUTEX(proto_list_mutex); + static LIST_HEAD(proto_list); ++DEFINE_COOKIE(sock_cookie); + + static void sock_inuse_add(struct net *net, int val); + +@@ -526,6 +528,18 @@ discard_and_relse: + } + EXPORT_SYMBOL(__sk_receive_skb); + ++u64 __sock_gen_cookie(struct sock *sk) ++{ ++ while (1) { ++ u64 res = atomic64_read(&sk->sk_cookie); ++ ++ if (res) ++ return res; ++ res = gen_cookie_next(&sock_cookie); ++ atomic64_cmpxchg(&sk->sk_cookie, 0, res); ++ } ++} ++ + struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) + { + struct dst_entry *dst = __sk_dst_get(sk); +@@ -1834,9 +1848,11 @@ static void __sk_free(struct sock *sk) + if (likely(sk->sk_net_refcnt)) + sock_inuse_add(sock_net(sk), -1); + ++#ifdef CONFIG_SOCK_DIAG + if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk))) + sock_diag_broadcast_destroy(sk); + else ++#endif + sk_destruct(sk); + } + +--- a/net/core/sock_diag.c ++++ b/net/core/sock_diag.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -20,20 +19,6 @@ static int (*inet_rcv_compat)(struct sk_ + static DEFINE_MUTEX(sock_diag_table_mutex); + static struct workqueue_struct *broadcast_wq; + +-DEFINE_COOKIE(sock_cookie); +- +-u64 __sock_gen_cookie(struct sock *sk) +-{ +- while (1) { +- u64 res = atomic64_read(&sk->sk_cookie); +- +- if (res) +- return res; +- res = gen_cookie_next(&sock_cookie); +- atomic64_cmpxchg(&sk->sk_cookie, 0, res); +- } +-} +- + int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie) + { + u64 res; +--- a/net/ipv4/Kconfig ++++ b/net/ipv4/Kconfig +@@ -414,6 +414,7 @@ config INET_TUNNEL + + config INET_DIAG + tristate "INET: socket monitoring interface" ++ select SOCK_DIAG + default y + help + Support for INET (TCP, DCCP, etc) socket monitoring interface used by +--- a/net/netlink/Kconfig ++++ b/net/netlink/Kconfig +@@ -5,6 +5,7 @@ + + config NETLINK_DIAG + tristate "NETLINK: socket monitoring interface" ++ select SOCK_DIAG + default n + help + Support for NETLINK socket monitoring interface used by the ss tool. +--- a/net/packet/Kconfig ++++ b/net/packet/Kconfig +@@ -19,6 +19,7 @@ config PACKET + config PACKET_DIAG + tristate "Packet: sockets monitoring interface" + depends on PACKET ++ select SOCK_DIAG + default n + help + Support for PF_PACKET sockets monitoring interface used by the ss tool. +--- a/net/unix/Kconfig ++++ b/net/unix/Kconfig +@@ -28,6 +28,7 @@ config UNIX_SCM + config UNIX_DIAG + tristate "UNIX: socket monitoring interface" + depends on UNIX ++ select SOCK_DIAG + default n + help + Support for UNIX socket monitoring interface used by the ss tool. diff --git a/target/linux/generic/hack-5.15/902-debloat_proc.patch b/target/linux/generic/hack-5.15/902-debloat_proc.patch new file mode 100644 index 0000000000..33a3e3c5d5 --- /dev/null +++ b/target/linux/generic/hack-5.15/902-debloat_proc.patch @@ -0,0 +1,408 @@ +From 9e3f1d0805b2d919904dd9a4ff0d956314cc3cba Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 8 Jul 2017 08:20:09 +0200 +Subject: debloat: procfs + +Signed-off-by: Felix Fietkau +--- + fs/locks.c | 2 ++ + fs/proc/Kconfig | 5 +++++ + fs/proc/consoles.c | 3 +++ + fs/proc/proc_tty.c | 11 ++++++++++- + include/net/snmp.h | 18 +++++++++++++++++- + ipc/msg.c | 3 +++ + ipc/sem.c | 2 ++ + ipc/shm.c | 2 ++ + ipc/util.c | 3 +++ + kernel/exec_domain.c | 2 ++ + kernel/irq/proc.c | 9 +++++++++ + kernel/time/timer_list.c | 2 ++ + mm/vmalloc.c | 2 ++ + mm/vmstat.c | 8 +++++--- + net/8021q/vlanproc.c | 6 ++++++ + net/core/net-procfs.c | 18 ++++++++++++------ + net/core/sock.c | 2 ++ + net/ipv4/fib_trie.c | 18 ++++++++++++------ + net/ipv4/proc.c | 3 +++ + net/ipv4/route.c | 3 +++ + 20 files changed, 105 insertions(+), 17 deletions(-) + +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2993,6 +2993,8 @@ static const struct seq_operations locks + + static int __init proc_locks_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + proc_create_seq_private("locks", 0, NULL, &locks_seq_operations, + sizeof(struct locks_iterator), NULL); + return 0; +--- a/fs/proc/Kconfig ++++ b/fs/proc/Kconfig +@@ -100,6 +100,11 @@ config PROC_CHILDREN + Say Y if you are running any user-space software which takes benefit from + this interface. For example, rkt is such a piece of software. + ++config PROC_STRIPPED ++ default n ++ depends on EXPERT ++ bool "Strip non-essential /proc functionality to reduce code size" ++ + config PROC_PID_ARCH_STATUS + def_bool n + depends on PROC_FS +--- a/fs/proc/consoles.c ++++ b/fs/proc/consoles.c +@@ -92,6 +92,9 @@ static const struct seq_operations conso + + static int __init proc_consoles_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + proc_create_seq("consoles", 0, NULL, &consoles_op); + return 0; + } +--- a/fs/proc/proc_tty.c ++++ b/fs/proc/proc_tty.c +@@ -133,7 +133,10 @@ static const struct seq_operations tty_d + void proc_tty_register_driver(struct tty_driver *driver) + { + struct proc_dir_entry *ent; +- ++ ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + if (!driver->driver_name || driver->proc_entry || + !driver->ops->proc_show) + return; +@@ -150,6 +153,9 @@ void proc_tty_unregister_driver(struct t + { + struct proc_dir_entry *ent; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + ent = driver->proc_entry; + if (!ent) + return; +@@ -164,6 +170,9 @@ void proc_tty_unregister_driver(struct t + */ + void __init proc_tty_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + if (!proc_mkdir("tty", NULL)) + return; + proc_mkdir("tty/ldisc", NULL); /* Preserved: it's userspace visible */ +--- a/include/net/snmp.h ++++ b/include/net/snmp.h +@@ -124,6 +124,21 @@ struct linux_tls_mib { + #define DECLARE_SNMP_STAT(type, name) \ + extern __typeof__(type) __percpu *name + ++#ifdef CONFIG_PROC_STRIPPED ++#define __SNMP_STATS_DUMMY(mib) \ ++ do { (void) mib->mibs[0]; } while(0) ++ ++#define __SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) ++#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) __SNMP_STATS_DUMMY(mib) ++#define SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) ++#define SNMP_DEC_STATS(mib, field) __SNMP_STATS_DUMMY(mib) ++#define __SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib) ++#define SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib) ++#define SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib) ++#define __SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib) ++ ++#else ++ + #define __SNMP_INC_STATS(mib, field) \ + __this_cpu_inc(mib->mibs[field]) + +@@ -154,8 +169,9 @@ struct linux_tls_mib { + __this_cpu_add(ptr[basefield##OCTETS], addend); \ + } while (0) + ++#endif + +-#if BITS_PER_LONG==32 ++#if (BITS_PER_LONG==32) && !defined(CONFIG_PROC_STRIPPED) + + #define __SNMP_ADD_STATS64(mib, field, addend) \ + do { \ +--- a/ipc/msg.c ++++ b/ipc/msg.c +@@ -1350,6 +1350,9 @@ void __init msg_init(void) + { + msg_init_ns(&init_ipc_ns); + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + ipc_init_proc_interface("sysvipc/msg", + " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", + IPC_MSG_IDS, sysvipc_msg_proc_show); +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -266,6 +266,8 @@ void sem_exit_ns(struct ipc_namespace *n + void __init sem_init(void) + { + sem_init_ns(&init_ipc_ns); ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; + ipc_init_proc_interface("sysvipc/sem", + " key semid perms nsems uid gid cuid cgid otime ctime\n", + IPC_SEM_IDS, sysvipc_sem_proc_show); +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -154,6 +154,8 @@ pure_initcall(ipc_ns_init); + + void __init shm_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; + ipc_init_proc_interface("sysvipc/shm", + #if BITS_PER_LONG <= 32 + " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n", +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -140,6 +140,9 @@ void __init ipc_init_proc_interface(cons + struct proc_dir_entry *pde; + struct ipc_proc_iface *iface; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + iface = kmalloc(sizeof(*iface), GFP_KERNEL); + if (!iface) + return; +--- a/kernel/exec_domain.c ++++ b/kernel/exec_domain.c +@@ -29,6 +29,8 @@ static int execdomains_proc_show(struct + + static int __init proc_execdomains_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + proc_create_single("execdomains", 0, NULL, execdomains_proc_show); + return 0; + } +--- a/kernel/irq/proc.c ++++ b/kernel/irq/proc.c +@@ -341,6 +341,9 @@ void register_irq_proc(unsigned int irq, + void __maybe_unused *irqp = (void *)(unsigned long) irq; + char name [MAX_NAMELEN]; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) ++ return; ++ + if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip)) + return; + +@@ -394,6 +397,9 @@ void unregister_irq_proc(unsigned int ir + { + char name [MAX_NAMELEN]; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) ++ return; ++ + if (!root_irq_dir || !desc->dir) + return; + #ifdef CONFIG_SMP +@@ -432,6 +438,9 @@ void init_irq_proc(void) + unsigned int irq; + struct irq_desc *desc; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP)) ++ return; ++ + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", NULL); + if (!root_irq_dir) +--- a/kernel/time/timer_list.c ++++ b/kernel/time/timer_list.c +@@ -370,6 +370,8 @@ static int __init init_timer_list_procfs + { + struct proc_dir_entry *pe; + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + pe = proc_create_seq_private("timer_list", 0400, NULL, &timer_list_sops, + sizeof(struct timer_list_iter), NULL); + if (!pe) +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -3572,6 +3572,8 @@ static const struct seq_operations vmall + + static int __init proc_vmalloc_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + if (IS_ENABLED(CONFIG_NUMA)) + proc_create_seq_private("vmallocinfo", 0400, NULL, + &vmalloc_op, +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -2044,10 +2044,12 @@ void __init init_mm_internals(void) + start_shepherd_timer(); + #endif + #ifdef CONFIG_PROC_FS +- proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op); +- proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { ++ proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op); ++ proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op); ++ proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op); ++ } + proc_create_seq("vmstat", 0444, NULL, &vmstat_op); +- proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op); + #endif + } + +--- a/net/8021q/vlanproc.c ++++ b/net/8021q/vlanproc.c +@@ -93,6 +93,9 @@ void vlan_proc_cleanup(struct net *net) + { + struct vlan_net *vn = net_generic(net, vlan_net_id); + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return; ++ + if (vn->proc_vlan_conf) + remove_proc_entry(name_conf, vn->proc_vlan_dir); + +@@ -112,6 +115,9 @@ int __net_init vlan_proc_init(struct net + { + struct vlan_net *vn = net_generic(net, vlan_net_id); + ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net); + if (!vn->proc_vlan_dir) + goto err; +--- a/net/core/net-procfs.c ++++ b/net/core/net-procfs.c +@@ -320,10 +320,12 @@ static int __net_init dev_proc_net_init( + if (!proc_create_net("dev", 0444, net->proc_net, &dev_seq_ops, + sizeof(struct seq_net_private))) + goto out; +- if (!proc_create_seq("softnet_stat", 0444, net->proc_net, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_seq("softnet_stat", 0444, net->proc_net, + &softnet_seq_ops)) + goto out_dev; +- if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops, + sizeof(struct seq_net_private))) + goto out_softnet; + +@@ -333,9 +335,11 @@ static int __net_init dev_proc_net_init( + out: + return rc; + out_ptype: +- remove_proc_entry("ptype", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("ptype", net->proc_net); + out_softnet: +- remove_proc_entry("softnet_stat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("softnet_stat", net->proc_net); + out_dev: + remove_proc_entry("dev", net->proc_net); + goto out; +@@ -345,8 +349,10 @@ static void __net_exit dev_proc_net_exit + { + wext_proc_exit(net); + +- remove_proc_entry("ptype", net->proc_net); +- remove_proc_entry("softnet_stat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { ++ remove_proc_entry("ptype", net->proc_net); ++ remove_proc_entry("softnet_stat", net->proc_net); ++ } + remove_proc_entry("dev", net->proc_net); + } + +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -3699,6 +3699,8 @@ static __net_initdata struct pernet_oper + + static int __init proto_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; + return register_pernet_subsys(&proto_net_ops); + } + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -2986,11 +2986,13 @@ static const struct seq_operations fib_r + + int __net_init fib_proc_init(struct net *net) + { +- if (!proc_create_net("fib_trie", 0444, net->proc_net, &fib_trie_seq_ops, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_net("fib_trie", 0444, net->proc_net, &fib_trie_seq_ops, + sizeof(struct fib_trie_iter))) + goto out1; + +- if (!proc_create_net_single("fib_triestat", 0444, net->proc_net, ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) && ++ !proc_create_net_single("fib_triestat", 0444, net->proc_net, + fib_triestat_seq_show, NULL)) + goto out2; + +@@ -3001,17 +3003,21 @@ int __net_init fib_proc_init(struct net + return 0; + + out3: +- remove_proc_entry("fib_triestat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("fib_triestat", net->proc_net); + out2: +- remove_proc_entry("fib_trie", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ remove_proc_entry("fib_trie", net->proc_net); + out1: + return -ENOMEM; + } + + void __net_exit fib_proc_exit(struct net *net) + { +- remove_proc_entry("fib_trie", net->proc_net); +- remove_proc_entry("fib_triestat", net->proc_net); ++ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) { ++ remove_proc_entry("fib_trie", net->proc_net); ++ remove_proc_entry("fib_triestat", net->proc_net); ++ } + remove_proc_entry("route", net->proc_net); + } + +--- a/net/ipv4/proc.c ++++ b/net/ipv4/proc.c +@@ -528,5 +528,8 @@ static __net_initdata struct pernet_oper + + int __init ip_misc_proc_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + return register_pernet_subsys(&ip_proc_ops); + } +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -410,6 +410,9 @@ static struct pernet_operations ip_rt_pr + + static int __init ip_rt_proc_init(void) + { ++ if (IS_ENABLED(CONFIG_PROC_STRIPPED)) ++ return 0; ++ + return register_pernet_subsys(&ip_rt_proc_ops); + } + diff --git a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch new file mode 100644 index 0000000000..54e78cedc8 --- /dev/null +++ b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch @@ -0,0 +1,92 @@ +From e3692cb2fcd5ba1244512a0f43b8118f65f1c375 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 8 Jul 2017 08:20:43 +0200 +Subject: debloat: dmabuf + +Signed-off-by: Felix Fietkau +--- + drivers/base/Kconfig | 2 +- + drivers/dma-buf/Makefile | 10 +++++++--- + drivers/dma-buf/dma-buf.c | 4 +++- + kernel/sched/core.c | 1 + + 4 files changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -184,7 +184,7 @@ config SOC_BUS + source "drivers/base/regmap/Kconfig" + + config DMA_SHARED_BUFFER +- bool ++ tristate + default n + select IRQ_WORK + help +--- a/drivers/dma-buf/heaps/Makefile ++++ b/drivers/dma-buf/heaps/Makefile +@@ -1,4 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 +-obj-y += heap-helpers.o +-obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +-obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o ++dma-buf-objs-y += heap-helpers.o ++dma-buf-objs-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o ++dma-buf-objs-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o +--- a/drivers/dma-buf/Makefile ++++ b/drivers/dma-buf/Makefile +@@ -1,15 +1,19 @@ + # SPDX-License-Identifier: GPL-2.0-only +-obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \ ++obj-$(CONFIG_DMA_SHARED_BUFFER) := dma-shared-buffer.o ++ ++dma-buf-objs-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \ + dma-resv.o seqno-fence.o +-obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o +-obj-$(CONFIG_DMABUF_HEAPS) += heaps/ +-obj-$(CONFIG_SYNC_FILE) += sync_file.o +-obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o +-obj-$(CONFIG_UDMABUF) += udmabuf.o ++dma-buf-objs-$(CONFIG_DMABUF_HEAPS) += dma-heap.o ++obj-$(CONFIG_DMABUF_HEAPS) += heaps/ ++dma-buf-objs-$(CONFIG_SYNC_FILE) += sync_file.o ++dma-buf-objs-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o ++dma-buf-objs-$(CONFIG_UDMABUF) += udmabuf.o + + dmabuf_selftests-y := \ + selftest.o \ + st-dma-fence.o \ + st-dma-fence-chain.o + +-obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o ++dma-buf-objs-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o ++ ++dma-shared-buffer-objs := $(dma-buf-objs-y) +--- a/drivers/dma-buf/dma-buf.c ++++ b/drivers/dma-buf/dma-buf.c +@@ -1419,4 +1419,5 @@ static void __exit dma_buf_deinit(void) + dma_buf_uninit_debugfs(); + kern_unmount(dma_buf_mnt); + } +-__exitcall(dma_buf_deinit); ++module_exit(dma_buf_deinit); ++MODULE_LICENSE("GPL"); +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -3065,6 +3065,7 @@ int wake_up_state(struct task_struct *p, + { + return try_to_wake_up(p, state, 0); + } ++EXPORT_SYMBOL_GPL(wake_up_state); + + /* + * Perform scheduler related setup for a newly forked process p. +--- a/fs/d_path.c ++++ b/fs/d_path.c +@@ -311,6 +311,7 @@ char *dynamic_dname(struct dentry *dentr + buffer += buflen - sz; + return memcpy(buffer, temp, sz); + } ++EXPORT_SYMBOL_GPL(dynamic_dname); + + char *simple_dname(struct dentry *dentry, char *buffer, int buflen) + { diff --git a/target/linux/generic/hack-5.15/910-kobject_uevent.patch b/target/linux/generic/hack-5.15/910-kobject_uevent.patch new file mode 100644 index 0000000000..c4c41ca400 --- /dev/null +++ b/target/linux/generic/hack-5.15/910-kobject_uevent.patch @@ -0,0 +1,32 @@ +From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 16 Jul 2017 16:56:10 +0200 +Subject: lib: add uevent_next_seqnum() + +Signed-off-by: Felix Fietkau +--- + include/linux/kobject.h | 5 +++++ + lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +--- a/lib/kobject_uevent.c ++++ b/lib/kobject_uevent.c +@@ -179,6 +179,18 @@ out: + return r; + } + ++u64 uevent_next_seqnum(void) ++{ ++ u64 seq; ++ ++ mutex_lock(&uevent_sock_mutex); ++ seq = ++uevent_seqnum; ++ mutex_unlock(&uevent_sock_mutex); ++ ++ return seq; ++} ++EXPORT_SYMBOL_GPL(uevent_next_seqnum); ++ + /** + * kobject_synth_uevent - send synthetic uevent with arguments + * diff --git a/target/linux/generic/hack-5.15/911-kobject_add_broadcast_uevent.patch b/target/linux/generic/hack-5.15/911-kobject_add_broadcast_uevent.patch new file mode 100644 index 0000000000..a487d55193 --- /dev/null +++ b/target/linux/generic/hack-5.15/911-kobject_add_broadcast_uevent.patch @@ -0,0 +1,76 @@ +From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sun, 16 Jul 2017 16:56:10 +0200 +Subject: lib: add uevent_next_seqnum() + +Signed-off-by: Felix Fietkau +--- + include/linux/kobject.h | 5 +++++ + lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +--- a/include/linux/kobject.h ++++ b/include/linux/kobject.h +@@ -32,6 +32,8 @@ + #define UEVENT_NUM_ENVP 64 /* number of env pointers */ + #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ + ++struct sk_buff; ++ + #ifdef CONFIG_UEVENT_HELPER + /* path to the userspace helper executed on an event */ + extern char uevent_helper[]; +@@ -244,4 +246,7 @@ int kobject_synth_uevent(struct kobject + __printf(2, 3) + int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...); + ++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, ++ gfp_t allocation); ++ + #endif /* _KOBJECT_H_ */ +--- a/lib/kobject_uevent.c ++++ b/lib/kobject_uevent.c +@@ -691,6 +691,43 @@ int add_uevent_var(struct kobj_uevent_en + EXPORT_SYMBOL_GPL(add_uevent_var); + + #if defined(CONFIG_NET) ++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, ++ gfp_t allocation) ++{ ++ struct uevent_sock *ue_sk; ++ int err = 0; ++ ++ /* send netlink message */ ++ mutex_lock(&uevent_sock_mutex); ++ list_for_each_entry(ue_sk, &uevent_sock_list, list) { ++ struct sock *uevent_sock = ue_sk->sk; ++ struct sk_buff *skb2; ++ ++ skb2 = skb_clone(skb, allocation); ++ if (!skb2) ++ break; ++ ++ err = netlink_broadcast(uevent_sock, skb2, pid, group, ++ allocation); ++ if (err) ++ break; ++ } ++ mutex_unlock(&uevent_sock_mutex); ++ ++ kfree_skb(skb); ++ return err; ++} ++#else ++int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group, ++ gfp_t allocation) ++{ ++ kfree_skb(skb); ++ return 0; ++} ++#endif ++EXPORT_SYMBOL_GPL(broadcast_uevent); ++ ++#if defined(CONFIG_NET) + static int uevent_net_broadcast(struct sock *usk, struct sk_buff *skb, + struct netlink_ext_ack *extack) + { diff --git a/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch b/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch new file mode 100644 index 0000000000..27d4d7f1e5 --- /dev/null +++ b/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch @@ -0,0 +1,12 @@ +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -1055,6 +1055,9 @@ int __init early_init_dt_scan_chosen(uns + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); ++ p = of_get_flat_dt_prop(node, "bootargs-append", &l); ++ if (p != NULL && l > 0) ++ strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE)); + + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else diff --git a/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch b/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch new file mode 100644 index 0000000000..75f63728ec --- /dev/null +++ b/target/linux/generic/pending-5.15/050-dtc-checks-Drop-interrupt-provider-address-cells-check.patch @@ -0,0 +1,28 @@ +From d8d1a9a77863a8c7031ae82a1d461aa78eb72a7b Mon Sep 17 00:00:00 2001 +From: Rob Herring +Date: Mon, 11 Oct 2021 14:12:43 -0500 +Subject: [PATCH] checks: Drop interrupt provider '#address-cells' check + +'#address-cells' is only needed when parsing 'interrupt-map' properties, so +remove it from the common interrupt-provider test. + +Cc: Andre Przywara +Reviewed-by: David Gibson +Signed-off-by: Rob Herring +Message-Id: <20211011191245.1009682-3-robh@kernel.org> +Signed-off-by: David Gibson +--- +--- a/scripts/dtc/checks.c ++++ b/scripts/dtc/checks.c +@@ -1569,11 +1569,6 @@ static void check_interrupt_provider(str + if (!prop) + FAIL(c, dti, node, + "Missing #interrupt-cells in interrupt provider"); +- +- prop = get_property(node, "#address-cells"); +- if (!prop) +- FAIL(c, dti, node, +- "Missing #address-cells in interrupt provider"); + } + WARNING(interrupt_provider, check_interrupt_provider, NULL); + diff --git a/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch new file mode 100644 index 0000000000..282c8196e5 --- /dev/null +++ b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Thu, 22 Oct 2020 22:00:03 +0200 +Subject: [PATCH] compiler.h: only include asm/rwonce.h for kernel code + +This header file is not in uapi, which makes any user space code that includes +linux/compiler.h to fail with the error 'asm/rwonce.h: No such file or directory' + +Fixes: e506ea451254 ("compiler.h: Split {READ,WRITE}_ONCE definitions out into rwonce.h") +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -213,6 +213,8 @@ void ftrace_likely_update(struct ftrace_ + __v; \ + }) + ++#include ++ + #endif /* __KERNEL__ */ + + /* +@@ -245,6 +247,4 @@ static inline void *offset_to_ptr(const + */ + #define prevent_tail_call_optimization() mb() + +-#include +- + #endif /* __LINUX_COMPILER_H */ diff --git a/target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch b/target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch new file mode 100644 index 0000000000..824b9444ee --- /dev/null +++ b/target/linux/generic/pending-5.15/101-Use-stddefs.h-instead-of-compiler.h.patch @@ -0,0 +1,11 @@ +--- a/include/uapi/linux/swab.h ++++ b/include/uapi/linux/swab.h +@@ -3,7 +3,7 @@ + #define _UAPI_LINUX_SWAB_H + + #include +-#include ++#include + #include + #include + diff --git a/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch new file mode 100644 index 0000000000..cc9f99e8b0 --- /dev/null +++ b/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch @@ -0,0 +1,57 @@ +From: Felix Fietkau +Date: Wed, 18 Apr 2018 10:50:05 +0200 +Subject: [PATCH] MIPS: only process negative stack offsets on stack traces + +Fixes endless back traces in cases where the compiler emits a stack +pointer increase in a branch delay slot (probably for some form of +function return). + +[ 3.475442] BUG: MAX_STACK_TRACE_ENTRIES too low! +[ 3.480070] turning off the locking correctness validator. +[ 3.485521] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.34 #0 +[ 3.491475] Stack : 00000000 00000000 00000000 00000000 80e0fce2 00000034 00000000 00000000 +[ 3.499764] 87c3838c 80696377 8061047c 00000000 00000001 00000001 87c2d850 6534689f +[ 3.508059] 00000000 00000000 80e10000 00000000 00000000 000000cf 0000000f 00000000 +[ 3.516353] 00000000 806a0000 00076891 00000000 00000000 00000000 ffffffff 00000000 +[ 3.524648] 806c0000 00000004 80e10000 806a0000 00000003 80690000 00000000 80700000 +[ 3.532942] ... +[ 3.535362] Call Trace: +[ 3.537818] [<80010a48>] show_stack+0x58/0x100 +[ 3.542207] [<804c2f78>] dump_stack+0xe8/0x170 +[ 3.546613] [<80079f90>] save_trace+0xf0/0x110 +[ 3.551010] [<8007b1ec>] mark_lock+0x33c/0x78c +[ 3.555413] [<8007bf48>] __lock_acquire+0x2ac/0x1a08 +[ 3.560337] [<8007de60>] lock_acquire+0x64/0x8c +[ 3.564846] [<804e1570>] _raw_spin_lock_irqsave+0x54/0x78 +[ 3.570186] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.574770] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.579257] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.583839] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.588329] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.592911] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.597401] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.601983] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.606473] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.611055] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.615545] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.620125] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.624619] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.629197] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.633691] [<801b618c>] kernfs_notify+0x94/0xac +[ 3.638269] [<801b7b10>] sysfs_notify+0x74/0xa0 +[ 3.642763] [<801b618c>] kernfs_notify+0x94/0xac + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -380,6 +380,8 @@ static inline int is_sp_move_ins(union m + + if (ip->i_format.opcode == addiu_op || + ip->i_format.opcode == daddiu_op) { ++ if (ip->i_format.simmediate > 0) ++ return 0; + *frame_size = -ip->i_format.simmediate; + return 1; + } diff --git a/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch new file mode 100644 index 0000000000..0d1d3e1137 --- /dev/null +++ b/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -0,0 +1,82 @@ +From: Tobias Wolf +Subject: mm: Fix alloc_node_mem_map with ARCH_PFN_OFFSET calculation + +An rt288x (ralink) based router (Belkin F5D8235 v1) does not boot with any +kernel beyond version 4.3 resulting in: + +BUG: Bad page state in process swapper pfn:086ac + +bisect resulted in: + +a1c34a3bf00af2cede839879502e12dc68491ad5 is the first bad commit +commit a1c34a3bf00af2cede839879502e12dc68491ad5 +Author: Laura Abbott +Date: Thu Nov 5 18:48:46 2015 -0800 + + mm: Don't offset memmap for flatmem + + Srinivas Kandagatla reported bad page messages when trying to remove the + bottom 2MB on an ARM based IFC6410 board + + BUG: Bad page state in process swapper pfn:fffa8 + page:ef7fb500 count:0 mapcount:0 mapping: (null) index:0x0 + flags: 0x96640253(locked|error|dirty|active|arch_1|reclaim|mlocked) + page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set + bad because of flags: + flags: 0x200041(locked|active|mlocked) + Modules linked in: + CPU: 0 PID: 0 Comm: swapper Not tainted 3.19.0-rc3-00007-g412f9ba-dirty +#816 + Hardware name: Qualcomm (Flattened Device Tree) + unwind_backtrace + show_stack + dump_stack + bad_page + free_pages_prepare + free_hot_cold_page + __free_pages + free_highmem_page + mem_init + start_kernel + Disabling lock debugging due to kernel taint + [...] +:040000 040000 2de013c372345fd471cd58f0553c9b38b0ef1cc4 +0a8156f848733dfa21e16c196dfb6c0a76290709 M mm + +This fix for ARM does not account ARCH_PFN_OFFSET for mem_map as later used by +page_to_pfn anymore. + +The following output was generated with two hacked in printk statements: + +printk("before %p vs. %p or %p\n", mem_map, mem_map - offset, mem_map - +(pgdat->node_start_pfn - ARCH_PFN_OFFSET)); + if (page_to_pfn(mem_map) != pgdat->node_start_pfn) + mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET); +printk("after %p\n", mem_map); + +Output: + +[ 0.000000] before 8861b280 vs. 8861b280 or 8851b280 +[ 0.000000] after 8851b280 + +As seen in the first line mem_map with subtraction of offset does not equal the +mem_map after subtraction of ARCH_PFN_OFFSET. + +After adding the offset of ARCH_PFN_OFFSET as well to mem_map as the +previously calculated offset is zero for the named platform it is able to boot +4.4 and 4.9-rc7 again. + +Signed-off-by: Tobias Wolf +--- + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7055,7 +7055,7 @@ static void __ref alloc_node_mem_map(str + if (pgdat == NODE_DATA(0)) { + mem_map = NODE_DATA(0)->node_mem_map; + if (page_to_pfn(mem_map) != pgdat->node_start_pfn) +- mem_map -= offset; ++ mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET); + } + #endif + } diff --git a/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch b/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch new file mode 100644 index 0000000000..355e900a3b --- /dev/null +++ b/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch @@ -0,0 +1,18 @@ +From: Giuseppe Lippolis +Subject: Add the linux,spidev compatible in spidev Several device in ramips have this binding in the dts + +Signed-off-by: Giuseppe Lippolis +--- + drivers/spi/spidev.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -682,6 +682,7 @@ static const struct of_device_id spidev_ + { .compatible = "lwn,bk4" }, + { .compatible = "dh,dhcom-board" }, + { .compatible = "menlo,m53cpld" }, ++ { .compatible = "siliconlabs,si3210" }, + {}, + }; + MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch new file mode 100644 index 0000000000..e48da41fae --- /dev/null +++ b/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch @@ -0,0 +1,78 @@ +From: Felix Fietkau +Subject: jffs2: use .rename2 and add RENAME_WHITEOUT support + +It is required for renames on overlayfs + +Signed-off-by: Felix Fietkau +--- + +--- a/fs/jffs2/dir.c ++++ b/fs/jffs2/dir.c +@@ -609,7 +609,8 @@ static int jffs2_rmdir (struct inode *di + return ret; + } + +-static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev) ++static int __jffs2_mknod (struct inode *dir_i, struct dentry *dentry, ++ umode_t mode, dev_t rdev, bool whiteout) + { + struct jffs2_inode_info *f, *dir_f; + struct jffs2_sb_info *c; +@@ -748,7 +749,11 @@ static int jffs2_mknod (struct inode *di + mutex_unlock(&dir_f->sem); + jffs2_complete_reservation(c); + +- d_instantiate_new(dentry, inode); ++ if (!whiteout) ++ d_instantiate_new(dentry, inode); ++ else ++ unlock_new_inode(inode); ++ + return 0; + + fail: +@@ -756,6 +761,17 @@ static int jffs2_mknod (struct inode *di + return ret; + } + ++static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev) ++{ ++ return __jffs2_mknod(dir_i, dentry, mode, rdev, false); ++} ++ ++static int jffs2_whiteout (struct inode *old_dir, struct dentry *old_dentry) ++{ ++ return __jffs2_mknod(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, ++ WHITEOUT_DEV, true); ++} ++ + static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, + struct inode *new_dir_i, struct dentry *new_dentry, + unsigned int flags) +@@ -766,7 +782,7 @@ static int jffs2_rename (struct inode *o + uint8_t type; + uint32_t now; + +- if (flags & ~RENAME_NOREPLACE) ++ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT)) + return -EINVAL; + + /* The VFS will check for us and prevent trying to rename a +@@ -832,9 +848,14 @@ static int jffs2_rename (struct inode *o + if (d_is_dir(old_dentry) && !victim_f) + inc_nlink(new_dir_i); + +- /* Unlink the original */ +- ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), +- old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); ++ if (flags & RENAME_WHITEOUT) ++ /* Replace with whiteout */ ++ ret = jffs2_whiteout(old_dir_i, old_dentry); ++ else ++ /* Unlink the original */ ++ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), ++ old_dentry->d_name.name, ++ old_dentry->d_name.len, NULL, now); + + /* We don't touch inode->i_nlink */ + diff --git a/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch b/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch new file mode 100644 index 0000000000..dbc72339c6 --- /dev/null +++ b/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch @@ -0,0 +1,73 @@ +From: Felix Fietkau +Subject: jffs2: add RENAME_EXCHANGE support + +Signed-off-by: Felix Fietkau +--- + +--- a/fs/jffs2/dir.c ++++ b/fs/jffs2/dir.c +@@ -779,18 +779,31 @@ static int jffs2_rename (struct inode *o + int ret; + struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); + struct jffs2_inode_info *victim_f = NULL; ++ struct inode *fst_inode = d_inode(old_dentry); ++ struct inode *snd_inode = d_inode(new_dentry); + uint8_t type; + uint32_t now; + +- if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT)) ++ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT|RENAME_EXCHANGE)) + return -EINVAL; + ++ if ((flags & RENAME_EXCHANGE) && (old_dir_i != new_dir_i)) { ++ if (S_ISDIR(fst_inode->i_mode) && !S_ISDIR(snd_inode->i_mode)) { ++ inc_nlink(new_dir_i); ++ drop_nlink(old_dir_i); ++ } ++ else if (!S_ISDIR(fst_inode->i_mode) && S_ISDIR(snd_inode->i_mode)) { ++ drop_nlink(new_dir_i); ++ inc_nlink(old_dir_i); ++ } ++ } ++ + /* The VFS will check for us and prevent trying to rename a + * file over a directory and vice versa, but if it's a directory, + * the VFS can't check whether the victim is empty. The filesystem + * needs to do that for itself. + */ +- if (d_really_is_positive(new_dentry)) { ++ if (d_really_is_positive(new_dentry) && !(flags & RENAME_EXCHANGE)) { + victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); + if (d_is_dir(new_dentry)) { + struct jffs2_full_dirent *fd; +@@ -825,7 +838,7 @@ static int jffs2_rename (struct inode *o + if (ret) + return ret; + +- if (victim_f) { ++ if (victim_f && !(flags & RENAME_EXCHANGE)) { + /* There was a victim. Kill it off nicely */ + if (d_is_dir(new_dentry)) + clear_nlink(d_inode(new_dentry)); +@@ -851,6 +864,12 @@ static int jffs2_rename (struct inode *o + if (flags & RENAME_WHITEOUT) + /* Replace with whiteout */ + ret = jffs2_whiteout(old_dir_i, old_dentry); ++ else if (flags & RENAME_EXCHANGE) ++ /* Replace the original */ ++ ret = jffs2_do_link(c, JFFS2_INODE_INFO(old_dir_i), ++ d_inode(new_dentry)->i_ino, type, ++ old_dentry->d_name.name, old_dentry->d_name.len, ++ now); + else + /* Unlink the original */ + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), +@@ -882,7 +901,7 @@ static int jffs2_rename (struct inode *o + return ret; + } + +- if (d_is_dir(old_dentry)) ++ if (d_is_dir(old_dentry) && !(flags & RENAME_EXCHANGE)) + drop_nlink(old_dir_i); + + new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); diff --git a/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch b/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch new file mode 100644 index 0000000000..de847a1f5c --- /dev/null +++ b/target/linux/generic/pending-5.15/142-jffs2-add-splice-ops.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Subject: jffs2: add splice ops + +Add splice_read using generic_file_splice_read. +Add splice_write using iter_file_splice_write + +Signed-off-by: Felix Fietkau +--- + +--- a/fs/jffs2/file.c ++++ b/fs/jffs2/file.c +@@ -53,6 +53,8 @@ const struct file_operations jffs2_file_ + .open = generic_file_open, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, ++ .splice_read = generic_file_splice_read, ++ .splice_write = iter_file_splice_write, + .unlocked_ioctl=jffs2_ioctl, + .mmap = generic_file_readonly_mmap, + .fsync = jffs2_fsync, diff --git a/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch new file mode 100644 index 0000000000..6de22b1c7d --- /dev/null +++ b/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch @@ -0,0 +1,45 @@ +From: Stephen Hemminger +Subject: bridge: allow receiption on disabled port + +When an ethernet device is enslaved to a bridge, and the bridge STP +detects loss of carrier (or operational state down), then normally +packet receiption is blocked. + +This breaks control applications like WPA which maybe expecting to +receive packets to negotiate to bring link up. The bridge needs to +block forwarding packets from these disabled ports, but there is no +hard requirement to not allow local packet delivery. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Felix Fietkau + +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -195,6 +195,9 @@ static void __br_handle_local_finish(str + /* note: already called with rcu_read_lock */ + static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) + { ++ struct net_bridge_port *p = br_port_get_rcu(skb->dev); ++ ++ if (p->state != BR_STATE_DISABLED) + __br_handle_local_finish(skb); + + /* return 1 to signal the okfn() was called so it's ok to use the skb */ +@@ -348,6 +351,17 @@ static rx_handler_result_t br_handle_fra + + forward: + switch (p->state) { ++ case BR_STATE_DISABLED: ++ if (ether_addr_equal(p->br->dev->dev_addr, dest)) ++ skb->pkt_type = PACKET_HOST; ++ ++ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, ++ dev_net(skb->dev), NULL, skb, skb->dev, NULL, ++ br_handle_local_finish) == 1) { ++ return RX_HANDLER_PASS; ++ } ++ break; ++ + case BR_STATE_FORWARDING: + case BR_STATE_LEARNING: + if (ether_addr_equal(p->br->dev->dev_addr, dest)) diff --git a/target/linux/generic/pending-5.15/190-rtc-rs5c372-support_alarms_up_to_1_week.patch b/target/linux/generic/pending-5.15/190-rtc-rs5c372-support_alarms_up_to_1_week.patch new file mode 100644 index 0000000000..13b79b5c09 --- /dev/null +++ b/target/linux/generic/pending-5.15/190-rtc-rs5c372-support_alarms_up_to_1_week.patch @@ -0,0 +1,94 @@ +From: Daniel González Cabanelas +Subject: [PATCH 1/2] rtc: rs5c372: support alarms up to 1 week + +The Ricoh R2221x, R2223x, RS5C372, RV5C387A chips can handle 1 week +alarms. + +Read the "wday" alarm register and convert it to a date to support up 1 +week in our driver. + +Signed-off-by: Daniel González Cabanelas +--- + drivers/rtc/rtc-rs5c372.c | 48 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 42 insertions(+), 6 deletions(-) + +--- a/drivers/rtc/rtc-rs5c372.c ++++ b/drivers/rtc/rtc-rs5c372.c +@@ -393,7 +393,9 @@ static int rs5c_read_alarm(struct device + { + struct i2c_client *client = to_i2c_client(dev); + struct rs5c372 *rs5c = i2c_get_clientdata(client); +- int status; ++ int status, wday_offs; ++ struct rtc_time rtc; ++ unsigned long alarm_secs; + + status = rs5c_get_regs(rs5c); + if (status < 0) +@@ -403,6 +405,30 @@ static int rs5c_read_alarm(struct device + t->time.tm_sec = 0; + t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); + t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]); ++ t->time.tm_wday = ffs(rs5c->regs[RS5C_REG_ALARM_A_WDAY] & 0x7f) - 1; ++ ++ /* determine the day, month and year based on alarm wday, taking as a ++ * reference the current time from the rtc ++ */ ++ status = rs5c372_rtc_read_time(dev, &rtc); ++ if (status < 0) ++ return status; ++ ++ wday_offs = t->time.tm_wday - rtc.tm_wday; ++ alarm_secs = mktime64(rtc.tm_year + 1900, ++ rtc.tm_mon + 1, ++ rtc.tm_mday + wday_offs, ++ t->time.tm_hour, ++ t->time.tm_min, ++ t->time.tm_sec); ++ ++ if (wday_offs < 0 || (wday_offs == 0 && ++ (t->time.tm_hour < rtc.tm_hour || ++ (t->time.tm_hour == rtc.tm_hour && ++ t->time.tm_min <= rtc.tm_min)))) ++ alarm_secs += 7 * 86400; ++ ++ rtc_time64_to_tm(alarm_secs, &t->time); + + /* ... and status */ + t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE); +@@ -417,12 +443,20 @@ static int rs5c_set_alarm(struct device + struct rs5c372 *rs5c = i2c_get_clientdata(client); + int status, addr, i; + unsigned char buf[3]; ++ struct rtc_time rtc_tm; ++ unsigned long rtc_secs, alarm_secs; + +- /* only handle up to 24 hours in the future, like RTC_ALM_SET */ +- if (t->time.tm_mday != -1 +- || t->time.tm_mon != -1 +- || t->time.tm_year != -1) ++ /* chip only can handle alarms up to one week in the future*/ ++ status = rs5c372_rtc_read_time(dev, &rtc_tm); ++ if (status) ++ return status; ++ rtc_secs = rtc_tm_to_time64(&rtc_tm); ++ alarm_secs = rtc_tm_to_time64(&t->time); ++ if (alarm_secs >= rtc_secs + 7 * 86400) { ++ dev_err(dev, "%s: alarm maximum is one week in the future (%d)\n", ++ __func__, status); + return -EINVAL; ++ } + + /* REVISIT: round up tm_sec */ + +@@ -443,7 +477,9 @@ static int rs5c_set_alarm(struct device + /* set alarm */ + buf[0] = bin2bcd(t->time.tm_min); + buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour); +- buf[2] = 0x7f; /* any/all days */ ++ /* each bit is the day of the week, 0x7f means all days */ ++ buf[2] = (t->time.tm_wday >= 0 && t->time.tm_wday < 7) ? ++ BIT(t->time.tm_wday) : 0x7f; + + for (i = 0; i < sizeof(buf); i++) { + addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); diff --git a/target/linux/generic/pending-5.15/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch b/target/linux/generic/pending-5.15/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch new file mode 100644 index 0000000000..7e9d0e66c0 --- /dev/null +++ b/target/linux/generic/pending-5.15/191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch @@ -0,0 +1,70 @@ +From: Daniel González Cabanelas +Subject: [PATCH 2/2] rtc: rs5c372: let the alarm to be used as wakeup source + +Currently there is no use for the interrupts on the rs5c372 RTC and the +wakealarm isn't enabled. There are some devices like NASes which use this +RTC to wake up from the power off state when the INTR pin is activated by +the alarm clock. + +Enable the alarm and let to be used as a wakeup source. + +Tested on a Buffalo LS421DE NAS. + +Signed-off-by: Daniel González Cabanelas +--- + drivers/rtc/rtc-rs5c372.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/rtc/rtc-rs5c372.c ++++ b/drivers/rtc/rtc-rs5c372.c +@@ -654,6 +654,7 @@ static int rs5c372_probe(struct i2c_clie + int err = 0; + int smbus_mode = 0; + struct rs5c372 *rs5c372; ++ bool rs5c372_can_wakeup_device = false; + + dev_dbg(&client->dev, "%s\n", __func__); + +@@ -689,6 +690,12 @@ static int rs5c372_probe(struct i2c_clie + else + rs5c372->type = id->driver_data; + ++#ifdef CONFIG_OF ++ if(of_property_read_bool(client->dev.of_node, ++ "wakeup-source")) ++ rs5c372_can_wakeup_device = true; ++#endif ++ + /* we read registers 0x0f then 0x00-0x0f; skip the first one */ + rs5c372->regs = &rs5c372->buf[1]; + rs5c372->smbus = smbus_mode; +@@ -722,6 +729,8 @@ static int rs5c372_probe(struct i2c_clie + goto exit; + } + ++ rs5c372->has_irq = 1; ++ + /* if the oscillator lost power and no other software (like + * the bootloader) set it up, do it here. + * +@@ -748,6 +757,10 @@ static int rs5c372_probe(struct i2c_clie + ); + + /* REVISIT use client->irq to register alarm irq ... */ ++ if (rs5c372_can_wakeup_device) { ++ device_init_wakeup(&client->dev, true); ++ } ++ + rs5c372->rtc = devm_rtc_device_register(&client->dev, + rs5c372_driver.driver.name, + &rs5c372_rtc_ops, THIS_MODULE); +@@ -761,6 +774,9 @@ static int rs5c372_probe(struct i2c_clie + if (err) + goto exit; + ++ /* the rs5c372 alarm only supports a minute accuracy */ ++ rs5c372->rtc->uie_unsupported = 1; ++ + return 0; + + exit: diff --git a/target/linux/generic/pending-5.15/201-extra_optimization.patch b/target/linux/generic/pending-5.15/201-extra_optimization.patch new file mode 100644 index 0000000000..cb1de80764 --- /dev/null +++ b/target/linux/generic/pending-5.15/201-extra_optimization.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +Subject: Upgrade to Linux 2.6.19 + +- Includes large parts of the patch from #1021 by dpalffy +- Includes RB532 NAND driver changes by n0-1 + +[john@phrozen.org: feix will add this to his upstream queue] + +lede-commit: bff468813f78f81e36ebb2a3f4354de7365e640f +Signed-off-by: Felix Fietkau +--- + Makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -735,11 +735,11 @@ KBUILD_CFLAGS += $(call cc-disable-warni + KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) + + ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE +-KBUILD_CFLAGS += -O2 ++KBUILD_CFLAGS += -O2 $(EXTRA_OPTIMIZATION) + else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 +-KBUILD_CFLAGS += -O3 ++KBUILD_CFLAGS += -O3 $(EXTRA_OPTIMIZATION) + else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +-KBUILD_CFLAGS += -Os ++KBUILD_CFLAGS += -Os -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION) + endif + + # Tell gcc to never replace conditional load with a non-conditional one diff --git a/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch new file mode 100644 index 0000000000..348a5afa3d --- /dev/null +++ b/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch @@ -0,0 +1,119 @@ +From: Felix Fietkau +Subject: kernel: add a config option for keeping the kallsyms table uncompressed, saving ~9kb kernel size after lzma on ar71xx + +[john@phrozen.org: added to my upstream queue 30.12.2016] +lede-commit: e0e3509b5ce2ccf93d4d67ea907613f5f7ec2eed +Signed-off-by: Felix Fietkau +--- + init/Kconfig | 11 +++++++++++ + kernel/kallsyms.c | 8 ++++++++ + scripts/kallsyms.c | 12 ++++++++++++ + scripts/link-vmlinux.sh | 4 ++++ + 4 files changed, 35 insertions(+) + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1384,6 +1384,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW + the unaligned access emulation. + see arch/parisc/kernel/unaligned.c for reference + ++config KALLSYMS_UNCOMPRESSED ++ bool "Keep kallsyms uncompressed" ++ depends on KALLSYMS ++ help ++ Normally kallsyms contains compressed symbols (using a token table), ++ reducing the uncompressed kernel image size. Keeping the symbol table ++ uncompressed significantly improves the size of this part in compressed ++ kernel images. ++ ++ Say N unless you need compressed kernel images to be small. ++ + config HAVE_PCSPKR_PLATFORM + bool + +--- a/kernel/kallsyms.c ++++ b/kernel/kallsyms.c +@@ -77,6 +77,11 @@ static unsigned int kallsyms_expand_symb + * For every byte on the compressed symbol data, copy the table + * entry for that byte. + */ ++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED ++ memcpy(result, data + 1, len - 1); ++ result += len - 1; ++ len = 0; ++#endif + while (len) { + tptr = &kallsyms_token_table[kallsyms_token_index[*data]]; + data++; +@@ -109,6 +114,9 @@ tail: + */ + static char kallsyms_get_symbol_type(unsigned int off) + { ++#ifdef CONFIG_KALLSYMS_UNCOMPRESSED ++ return kallsyms_names[off + 1]; ++#endif + /* + * Get just the first code, look it up in the token table, + * and return the first char from this token. +--- a/scripts/kallsyms.c ++++ b/scripts/kallsyms.c +@@ -58,6 +58,7 @@ static struct addr_range percpu_range = + static struct sym_entry **table; + static unsigned int table_size, table_cnt; + static int all_symbols; ++static int uncompressed; + static int absolute_percpu; + static int base_relative; + +@@ -486,6 +487,9 @@ static void write_src(void) + + free(markers); + ++ if (uncompressed) ++ return; ++ + output_label("kallsyms_token_table"); + off = 0; + for (i = 0; i < 256; i++) { +@@ -537,6 +541,9 @@ static unsigned char *find_token(unsigne + { + int i; + ++ if (uncompressed) ++ return NULL; ++ + for (i = 0; i < len - 1; i++) { + if (str[i] == token[0] && str[i+1] == token[1]) + return &str[i]; +@@ -609,6 +616,9 @@ static void optimize_result(void) + { + int i, best; + ++ if (uncompressed) ++ return; ++ + /* using the '\0' symbol last allows compress_symbols to use standard + * fast string functions */ + for (i = 255; i >= 0; i--) { +@@ -773,6 +783,8 @@ int main(int argc, char **argv) + absolute_percpu = 1; + else if (strcmp(argv[i], "--base-relative") == 0) + base_relative = 1; ++ else if (strcmp(argv[i], "--uncompressed") == 0) ++ uncompressed = 1; + else + usage(); + } +--- a/scripts/link-vmlinux.sh ++++ b/scripts/link-vmlinux.sh +@@ -186,6 +186,10 @@ kallsyms() + kallsymopt="${kallsymopt} --base-relative" + fi + ++ if [ -n "${CONFIG_KALLSYMS_UNCOMPRESSED}" ]; then ++ kallsymopt="${kallsymopt} --uncompressed" ++ fi ++ + info KSYMS ${2} + ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${2} + } diff --git a/target/linux/generic/pending-5.15/205-backtrace_module_info.patch b/target/linux/generic/pending-5.15/205-backtrace_module_info.patch new file mode 100644 index 0000000000..f46877f254 --- /dev/null +++ b/target/linux/generic/pending-5.15/205-backtrace_module_info.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +Subject: kernel: when KALLSYMS is disabled, print module address + size for matching backtrace entries + +[john@phrozen.org: felix will add this to his upstream queue] + +lede-commit 53827cdc824556cda910b23ce5030c363b8f1461 +Signed-off-by: Felix Fietkau +--- + lib/vsprintf.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/lib/vsprintf.c ++++ b/lib/vsprintf.c +@@ -983,8 +983,10 @@ char *symbol_string(char *buf, char *end + struct printf_spec spec, const char *fmt) + { + unsigned long value; +-#ifdef CONFIG_KALLSYMS + char sym[KSYM_SYMBOL_LEN]; ++#ifndef CONFIG_KALLSYMS ++ struct module *mod; ++ int len; + #endif + + if (fmt[1] == 'R') +@@ -1001,8 +1003,14 @@ char *symbol_string(char *buf, char *end + + return string_nocheck(buf, end, sym, spec); + #else +- return special_hex_number(buf, end, value, sizeof(void *)); ++ len = snprintf(sym, sizeof(sym), "0x%lx", value); ++ mod = __module_address(value); ++ if (mod) ++ snprintf(sym + len, sizeof(sym) - len, " [%s@%p+0x%x]", ++ mod->name, mod->core_layout.base, ++ mod->core_layout.size); + #endif ++ return string(buf, end, sym, spec); + } + + static const struct printf_spec default_str_spec = { diff --git a/target/linux/generic/pending-5.15/240-remove-unsane-filenames-from-deps_initramfs-list.patch b/target/linux/generic/pending-5.15/240-remove-unsane-filenames-from-deps_initramfs-list.patch new file mode 100644 index 0000000000..29cfade716 --- /dev/null +++ b/target/linux/generic/pending-5.15/240-remove-unsane-filenames-from-deps_initramfs-list.patch @@ -0,0 +1,30 @@ +From: Gabor Juhos +Subject: usr: sanitize deps_initramfs list + +If any filename in the intramfs dependency +list contains a colon, that causes a kernel +build error like this: + +/devel/openwrt/build_dir/linux-ar71xx_generic/linux-3.6.6/usr/Makefile:58: *** multiple target patterns. Stop. +make[5]: *** [usr] Error 2 + +Fix it by removing such filenames from the +deps_initramfs list. + +Signed-off-by: Gabor Juhos +Signed-off-by: Felix Fietkau +--- + usr/Makefile | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/usr/Makefile ++++ b/usr/Makefile +@@ -61,6 +61,8 @@ hostprogs := gen_init_cpio + # The dependency list is generated by gen_initramfs.sh -l + -include $(obj)/.initramfs_data.cpio.d + ++deps_initramfs := $(foreach v,$(deps_initramfs),$(if $(findstring :,$(v)),,$(v))) ++ + # do not try to update files included in initramfs + $(deps_initramfs): ; + diff --git a/target/linux/generic/pending-5.15/261-enable_wilink_platform_without_drivers.patch b/target/linux/generic/pending-5.15/261-enable_wilink_platform_without_drivers.patch new file mode 100644 index 0000000000..cd31f9d934 --- /dev/null +++ b/target/linux/generic/pending-5.15/261-enable_wilink_platform_without_drivers.patch @@ -0,0 +1,20 @@ +From: Imre Kaloz +Subject: [PATCH] hack: net: wireless: make the wl12xx glue code available with + compat-wireless, too + +Signed-off-by: Imre Kaloz +--- + drivers/net/wireless/ti/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ti/Kconfig ++++ b/drivers/net/wireless/ti/Kconfig +@@ -20,7 +20,7 @@ source "drivers/net/wireless/ti/wlcore/K + + config WILINK_PLATFORM_DATA + bool "TI WiLink platform data" +- depends on WLCORE_SDIO || WL1251_SDIO ++ depends on WLCORE_SDIO || WL1251_SDIO || ARCH_OMAP2PLUS + default y + help + Small platform data bit needed to pass data to the sdio modules. diff --git a/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch b/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch new file mode 100644 index 0000000000..df738ef97b --- /dev/null +++ b/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch @@ -0,0 +1,31 @@ +From c2deb5ef01a0ef09088832744cbace9e239a6ee0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= +Date: Sat, 28 Mar 2020 12:11:50 +0100 +Subject: [PATCH] generic: platform/mikrotik build bits (5.4) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds platform/mikrotik kernel build bits + +Signed-off-by: Thibaut VARÈNE +--- + drivers/platform/Kconfig | 2 ++ + drivers/platform/Makefile | 1 + + 2 files changed, 3 insertions(+) + +--- a/drivers/platform/Kconfig ++++ b/drivers/platform/Kconfig +@@ -13,3 +13,5 @@ source "drivers/platform/chrome/Kconfig" + source "drivers/platform/mellanox/Kconfig" + + source "drivers/platform/olpc/Kconfig" ++ ++source "drivers/platform/mikrotik/Kconfig" +--- a/drivers/platform/Makefile ++++ b/drivers/platform/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_MIPS) += mips/ + obj-$(CONFIG_OLPC_EC) += olpc/ + obj-$(CONFIG_GOLDFISH) += goldfish/ + obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ ++obj-$(CONFIG_MIKROTIK) += mikrotik/ diff --git a/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch b/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch new file mode 100644 index 0000000000..706c5dee22 --- /dev/null +++ b/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch @@ -0,0 +1,40 @@ +From: Mark Miller +Subject: mips: expose CONFIG_BOOT_RAW + +This exposes the CONFIG_BOOT_RAW symbol in Kconfig. This is needed on +certain Broadcom chipsets running CFE in order to load the kernel. + +Signed-off-by: Mark Miller +Acked-by: Rob Landley +--- +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -1085,9 +1085,6 @@ config FW_ARC + config ARCH_MAY_HAVE_PC_FDC + bool + +-config BOOT_RAW +- bool +- + config CEVT_BCM1480 + bool + +@@ -3182,6 +3179,18 @@ choice + bool "Extend builtin kernel arguments with bootloader arguments" + endchoice + ++config BOOT_RAW ++ bool "Enable the kernel to be executed from the load address" ++ default n ++ help ++ Allow the kernel to be executed from the load address for ++ bootloaders which cannot read the ELF format. This places ++ a jump to start_kernel at the load address. ++ ++ If unsure, say N. ++ ++ ++ + endmenu + + config LOCKDEP_SUPPORT diff --git a/target/linux/generic/pending-5.15/302-mips_no_branch_likely.patch b/target/linux/generic/pending-5.15/302-mips_no_branch_likely.patch new file mode 100644 index 0000000000..271923fca8 --- /dev/null +++ b/target/linux/generic/pending-5.15/302-mips_no_branch_likely.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: mips: use -mno-branch-likely for kernel and userspace + +saves ~11k kernel size after lzma and ~12k squashfs size in the + +lede-commit: 41a039f46450ffae9483d6216422098669da2900 +Signed-off-by: Felix Fietkau +--- + arch/mips/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -95,7 +95,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin + # machines may also. Since BFD is incredibly buggy with respect to + # crossformat linking we rely on the elf2ecoff tool for format conversion. + # +-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe ++cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely + cflags-y += -msoft-float + LDFLAGS_vmlinux += -G 0 -static -n -nostdlib + KBUILD_AFLAGS_MODULE += -mlong-calls diff --git a/target/linux/generic/pending-5.15/305-mips_module_reloc.patch b/target/linux/generic/pending-5.15/305-mips_module_reloc.patch new file mode 100644 index 0000000000..839ba24293 --- /dev/null +++ b/target/linux/generic/pending-5.15/305-mips_module_reloc.patch @@ -0,0 +1,371 @@ +From: Felix Fietkau +Subject: mips: replace -mlong-calls with -mno-long-calls to make function calls faster in kernel modules to achieve this, try to + +lede-commit: 3b3d64743ba2a874df9d70cd19e242205b0a788c +Signed-off-by: Felix Fietkau +--- + arch/mips/Makefile | 5 + + arch/mips/include/asm/module.h | 5 + + arch/mips/kernel/module.c | 279 ++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 284 insertions(+), 5 deletions(-) + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -98,8 +98,18 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin + cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely + cflags-y += -msoft-float + LDFLAGS_vmlinux += -G 0 -static -n -nostdlib ++ifdef CONFIG_64BIT + KBUILD_AFLAGS_MODULE += -mlong-calls + KBUILD_CFLAGS_MODULE += -mlong-calls ++else ++ ifdef CONFIG_DYNAMIC_FTRACE ++ KBUILD_AFLAGS_MODULE += -mlong-calls ++ KBUILD_CFLAGS_MODULE += -mlong-calls ++ else ++ KBUILD_AFLAGS_MODULE += -mno-long-calls ++ KBUILD_CFLAGS_MODULE += -mno-long-calls ++ endif ++endif + + ifeq ($(CONFIG_RELOCATABLE),y) + LDFLAGS_vmlinux += --emit-relocs +--- a/arch/mips/include/asm/module.h ++++ b/arch/mips/include/asm/module.h +@@ -12,6 +12,11 @@ struct mod_arch_specific { + const struct exception_table_entry *dbe_start; + const struct exception_table_entry *dbe_end; + struct mips_hi16 *r_mips_hi16_list; ++ ++ void *phys_plt_tbl; ++ void *virt_plt_tbl; ++ unsigned int phys_plt_offset; ++ unsigned int virt_plt_offset; + }; + + typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ +--- a/arch/mips/kernel/module.c ++++ b/arch/mips/kernel/module.c +@@ -31,14 +31,221 @@ struct mips_hi16 { + static LIST_HEAD(dbe_list); + static DEFINE_SPINLOCK(dbe_lock); + +-#ifdef MODULE_START ++/* ++ * Get the potential max trampolines size required of the init and ++ * non-init sections. Only used if we cannot find enough contiguous ++ * physically mapped memory to put the module into. ++ */ ++static unsigned int ++get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, ++ const char *secstrings, unsigned int symindex, bool is_init) ++{ ++ unsigned long ret = 0; ++ unsigned int i, j; ++ Elf_Sym *syms; ++ ++ /* Everything marked ALLOC (this includes the exported symbols) */ ++ for (i = 1; i < hdr->e_shnum; ++i) { ++ unsigned int info = sechdrs[i].sh_info; ++ ++ if (sechdrs[i].sh_type != SHT_REL ++ && sechdrs[i].sh_type != SHT_RELA) ++ continue; ++ ++ /* Not a valid relocation section? */ ++ if (info >= hdr->e_shnum) ++ continue; ++ ++ /* Don't bother with non-allocated sections */ ++ if (!(sechdrs[info].sh_flags & SHF_ALLOC)) ++ continue; ++ ++ /* If it's called *.init*, and we're not init, we're ++ not interested */ ++ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) ++ != is_init) ++ continue; ++ ++ syms = (Elf_Sym *) sechdrs[symindex].sh_addr; ++ if (sechdrs[i].sh_type == SHT_REL) { ++ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; ++ unsigned int size = sechdrs[i].sh_size / sizeof(*rel); ++ ++ for (j = 0; j < size; ++j) { ++ Elf_Sym *sym; ++ ++ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) ++ continue; ++ ++ sym = syms + ELF_MIPS_R_SYM(rel[j]); ++ if (!is_init && sym->st_shndx != SHN_UNDEF) ++ continue; ++ ++ ret += 4 * sizeof(int); ++ } ++ } else { ++ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; ++ unsigned int size = sechdrs[i].sh_size / sizeof(*rela); ++ ++ for (j = 0; j < size; ++j) { ++ Elf_Sym *sym; ++ ++ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) ++ continue; ++ ++ sym = syms + ELF_MIPS_R_SYM(rela[j]); ++ if (!is_init && sym->st_shndx != SHN_UNDEF) ++ continue; ++ ++ ret += 4 * sizeof(int); ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++#ifndef MODULE_START ++static void *alloc_phys(unsigned long size) ++{ ++ unsigned order; ++ struct page *page; ++ struct page *p; ++ ++ size = PAGE_ALIGN(size); ++ order = get_order(size); ++ ++ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | ++ __GFP_THISNODE, order); ++ if (!page) ++ return NULL; ++ ++ split_page(page, order); ++ ++ /* mark all pages except for the last one */ ++ for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p) ++ set_bit(PG_owner_priv_1, &p->flags); ++ ++ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) ++ __free_page(p); ++ ++ return page_address(page); ++} ++#endif ++ ++static void free_phys(void *ptr) ++{ ++ struct page *page; ++ bool free; ++ ++ page = virt_to_page(ptr); ++ do { ++ free = test_and_clear_bit(PG_owner_priv_1, &page->flags); ++ __free_page(page); ++ page++; ++ } while (free); ++} ++ ++ + void *module_alloc(unsigned long size) + { ++#ifdef MODULE_START + return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END, + GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, + __builtin_return_address(0)); ++#else ++ void *ptr; ++ ++ if (size == 0) ++ return NULL; ++ ++ ptr = alloc_phys(size); ++ ++ /* If we failed to allocate physically contiguous memory, ++ * fall back to regular vmalloc. The module loader code will ++ * create jump tables to handle long jumps */ ++ if (!ptr) ++ return vmalloc(size); ++ ++ return ptr; ++#endif + } ++ ++static inline bool is_phys_addr(void *ptr) ++{ ++#ifdef CONFIG_64BIT ++ return (KSEGX((unsigned long)ptr) == CKSEG0); ++#else ++ return (KSEGX(ptr) == KSEG0); + #endif ++} ++ ++/* Free memory returned from module_alloc */ ++void module_memfree(void *module_region) ++{ ++ if (is_phys_addr(module_region)) ++ free_phys(module_region); ++ else ++ vfree(module_region); ++} ++ ++static void *__module_alloc(int size, bool phys) ++{ ++ void *ptr; ++ ++ if (phys) ++ ptr = kmalloc(size, GFP_KERNEL); ++ else ++ ptr = vmalloc(size); ++ return ptr; ++} ++ ++static void __module_free(void *ptr) ++{ ++ if (is_phys_addr(ptr)) ++ kfree(ptr); ++ else ++ vfree(ptr); ++} ++ ++int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, ++ char *secstrings, struct module *mod) ++{ ++ unsigned int symindex = 0; ++ unsigned int core_size, init_size; ++ int i; ++ ++ mod->arch.phys_plt_offset = 0; ++ mod->arch.virt_plt_offset = 0; ++ mod->arch.phys_plt_tbl = NULL; ++ mod->arch.virt_plt_tbl = NULL; ++ ++ if (IS_ENABLED(CONFIG_64BIT)) ++ return 0; ++ ++ for (i = 1; i < hdr->e_shnum; i++) ++ if (sechdrs[i].sh_type == SHT_SYMTAB) ++ symindex = i; ++ ++ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); ++ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); ++ ++ if ((core_size + init_size) == 0) ++ return 0; ++ ++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); ++ if (!mod->arch.phys_plt_tbl) ++ return -ENOMEM; ++ ++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); ++ if (!mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ return -ENOMEM; ++ } ++ ++ return 0; ++} + + static int apply_r_mips_none(struct module *me, u32 *location, + u32 base, Elf_Addr v, bool rela) +@@ -54,9 +261,40 @@ static int apply_r_mips_32(struct module + return 0; + } + ++static Elf_Addr add_plt_entry_to(unsigned *plt_offset, ++ void *start, Elf_Addr v) ++{ ++ unsigned *tramp = start + *plt_offset; ++ *plt_offset += 4 * sizeof(int); ++ ++ /* adjust carry for addiu */ ++ if (v & 0x00008000) ++ v += 0x10000; ++ ++ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ ++ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ ++ tramp[2] = 0x03200008; /* jr t9 */ ++ tramp[3] = 0x00000000; /* nop */ ++ ++ return (Elf_Addr) tramp; ++} ++ ++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) ++{ ++ if (is_phys_addr(location)) ++ return add_plt_entry_to(&me->arch.phys_plt_offset, ++ me->arch.phys_plt_tbl, v); ++ else ++ return add_plt_entry_to(&me->arch.virt_plt_offset, ++ me->arch.virt_plt_tbl, v); ++ ++} ++ + static int apply_r_mips_26(struct module *me, u32 *location, + u32 base, Elf_Addr v, bool rela) + { ++ u32 ofs = base & 0x03ffffff; ++ + if (v % 4) { + pr_err("module %s: dangerous R_MIPS_26 relocation\n", + me->name); +@@ -64,13 +302,17 @@ static int apply_r_mips_26(struct module + } + + if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { +- pr_err("module %s: relocation overflow\n", +- me->name); +- return -ENOEXEC; ++ v = add_plt_entry(me, location, v + (ofs << 2)); ++ if (!v) { ++ pr_err("module %s: relocation overflow\n", ++ me->name); ++ return -ENOEXEC; ++ } ++ ofs = 0; + } + + *location = (*location & ~0x03ffffff) | +- ((base + (v >> 2)) & 0x03ffffff); ++ ((ofs + (v >> 2)) & 0x03ffffff); + + return 0; + } +@@ -446,9 +688,36 @@ int module_finalize(const Elf_Ehdr *hdr, + list_add(&me->arch.dbe_list, &dbe_list); + spin_unlock_irq(&dbe_lock); + } ++ ++ /* Get rid of the fixup trampoline if we're running the module ++ * from physically mapped address space */ ++ if (me->arch.phys_plt_offset == 0) { ++ __module_free(me->arch.phys_plt_tbl); ++ me->arch.phys_plt_tbl = NULL; ++ } ++ if (me->arch.virt_plt_offset == 0) { ++ __module_free(me->arch.virt_plt_tbl); ++ me->arch.virt_plt_tbl = NULL; ++ } ++ + return 0; + } + ++void module_arch_freeing_init(struct module *mod) ++{ ++ if (mod->state == MODULE_STATE_LIVE) ++ return; ++ ++ if (mod->arch.phys_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ } ++ if (mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.virt_plt_tbl); ++ mod->arch.virt_plt_tbl = NULL; ++ } ++} ++ + void module_arch_cleanup(struct module *mod) + { + spin_lock_irq(&dbe_lock); diff --git a/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch b/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch new file mode 100644 index 0000000000..e1ada22f34 --- /dev/null +++ b/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch @@ -0,0 +1,19 @@ +From: Felix Fietkau +Subject: kernel: adjust mips highmem offset to avoid the need for -mlong-calls on systems with >256M RAM + +Signed-off-by: Felix Fietkau +--- + arch/mips/include/asm/mach-generic/spaces.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/include/asm/mach-generic/spaces.h ++++ b/arch/mips/include/asm/mach-generic/spaces.h +@@ -54,7 +54,7 @@ + * Memory above this physical address will be considered highmem. + */ + #ifndef HIGHMEM_START +-#define HIGHMEM_START _AC(0x20000000, UL) ++#define HIGHMEM_START _AC(0x10000000, UL) + #endif + + #endif /* CONFIG_32BIT */ diff --git a/target/linux/generic/pending-5.15/308-mips32r2_tune.patch b/target/linux/generic/pending-5.15/308-mips32r2_tune.patch new file mode 100644 index 0000000000..bbea947382 --- /dev/null +++ b/target/linux/generic/pending-5.15/308-mips32r2_tune.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: kernel: add -mtune=34kc to MIPS CFLAGS when building for mips32r2 + +This provides a good tradeoff across at least 24Kc-74Kc, while also +producing smaller code. + +Signed-off-by: Felix Fietkau +--- + arch/mips/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -174,7 +174,7 @@ cflags-$(CONFIG_CPU_VR41XX) += -march=r4 + cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap + cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap + cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap +-cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap ++cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -mtune=34kc -Wa,--trap + cflags-$(CONFIG_CPU_MIPS32_R5) += -march=mips32r5 -Wa,--trap -modd-spreg + cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg + cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap diff --git a/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch b/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch new file mode 100644 index 0000000000..794f027f18 --- /dev/null +++ b/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch @@ -0,0 +1,140 @@ +From 87ec87c2ad615c1a177cd08ef5fa29fc739f6e50 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 23 Dec 2018 18:06:53 +0100 +Subject: [PATCH] MIPS: Add CPU option reporting to /proc/cpuinfo + +Many MIPS CPUs have optional CPU features which are not activates for +all CPU cores. Print the CPU options which are implemented in the core +in /proc/cpuinfo. This makes it possible to see what features are +supported and which are not supported. This should cover all standard +MIPS extensions, before it only printed information about the main MIPS +ASEs. + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/kernel/proc.c | 116 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 116 insertions(+) + +--- a/arch/mips/kernel/proc.c ++++ b/arch/mips/kernel/proc.c +@@ -138,6 +138,120 @@ static int show_cpuinfo(struct seq_file + seq_printf(m, "micromips kernel\t: %s\n", + (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no"); + } ++ ++ seq_printf(m, "Options implemented\t:"); ++ if (cpu_has_tlb) ++ seq_printf(m, "%s", " tlb"); ++ if (cpu_has_ftlb) ++ seq_printf(m, "%s", " ftlb"); ++ if (cpu_has_tlbinv) ++ seq_printf(m, "%s", " tlbinv"); ++ if (cpu_has_segments) ++ seq_printf(m, "%s", " segments"); ++ if (cpu_has_rixiex) ++ seq_printf(m, "%s", " rixiex"); ++ if (cpu_has_ldpte) ++ seq_printf(m, "%s", " ldpte"); ++ if (cpu_has_maar) ++ seq_printf(m, "%s", " maar"); ++ if (cpu_has_rw_llb) ++ seq_printf(m, "%s", " rw_llb"); ++ if (cpu_has_4kex) ++ seq_printf(m, "%s", " 4kex"); ++ if (cpu_has_3k_cache) ++ seq_printf(m, "%s", " 3k_cache"); ++ if (cpu_has_4k_cache) ++ seq_printf(m, "%s", " 4k_cache"); ++ if (cpu_has_6k_cache) ++ seq_printf(m, "%s", " 6k_cache"); ++ if (cpu_has_8k_cache) ++ seq_printf(m, "%s", " 8k_cache"); ++ if (cpu_has_tx39_cache) ++ seq_printf(m, "%s", " tx39_cache"); ++ if (cpu_has_octeon_cache) ++ seq_printf(m, "%s", " octeon_cache"); ++ if (cpu_has_fpu) ++ seq_printf(m, "%s", " fpu"); ++ if (cpu_has_32fpr) ++ seq_printf(m, "%s", " 32fpr"); ++ if (cpu_has_cache_cdex_p) ++ seq_printf(m, "%s", " cache_cdex_p"); ++ if (cpu_has_cache_cdex_s) ++ seq_printf(m, "%s", " cache_cdex_s"); ++ if (cpu_has_prefetch) ++ seq_printf(m, "%s", " prefetch"); ++ if (cpu_has_mcheck) ++ seq_printf(m, "%s", " mcheck"); ++ if (cpu_has_ejtag) ++ seq_printf(m, "%s", " ejtag"); ++ if (cpu_has_llsc) ++ seq_printf(m, "%s", " llsc"); ++ if (cpu_has_guestctl0ext) ++ seq_printf(m, "%s", " guestctl0ext"); ++ if (cpu_has_guestctl1) ++ seq_printf(m, "%s", " guestctl1"); ++ if (cpu_has_guestctl2) ++ seq_printf(m, "%s", " guestctl2"); ++ if (cpu_has_guestid) ++ seq_printf(m, "%s", " guestid"); ++ if (cpu_has_drg) ++ seq_printf(m, "%s", " drg"); ++ if (cpu_has_rixi) ++ seq_printf(m, "%s", " rixi"); ++ if (cpu_has_lpa) ++ seq_printf(m, "%s", " lpa"); ++ if (cpu_has_mvh) ++ seq_printf(m, "%s", " mvh"); ++ if (cpu_has_vtag_icache) ++ seq_printf(m, "%s", " vtag_icache"); ++ if (cpu_has_dc_aliases) ++ seq_printf(m, "%s", " dc_aliases"); ++ if (cpu_has_ic_fills_f_dc) ++ seq_printf(m, "%s", " ic_fills_f_dc"); ++ if (cpu_has_pindexed_dcache) ++ seq_printf(m, "%s", " pindexed_dcache"); ++ if (cpu_has_userlocal) ++ seq_printf(m, "%s", " userlocal"); ++ if (cpu_has_nofpuex) ++ seq_printf(m, "%s", " nofpuex"); ++ if (cpu_has_vint) ++ seq_printf(m, "%s", " vint"); ++ if (cpu_has_veic) ++ seq_printf(m, "%s", " veic"); ++ if (cpu_has_inclusive_pcaches) ++ seq_printf(m, "%s", " inclusive_pcaches"); ++ if (cpu_has_perf_cntr_intr_bit) ++ seq_printf(m, "%s", " perf_cntr_intr_bit"); ++ if (cpu_has_ufr) ++ seq_printf(m, "%s", " ufr"); ++ if (cpu_has_fre) ++ seq_printf(m, "%s", " fre"); ++ if (cpu_has_cdmm) ++ seq_printf(m, "%s", " cdmm"); ++ if (cpu_has_small_pages) ++ seq_printf(m, "%s", " small_pages"); ++ if (cpu_has_nan_legacy) ++ seq_printf(m, "%s", " nan_legacy"); ++ if (cpu_has_nan_2008) ++ seq_printf(m, "%s", " nan_2008"); ++ if (cpu_has_ebase_wg) ++ seq_printf(m, "%s", " ebase_wg"); ++ if (cpu_has_badinstr) ++ seq_printf(m, "%s", " badinstr"); ++ if (cpu_has_badinstrp) ++ seq_printf(m, "%s", " badinstrp"); ++ if (cpu_has_contextconfig) ++ seq_printf(m, "%s", " contextconfig"); ++ if (cpu_has_perf) ++ seq_printf(m, "%s", " perf"); ++ if (cpu_has_shared_ftlb_ram) ++ seq_printf(m, "%s", " shared_ftlb_ram"); ++ if (cpu_has_shared_ftlb_entries) ++ seq_printf(m, "%s", " shared_ftlb_entries"); ++ if (cpu_has_mipsmt_pertccounters) ++ seq_printf(m, "%s", " mipsmt_pertccounters"); ++ seq_printf(m, "\n"); ++ + seq_printf(m, "shadow register sets\t: %d\n", + cpu_data[n].srsets); + seq_printf(m, "kscratch registers\t: %d\n", diff --git a/target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch b/target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch new file mode 100644 index 0000000000..191dc6ac3c --- /dev/null +++ b/target/linux/generic/pending-5.15/310-arm_module_unresolved_weak_sym.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: fix errors in unresolved weak symbols on arm + +lede-commit: 570699d4838a907c3ef9f2819bf19eb72997b32f +Signed-off-by: Felix Fietkau +--- + arch/arm/kernel/module.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm/kernel/module.c ++++ b/arch/arm/kernel/module.c +@@ -105,6 +105,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons + return -ENOEXEC; + } + ++ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) && ++ ELF_ST_BIND(sym->st_info) == STB_WEAK) ++ continue; ++ + loc = dstsec->sh_addr + rel->r_offset; + + switch (ELF32_R_TYPE(rel->r_info)) { diff --git a/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch new file mode 100644 index 0000000000..2808c95322 --- /dev/null +++ b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch @@ -0,0 +1,281 @@ +From: Yousong Zhou +Subject: MIPS: kexec: Accept command line parameters from userspace. + +Signed-off-by: Yousong Zhou +--- + arch/mips/kernel/machine_kexec.c | 153 +++++++++++++++++++++++++++++++----- + arch/mips/kernel/machine_kexec.h | 20 +++++ + arch/mips/kernel/relocate_kernel.S | 21 +++-- + 3 files changed, 167 insertions(+), 27 deletions(-) + create mode 100644 arch/mips/kernel/machine_kexec.h + +--- a/arch/mips/kernel/machine_kexec.c ++++ b/arch/mips/kernel/machine_kexec.c +@@ -9,14 +9,11 @@ + #include + #include + ++#include + #include + #include +- +-extern const unsigned char relocate_new_kernel[]; +-extern const size_t relocate_new_kernel_size; +- +-extern unsigned long kexec_start_address; +-extern unsigned long kexec_indirection_page; ++#include ++#include "machine_kexec.h" + + static unsigned long reboot_code_buffer; + +@@ -30,6 +27,101 @@ void (*_crash_smp_send_stop)(void) = NUL + void (*_machine_kexec_shutdown)(void) = NULL; + void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; + ++static void machine_kexec_print_args(void) ++{ ++ unsigned long argc = (int)kexec_args[0]; ++ int i; ++ ++ pr_info("kexec_args[0] (argc): %lu\n", argc); ++ pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]); ++ pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]); ++ pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]); ++ ++ for (i = 0; i < argc; i++) { ++ pr_info("kexec_argv[%d] = %p, %s\n", ++ i, kexec_argv[i], kexec_argv[i]); ++ } ++} ++ ++static void machine_kexec_init_argv(struct kimage *image) ++{ ++ void __user *buf = NULL; ++ size_t bufsz; ++ size_t size; ++ int i; ++ ++ bufsz = 0; ++ for (i = 0; i < image->nr_segments; i++) { ++ struct kexec_segment *seg; ++ ++ seg = &image->segment[i]; ++ if (seg->bufsz < 6) ++ continue; ++ ++ if (strncmp((char *) seg->buf, "kexec ", 6)) ++ continue; ++ ++ buf = seg->buf; ++ bufsz = seg->bufsz; ++ break; ++ } ++ ++ if (!buf) ++ return; ++ ++ size = KEXEC_COMMAND_LINE_SIZE; ++ size = min(size, bufsz); ++ if (size < bufsz) ++ pr_warn("kexec command line truncated to %zd bytes\n", size); ++ ++ /* Copy to kernel space */ ++ if (copy_from_user(kexec_argv_buf, buf, size)) ++ pr_warn("kexec command line copy to kernel space failed\n"); ++ ++ kexec_argv_buf[size - 1] = 0; ++} ++ ++static void machine_kexec_parse_argv(struct kimage *image) ++{ ++ char *reboot_code_buffer; ++ int reloc_delta; ++ char *ptr; ++ int argc; ++ int i; ++ ++ ptr = kexec_argv_buf; ++ argc = 0; ++ ++ /* ++ * convert command line string to array of parameters ++ * (as bootloader does). ++ */ ++ while (ptr && *ptr && (KEXEC_MAX_ARGC > argc)) { ++ if (*ptr == ' ') { ++ *ptr++ = '\0'; ++ continue; ++ } ++ ++ kexec_argv[argc++] = ptr; ++ ptr = strchr(ptr, ' '); ++ } ++ ++ if (!argc) ++ return; ++ ++ kexec_args[0] = argc; ++ kexec_args[1] = (unsigned long)kexec_argv; ++ kexec_args[2] = 0; ++ kexec_args[3] = 0; ++ ++ reboot_code_buffer = page_address(image->control_code_page); ++ reloc_delta = reboot_code_buffer - (char *)kexec_relocate_new_kernel; ++ ++ kexec_args[1] += reloc_delta; ++ for (i = 0; i < argc; i++) ++ kexec_argv[i] += reloc_delta; ++} ++ + static void kexec_image_info(const struct kimage *kimage) + { + unsigned long i; +@@ -99,6 +191,18 @@ machine_kexec_prepare(struct kimage *kim + #endif + + kexec_image_info(kimage); ++ /* ++ * Whenever arguments passed from kexec-tools, Init the arguments as ++ * the original ones to try avoiding booting failure. ++ */ ++ ++ kexec_args[0] = fw_arg0; ++ kexec_args[1] = fw_arg1; ++ kexec_args[2] = fw_arg2; ++ kexec_args[3] = fw_arg3; ++ ++ machine_kexec_init_argv(kimage); ++ machine_kexec_parse_argv(kimage); + + if (_machine_kexec_prepare) + return _machine_kexec_prepare(kimage); +@@ -161,7 +265,7 @@ machine_crash_shutdown(struct pt_regs *r + void kexec_nonboot_cpu_jump(void) + { + local_flush_icache_range((unsigned long)relocated_kexec_smp_wait, +- reboot_code_buffer + relocate_new_kernel_size); ++ reboot_code_buffer + KEXEC_RELOCATE_NEW_KERNEL_SIZE); + + relocated_kexec_smp_wait(NULL); + } +@@ -199,7 +303,7 @@ void kexec_reboot(void) + * machine_kexec() CPU. + */ + local_flush_icache_range(reboot_code_buffer, +- reboot_code_buffer + relocate_new_kernel_size); ++ reboot_code_buffer + KEXEC_RELOCATE_NEW_KERNEL_SIZE); + + do_kexec = (void *)reboot_code_buffer; + do_kexec(); +@@ -212,10 +316,12 @@ machine_kexec(struct kimage *image) + unsigned long *ptr; + + reboot_code_buffer = +- (unsigned long)page_address(image->control_code_page); ++ (unsigned long)page_address(image->control_code_page); ++ pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer); + + kexec_start_address = + (unsigned long) phys_to_virt(image->start); ++ pr_info("kexec_start_address = %p\n", (void *)kexec_start_address); + + if (image->type == KEXEC_TYPE_DEFAULT) { + kexec_indirection_page = +@@ -223,9 +329,19 @@ machine_kexec(struct kimage *image) + } else { + kexec_indirection_page = (unsigned long)&image->head; + } ++ pr_info("kexec_indirection_page = %p\n", (void *)kexec_indirection_page); + +- memcpy((void*)reboot_code_buffer, relocate_new_kernel, +- relocate_new_kernel_size); ++ pr_info("Where is memcpy: %p\n", memcpy); ++ pr_info("kexec_relocate_new_kernel = %p, kexec_relocate_new_kernel_end = %p\n", ++ (void *)kexec_relocate_new_kernel, &kexec_relocate_new_kernel_end); ++ pr_info("Copy %lu bytes from %p to %p\n", KEXEC_RELOCATE_NEW_KERNEL_SIZE, ++ (void *)kexec_relocate_new_kernel, (void *)reboot_code_buffer); ++ memcpy((void*)reboot_code_buffer, kexec_relocate_new_kernel, ++ KEXEC_RELOCATE_NEW_KERNEL_SIZE); ++ ++ pr_info("Before _print_args().\n"); ++ machine_kexec_print_args(); ++ pr_info("Before eval loop.\n"); + + /* + * The generic kexec code builds a page list with physical +@@ -256,7 +372,7 @@ machine_kexec(struct kimage *image) + #ifdef CONFIG_SMP + /* All secondary cpus now may jump to kexec_wait cycle */ + relocated_kexec_smp_wait = reboot_code_buffer + +- (void *)(kexec_smp_wait - relocate_new_kernel); ++ (void *)(kexec_smp_wait - kexec_relocate_new_kernel); + smp_wmb(); + atomic_set(&kexec_ready_to_reboot, 1); + #endif +--- /dev/null ++++ b/arch/mips/kernel/machine_kexec.h +@@ -0,0 +1,20 @@ ++#ifndef _MACHINE_KEXEC_H ++#define _MACHINE_KEXEC_H ++ ++#ifndef __ASSEMBLY__ ++extern const unsigned char kexec_relocate_new_kernel[]; ++extern unsigned long kexec_relocate_new_kernel_end; ++extern unsigned long kexec_start_address; ++extern unsigned long kexec_indirection_page; ++ ++extern char kexec_argv_buf[]; ++extern char *kexec_argv[]; ++ ++#define KEXEC_RELOCATE_NEW_KERNEL_SIZE ((unsigned long)&kexec_relocate_new_kernel_end - (unsigned long)kexec_relocate_new_kernel) ++#endif /* !__ASSEMBLY__ */ ++ ++#define KEXEC_COMMAND_LINE_SIZE 256 ++#define KEXEC_ARGV_SIZE (KEXEC_COMMAND_LINE_SIZE / 16) ++#define KEXEC_MAX_ARGC (KEXEC_ARGV_SIZE / sizeof(long)) ++ ++#endif +--- a/arch/mips/kernel/relocate_kernel.S ++++ b/arch/mips/kernel/relocate_kernel.S +@@ -10,8 +10,9 @@ + #include + #include + #include ++#include "machine_kexec.h" + +-LEAF(relocate_new_kernel) ++LEAF(kexec_relocate_new_kernel) + PTR_L a0, arg0 + PTR_L a1, arg1 + PTR_L a2, arg2 +@@ -96,7 +97,7 @@ done: + #endif + /* jump to kexec_start_address */ + j s1 +- END(relocate_new_kernel) ++ END(kexec_relocate_new_kernel) + + #ifdef CONFIG_SMP + /* +@@ -182,9 +183,15 @@ kexec_indirection_page: + PTR 0 + .size kexec_indirection_page, PTRSIZE + +-relocate_new_kernel_end: ++kexec_argv_buf: ++ EXPORT(kexec_argv_buf) ++ .skip KEXEC_COMMAND_LINE_SIZE ++ .size kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE ++ ++kexec_argv: ++ EXPORT(kexec_argv) ++ .skip KEXEC_ARGV_SIZE ++ .size kexec_argv, KEXEC_ARGV_SIZE + +-relocate_new_kernel_size: +- EXPORT(relocate_new_kernel_size) +- PTR relocate_new_kernel_end - relocate_new_kernel +- .size relocate_new_kernel_size, PTRSIZE ++kexec_relocate_new_kernel_end: ++ EXPORT(kexec_relocate_new_kernel_end) diff --git a/target/linux/generic/pending-5.15/332-arc-add-OWRTDTB-section.patch b/target/linux/generic/pending-5.15/332-arc-add-OWRTDTB-section.patch new file mode 100644 index 0000000000..30158cf399 --- /dev/null +++ b/target/linux/generic/pending-5.15/332-arc-add-OWRTDTB-section.patch @@ -0,0 +1,84 @@ +From bb0c3b0175240bf152fd7c644821a0cf9f77c37c Mon Sep 17 00:00:00 2001 +From: Evgeniy Didin +Date: Fri, 15 Mar 2019 18:53:38 +0300 +Subject: [PATCH] arc add OWRTDTB section + +This change allows OpenWRT to patch resulting kernel binary with +external .dtb. + +That allows us to re-use exactky the same vmlinux on different boards +given its ARC core configurations match (at least cache line sizes etc). + +""patch-dtb" searches for ASCII "OWRTDTB:" strign and copies external +.dtb right after it, keeping the string in place. + +Signed-off-by: Eugeniy Paltsev +Signed-off-by: Alexey Brodkin +Signed-off-by: Evgeniy Didin +--- + arch/arc/kernel/head.S | 10 ++++++++++ + arch/arc/kernel/setup.c | 4 +++- + arch/arc/kernel/vmlinux.lds.S | 13 +++++++++++++ + 3 files changed, 26 insertions(+), 1 deletion(-) + +--- a/arch/arc/kernel/head.S ++++ b/arch/arc/kernel/head.S +@@ -88,6 +88,16 @@ + DSP_EARLY_INIT + .endm + ++ ; Here "patch-dtb" will embed external .dtb ++ ; Note "patch-dtb" searches for ASCII "OWRTDTB:" string ++ ; and pastes .dtb right after it, hense the string precedes ++ ; __image_dtb symbol. ++ .section .owrt, "aw",@progbits ++ .ascii "OWRTDTB:" ++ENTRY(__image_dtb) ++ .fill 0x4000 ++END(__image_dtb) ++ + .section .init.text, "ax",@progbits + + ;---------------------------------------------------------------- +--- a/arch/arc/kernel/setup.c ++++ b/arch/arc/kernel/setup.c +@@ -495,6 +495,8 @@ static inline bool uboot_arg_invalid(uns + /* We always pass 0 as magic from U-boot */ + #define UBOOT_MAGIC_VALUE 0 + ++extern struct boot_param_header __image_dtb; ++ + void __init handle_uboot_args(void) + { + bool use_embedded_dtb = true; +@@ -533,7 +535,7 @@ void __init handle_uboot_args(void) + ignore_uboot_args: + + if (use_embedded_dtb) { +- machine_desc = setup_machine_fdt(__dtb_start); ++ machine_desc = setup_machine_fdt(&__image_dtb); + if (!machine_desc) + panic("Embedded DT invalid\n"); + } +--- a/arch/arc/kernel/vmlinux.lds.S ++++ b/arch/arc/kernel/vmlinux.lds.S +@@ -27,6 +27,19 @@ SECTIONS + + . = CONFIG_LINUX_LINK_BASE; + ++ /* ++ * In OpenWRT we want to patch built binary embedding .dtb of choice. ++ * This is implemented with "patch-dtb" utility which searches for ++ * "OWRTDTB:" string in first 16k of image and if it is found ++ * copies .dtb right after mentioned string. ++ * ++ * Note: "OWRTDTB:" won't be overwritten with .dtb, .dtb will follow it. ++ */ ++ .owrt : { ++ *(.owrt) ++ . = ALIGN(PAGE_SIZE); ++ } ++ + _int_vec_base_lds = .; + .vector : { + *(.vector) diff --git a/target/linux/generic/pending-5.15/333-arc-enable-unaligned-access-in-kernel-mode.patch b/target/linux/generic/pending-5.15/333-arc-enable-unaligned-access-in-kernel-mode.patch new file mode 100644 index 0000000000..1848a84cc4 --- /dev/null +++ b/target/linux/generic/pending-5.15/333-arc-enable-unaligned-access-in-kernel-mode.patch @@ -0,0 +1,24 @@ +From: Alexey Brodkin +Subject: arc: enable unaligned access in kernel mode + +This enables misaligned access handling even in kernel mode. +Some wireless drivers (ath9k-htc and mt7601u) use misaligned accesses +here and there and to cope with that without fixing stuff in the drivers +we're just gracefully handling it on ARC. + +Signed-off-by: Alexey Brodkin +--- + arch/arc/kernel/unaligned.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arc/kernel/unaligned.c ++++ b/arch/arc/kernel/unaligned.c +@@ -202,7 +202,7 @@ int misaligned_fixup(unsigned long addre + char buf[TASK_COMM_LEN]; + + /* handle user mode only and only if enabled by sysadmin */ +- if (!user_mode(regs) || !unaligned_enabled) ++ if (!unaligned_enabled) + return 1; + + if (no_unaligned_warning) { diff --git a/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch new file mode 100644 index 0000000000..6792a66f8a --- /dev/null +++ b/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch @@ -0,0 +1,25 @@ +From 66770a004afe10df11d3902e16eaa0c2c39436bb Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Fri, 24 May 2019 17:56:19 +0200 +Subject: [PATCH] powerpc: Enable kernel XZ compression option on PPC_85xx + +Enable kernel XZ compression option on PPC_85xx. Tested with +simpleImage on TP-Link TL-WDR4900 (Freescale P1014 processor). + +Suggested-by: Christian Lamparter +Signed-off-by: Pawel Dembicki +--- + arch/powerpc/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -214,7 +214,7 @@ config PPC + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE + select HAVE_KERNEL_LZO if DEFAULT_UIMAGE +- select HAVE_KERNEL_XZ if PPC_BOOK3S || 44x ++ select HAVE_KERNEL_XZ if PPC_BOOK3S || 44x || PPC_85xx + select HAVE_KPROBES + select HAVE_KPROBES_ON_FTRACE + select HAVE_KRETPROBES diff --git a/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch new file mode 100644 index 0000000000..6f816a6ad3 --- /dev/null +++ b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch @@ -0,0 +1,313 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -12,6 +12,25 @@ menuconfig MTD + + if MTD + ++menu "OpenWrt specific MTD options" ++ ++config MTD_ROOTFS_ROOT_DEV ++ bool "Automatically set 'rootfs' partition to be root filesystem" ++ default y ++ ++config MTD_SPLIT_FIRMWARE ++ bool "Automatically split firmware partition for kernel+rootfs" ++ default y ++ ++config MTD_SPLIT_FIRMWARE_NAME ++ string "Firmware partition name" ++ depends on MTD_SPLIT_FIRMWARE ++ default "firmware" ++ ++source "drivers/mtd/mtdsplit/Kconfig" ++ ++endmenu ++ + config MTD_TESTS + tristate "MTD tests support (DANGEROUS)" + depends on m +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -15,10 +15,12 @@ + #include + #include + #include ++#include + #include + #include + + #include "mtdcore.h" ++#include "mtdsplit/mtdsplit.h" + + /* + * MTD methods which simply translate the effective address and pass through +@@ -236,6 +238,146 @@ static int mtd_add_partition_attrs(struc + return ret; + } + ++static DEFINE_SPINLOCK(part_parser_lock); ++static LIST_HEAD(part_parsers); ++ ++static struct mtd_part_parser *mtd_part_parser_get(const char *name) ++{ ++ struct mtd_part_parser *p, *ret = NULL; ++ ++ spin_lock(&part_parser_lock); ++ ++ list_for_each_entry(p, &part_parsers, list) ++ if (!strcmp(p->name, name) && try_module_get(p->owner)) { ++ ret = p; ++ break; ++ } ++ ++ spin_unlock(&part_parser_lock); ++ ++ return ret; ++} ++ ++static inline void mtd_part_parser_put(const struct mtd_part_parser *p) ++{ ++ module_put(p->owner); ++} ++ ++static struct mtd_part_parser * ++get_partition_parser_by_type(enum mtd_parser_type type, ++ struct mtd_part_parser *start) ++{ ++ struct mtd_part_parser *p, *ret = NULL; ++ ++ spin_lock(&part_parser_lock); ++ ++ p = list_prepare_entry(start, &part_parsers, list); ++ if (start) ++ mtd_part_parser_put(start); ++ ++ list_for_each_entry_continue(p, &part_parsers, list) { ++ if (p->type == type && try_module_get(p->owner)) { ++ ret = p; ++ break; ++ } ++ } ++ ++ spin_unlock(&part_parser_lock); ++ ++ return ret; ++} ++ ++static int parse_mtd_partitions_by_type(struct mtd_info *master, ++ enum mtd_parser_type type, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct mtd_part_parser *prev = NULL; ++ int ret = 0; ++ ++ while (1) { ++ struct mtd_part_parser *parser; ++ ++ parser = get_partition_parser_by_type(type, prev); ++ if (!parser) ++ break; ++ ++ ret = (*parser->parse_fn)(master, pparts, data); ++ ++ if (ret > 0) { ++ mtd_part_parser_put(parser); ++ printk(KERN_NOTICE ++ "%d %s partitions found on MTD device %s\n", ++ ret, parser->name, master->name); ++ break; ++ } ++ ++ prev = parser; ++ } ++ ++ return ret; ++} ++ ++static int ++run_parsers_by_type(struct mtd_info *child, enum mtd_parser_type type) ++{ ++ struct mtd_partition *parts; ++ int nr_parts; ++ int i; ++ ++ nr_parts = parse_mtd_partitions_by_type(child, type, (const struct mtd_partition **)&parts, ++ NULL); ++ if (nr_parts <= 0) ++ return nr_parts; ++ ++ if (WARN_ON(!parts)) ++ return 0; ++ ++ for (i = 0; i < nr_parts; i++) { ++ /* adjust partition offsets */ ++ parts[i].offset += child->part.offset; ++ ++ mtd_add_partition(child->parent, ++ parts[i].name, ++ parts[i].offset, ++ parts[i].size); ++ } ++ ++ kfree(parts); ++ ++ return nr_parts; ++} ++ ++#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME ++#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME ++#else ++#define SPLIT_FIRMWARE_NAME "unused" ++#endif ++ ++static void split_firmware(struct mtd_info *master, struct mtd_info *part) ++{ ++ run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); ++} ++ ++static void mtd_partition_split(struct mtd_info *master, struct mtd_info *part) ++{ ++ static int rootfs_found = 0; ++ ++ if (rootfs_found) ++ return; ++ ++ if (!strcmp(part->name, "rootfs")) { ++ run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); ++ ++ rootfs_found = 1; ++ } ++ ++ if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) && ++ !strcmp(part->name, SPLIT_FIRMWARE_NAME) && ++ !of_find_property(mtd_get_of_node(part), "compatible", NULL)) ++ split_firmware(master, part); ++} ++ + int mtd_add_partition(struct mtd_info *parent, const char *name, + long long offset, long long length) + { +@@ -274,6 +416,7 @@ int mtd_add_partition(struct mtd_info *p + if (ret) + goto err_remove_part; + ++ mtd_partition_split(parent, child); + mtd_add_partition_attrs(child); + + return 0; +@@ -422,6 +565,7 @@ int add_mtd_partitions(struct mtd_info * + goto err_del_partitions; + } + ++ mtd_partition_split(master, child); + mtd_add_partition_attrs(child); + + /* Look for subpartitions */ +@@ -438,31 +582,6 @@ err_del_partitions: + return ret; + } + +-static DEFINE_SPINLOCK(part_parser_lock); +-static LIST_HEAD(part_parsers); +- +-static struct mtd_part_parser *mtd_part_parser_get(const char *name) +-{ +- struct mtd_part_parser *p, *ret = NULL; +- +- spin_lock(&part_parser_lock); +- +- list_for_each_entry(p, &part_parsers, list) +- if (!strcmp(p->name, name) && try_module_get(p->owner)) { +- ret = p; +- break; +- } +- +- spin_unlock(&part_parser_lock); +- +- return ret; +-} +- +-static inline void mtd_part_parser_put(const struct mtd_part_parser *p) +-{ +- module_put(p->owner); +-} +- + /* + * Many partition parsers just expected the core to kfree() all their data in + * one chunk. Do that by default. +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -75,6 +75,12 @@ struct mtd_part_parser_data { + * Functions dealing with the various ways of partitioning the space + */ + ++enum mtd_parser_type { ++ MTD_PARSER_TYPE_DEVICE = 0, ++ MTD_PARSER_TYPE_ROOTFS, ++ MTD_PARSER_TYPE_FIRMWARE, ++}; ++ + struct mtd_part_parser { + struct list_head list; + struct module *owner; +@@ -83,6 +89,7 @@ struct mtd_part_parser { + int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, + struct mtd_part_parser_data *); + void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); ++ enum mtd_parser_type type; + }; + + /* Container for passing around a set of parsed partitions */ +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -9,6 +9,8 @@ mtd-y := mtdcore.o mtdsuper.o mtdconc + + obj-y += parsers/ + ++obj-$(CONFIG_MTD_SPLIT) += mtdsplit/ ++ + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o + obj-$(CONFIG_MTD_BLOCK) += mtdblock.o +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -608,6 +608,24 @@ static inline void mtd_align_erase_req(s + req->len += mtd->erasesize - mod; + } + ++static inline uint64_t mtd_roundup_to_eb(uint64_t sz, struct mtd_info *mtd) ++{ ++ if (mtd_mod_by_eb(sz, mtd) == 0) ++ return sz; ++ ++ /* Round up to next erase block */ ++ return (mtd_div_by_eb(sz, mtd) + 1) * mtd->erasesize; ++} ++ ++static inline uint64_t mtd_rounddown_to_eb(uint64_t sz, struct mtd_info *mtd) ++{ ++ if (mtd_mod_by_eb(sz, mtd) == 0) ++ return sz; ++ ++ /* Round down to the start of the current erase block */ ++ return (mtd_div_by_eb(sz, mtd)) * mtd->erasesize; ++} ++ + static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) + { + if (mtd->writesize_shift) +@@ -680,6 +698,13 @@ extern void __put_mtd_device(struct mtd_ + extern struct mtd_info *get_mtd_device_nm(const char *name); + extern void put_mtd_device(struct mtd_info *mtd); + ++static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) ++{ ++ if (!mtd_is_partition(mtd)) ++ return 0; ++ ++ return mtd->part.offset; ++} + + struct mtd_notifier { + void (*add)(struct mtd_info *mtd); diff --git a/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch b/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch new file mode 100644 index 0000000000..eaf96e9534 --- /dev/null +++ b/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch @@ -0,0 +1,389 @@ +From patchwork Tue Jun 8 04:07:19 2021 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: John Thomson +X-Patchwork-Id: 1489105 +X-Patchwork-Delegate: tudor.ambarus@gmail.com +Return-Path: + +X-Original-To: incoming@patchwork.ozlabs.org +Delivered-To: patchwork-incoming@bilbo.ozlabs.org +Authentication-Results: ozlabs.org; + spf=none (no SPF record) smtp.mailfrom=lists.infradead.org + (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; + envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; + receiver=) +Authentication-Results: ozlabs.org; + dkim=pass (2048-bit key; + secure) header.d=lists.infradead.org header.i=@lists.infradead.org + header.a=rsa-sha256 header.s=bombadil.20210309 header.b=EMabhVoR; + dkim=fail reason="signature verification failed" (2048-bit key; + unprotected) header.d=fastmail.com.au header.i=@fastmail.com.au + header.a=rsa-sha256 header.s=fm3 header.b=dLzuZ6dB; + dkim=fail reason="signature verification failed" (2048-bit key; + unprotected) header.d=messagingengine.com header.i=@messagingengine.com + header.a=rsa-sha256 header.s=fm3 header.b=nSRGsW+C; + dkim-atps=neutral +Received: from bombadil.infradead.org (bombadil.infradead.org + [IPv6:2607:7c80:54:e::133]) + (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest + SHA256) + (No client certificate requested) + by ozlabs.org (Postfix) with ESMTPS id 4FzcFN1j1nz9sW8 + for ; Tue, 8 Jun 2021 14:09:28 +1000 (AEST) +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=lists.infradead.org; s=bombadil.20210309; h=Sender: + Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: + List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc + :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: + Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: + List-Owner; bh=6mUWQd71FwsINycGYY1qOhKz+ecWJVNtwDkTebG3XkA=; b=EMabhVoRE3ad89 + o3L2AgyKrs+blSofUC3hoSsQe7gi3m4si8S9HW8Z+8SsS5TufUsvGwDl80qSYGlQOytQF+1yRUWvE + 6FJ/+bqv+TwjqZFibgJ6+9OVsQN9dZ/no1R0bBXIpmrf8ORUmv58QK4ZQquaFKbyXKpFeWOC2MSv4 + H2MAhyhTU8a3gtooH6G8+KvsJEfVgh6C+aDbwxyh2UY3chHKuw1kvL6AktbfUE2xl4zxi3x3kc70B + Wi3LiJBFokxVdgnROXxTU5tI0XboWYkQV64gLuQNV4XKClcuhVpzloDK8Iok6NTd7b32a7TdEFlCS + lGKsEKmxtUlW2FpfoduA==; +Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) + id 1lqT1r-006OAW-DX; Tue, 08 Jun 2021 04:07:51 +0000 +Received: from new1-smtp.messagingengine.com ([66.111.4.221]) + by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) + id 1lqT1l-006O9b-Fq + for linux-mtd@lists.infradead.org; Tue, 08 Jun 2021 04:07:50 +0000 +Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) + by mailnew.nyi.internal (Postfix) with ESMTP id 4456B580622; + Tue, 8 Jun 2021 00:07:42 -0400 (EDT) +Received: from mailfrontend2 ([10.202.2.163]) + by compute2.internal (MEProxy); Tue, 08 Jun 2021 00:07:42 -0400 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fastmail.com.au; + h=from:to:cc:subject:date:message-id:mime-version + :content-transfer-encoding; s=fm3; bh=ZXRH+YluM1mHCS1EWUiCY/Sg8O + LccfHe1oW5iAay6y8=; b=dLzuZ6dBYf7ZA8tWLOBFZYLi7ERsGe/4vnMXG+ovvb + dNBO0+SaFGwoqYSFrfq/TeyHfKyvxrA7+LCdopIuT4abpLHxtRwtRiafQcDYCPat + qJIqOZO+wCZC5S9Jc1OP7+t1FviGpgevqIMotci37P+RWc5u3AweMzFljZk90E8C + uorV6rXagD+OssJQzllRnAIK88+rOAC9ZyXv2gWxy4d1HSCwSWgzx2vnV9CNp918 + YC/3tiHas9krbrPIaAsdBROr7Bvoe/ShRRzruKRuvZVgg5NN90vX+/5ZjI8u04GM + p2bWCbC62CP6wlcgDaz+c/Sgr5ITd2GPENJsHfqmLRBA== +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= + messagingengine.com; h=cc:content-transfer-encoding:date:from + :message-id:mime-version:subject:to:x-me-proxy:x-me-proxy + :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=ZXRH+YluM1mHCS1EW + UiCY/Sg8OLccfHe1oW5iAay6y8=; b=nSRGsW+CQ2Zx1RVpIUu8W/VD/k5P+32BW + 5k2ltd+UhI3dfldBPzHrYiOP/IJqGkNW+V+rHASacW/vFygnaZoxNjRYKnOsu+26 + wb2yK3jpl6lsNTg3N1Z4XJrYY2lf9H29DMFbhC67l0PTc050rcZk4XsKTLAlv14Q + VA4WREYSaX/4IN4O+ES4TMq0a/3gKZh6nvbbJXbsXfK0WlSHTGZtZmW3fyrqvbXa + t+R7L8vvqWvwls0pV+Sn8LeQqb7+A69w0UOnuznjkcA3sCc2YehcHbxcUEnMH+9N + bxOjmIDeg9/4X/829tUWUJiLhE5SFmQZ1P6oFtmbWoLrDz0ZJIVBw== +X-ME-Sender: + +X-ME-Received: + +X-ME-Proxy-Cause: + gggruggvucftvghtrhhoucdtuddrgeduledrfedtkedgjeduucetufdoteggodetrfdotf + fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen + uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne + cujfgurhephffvufffkffoggfgsedtkeertdertddtnecuhfhrohhmpeflohhhnhcuvfhh + ohhmshhonhcuoehgihhtsehjohhhnhhthhhomhhsohhnrdhfrghsthhmrghilhdrtghomh + drrghuqeenucggtffrrghtthgvrhhnpefffeeihfdukedtuedufeetieeuudfhhefhkefh + tefgtdeuffekffelleetveduieenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmh + epmhgrihhlfhhrohhmpehgihhtsehjohhhnhhthhhomhhsohhnrdhfrghsthhmrghilhdr + tghomhdrrghu +X-ME-Proxy: + + + +Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, + 8 Jun 2021 00:07:35 -0400 (EDT) +From: John Thomson +To: Miquel Raynal , + Richard Weinberger , Vignesh Raghavendra , + Tudor Ambarus , + Michael Walle , Pratyush Yadav , + linux-mtd@lists.infradead.org +Cc: linux-kernel@vger.kernel.org, + John Thomson , + kernel test robot , Dan Carpenter +Subject: [PATCH] mtd: spi-nor: write support for minor aligned partitions +Date: Tue, 8 Jun 2021 14:07:19 +1000 +Message-Id: <20210608040719.14431-1-git@johnthomson.fastmail.com.au> +X-Mailer: git-send-email 2.31.1 +MIME-Version: 1.0 +X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 +X-CRM114-CacheID: sfid-20210607_210745_712053_67A7D864 +X-CRM114-Status: GOOD ( 26.99 ) +X-Spam-Score: -0.8 (/) +X-Spam-Report: Spam detection software, + running on the system "bombadil.infradead.org", + has NOT identified this incoming email as spam. The original + message has been attached to this so you can view it or label + similar future email. If you have any questions, see + the administrator of that system for details. + Content preview: Do not prevent writing to mtd partitions where a partition + boundary sits on a minor erasesize boundary. This addresses a FIXME that + has been present since the start of the linux git history: /* Doesn' [...] + Content analysis details: (-0.8 points, 5.0 required) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, + low trust [66.111.4.221 listed in list.dnswl.org] + -0.0 SPF_PASS SPF: sender matches SPF record + -0.0 SPF_HELO_PASS SPF: HELO matches SPF record + 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) + [66.111.4.221 listed in wl.mailspike.net] + -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature + 0.1 DKIM_SIGNED Message has a DKIM or DK signature, + not necessarily + valid + -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from + envelope-from domain + 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders +X-BeenThere: linux-mtd@lists.infradead.org +X-Mailman-Version: 2.1.34 +Precedence: list +List-Id: Linux MTD discussion mailing list +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Sender: "linux-mtd" +Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org + +Do not prevent writing to mtd partitions where a partition boundary sits +on a minor erasesize boundary. +This addresses a FIXME that has been present since the start of the +linux git history: +/* Doesn't start on a boundary of major erase size */ +/* FIXME: Let it be writable if it is on a boundary of + * _minor_ erase size though */ + +Allow a uniform erase region spi-nor device to be configured +to use the non-uniform erase regions code path for an erase with: +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y + +On supporting hardware (SECT_4K: majority of current SPI-NOR device) +provide the facility for an erase to use the least number +of SPI-NOR operations, as well as access to 4K erase without +requiring CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + +Introduce erasesize_minor to the mtd struct, +the smallest erasesize supported by the device + +On existing devices, this is useful where write support is wanted +for data on a 4K partition, such as some u-boot-env partitions, +or RouterBoot soft_config, while still netting the performance +benefits of using 64K sectors + +Performance: +time mtd erase firmware +OpenWrt 5.10 ramips MT7621 w25q128jv 0xfc0000 partition length + +Without this patch +MTD_SPI_NOR_USE_4K_SECTORS=y |n +real 2m 11.66s |0m 50.86s +user 0m 0.00s |0m 0.00s +sys 1m 56.20s |0m 50.80s + +With this patch +MTD_SPI_NOR_USE_VARIABLE_ERASE=n|y |4K_SECTORS=y +real 0m 51.68s |0m 50.85s |2m 12.89s +user 0m 0.00s |0m 0.00s |0m 0.01s +sys 0m 46.94s |0m 50.38s |2m 12.46s + +Signed-off-by: John Thomson +--- +Have not tested on variable erase regions device. + +checkpatch does not like the printk(KERN_WARNING +these should be changed separately beforehand? + +Changes RFC -> v1: +Fix uninitialized variable smatch warning +Reported-by: kernel test robot +Reported-by: Dan Carpenter +--- + drivers/mtd/mtdpart.c | 52 ++++++++++++++++++++++++++++--------- + drivers/mtd/spi-nor/Kconfig | 10 +++++++ + drivers/mtd/spi-nor/core.c | 10 +++++-- + include/linux/mtd/mtd.h | 2 ++ + 4 files changed, 60 insertions(+), 14 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -40,10 +40,11 @@ static struct mtd_info *allocate_partiti + struct mtd_info *master = mtd_get_master(parent); + int wr_alignment = (parent->flags & MTD_NO_ERASE) ? + master->writesize : master->erasesize; ++ int wr_alignment_minor = 0; + u64 parent_size = mtd_is_partition(parent) ? + parent->part.size : parent->size; + struct mtd_info *child; +- u32 remainder; ++ u32 remainder, remainder_minor; + char *name; + u64 tmp; + +@@ -145,6 +146,7 @@ static struct mtd_info *allocate_partiti + int i, max = parent->numeraseregions; + u64 end = child->part.offset + child->part.size; + struct mtd_erase_region_info *regions = parent->eraseregions; ++ uint32_t erasesize_minor = child->erasesize; + + /* Find the first erase regions which is part of this + * partition. */ +@@ -155,15 +157,24 @@ static struct mtd_info *allocate_partiti + if (i > 0) + i--; + +- /* Pick biggest erasesize */ + for (; i < max && regions[i].offset < end; i++) { ++ /* Pick biggest erasesize */ + if (child->erasesize < regions[i].erasesize) + child->erasesize = regions[i].erasesize; ++ /* Pick smallest non-zero erasesize */ ++ if ((erasesize_minor > regions[i].erasesize) && (regions[i].erasesize > 0)) ++ erasesize_minor = regions[i].erasesize; + } ++ ++ if (erasesize_minor < child->erasesize) ++ child->erasesize_minor = erasesize_minor; ++ + BUG_ON(child->erasesize == 0); + } else { + /* Single erase size */ + child->erasesize = master->erasesize; ++ if (master->erasesize_minor) ++ child->erasesize_minor = master->erasesize_minor; + } + + /* +@@ -171,26 +182,43 @@ static struct mtd_info *allocate_partiti + * exposes several regions with different erasesize. Adjust + * wr_alignment accordingly. + */ +- if (!(child->flags & MTD_NO_ERASE)) ++ if (!(child->flags & MTD_NO_ERASE)) { + wr_alignment = child->erasesize; ++ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE) && child->erasesize_minor) ++ wr_alignment_minor = child->erasesize_minor; ++ } + + tmp = mtd_get_master_ofs(child, 0); + remainder = do_div(tmp, wr_alignment); + if ((child->flags & MTD_WRITEABLE) && remainder) { +- /* Doesn't start on a boundary of major erase size */ +- /* FIXME: Let it be writable if it is on a boundary of +- * _minor_ erase size though */ +- child->flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", +- part->name); ++ if (wr_alignment_minor) { ++ tmp = mtd_get_master_ofs(child, 0); ++ remainder_minor = do_div(tmp, wr_alignment_minor); ++ if (remainder_minor == 0) ++ child->erasesize = child->erasesize_minor; ++ } ++ ++ if ((!wr_alignment_minor) || (wr_alignment_minor && remainder_minor != 0)) { ++ child->flags &= ~MTD_WRITEABLE; ++ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", ++ part->name); ++ } + } + + tmp = mtd_get_master_ofs(child, 0) + child->part.size; + remainder = do_div(tmp, wr_alignment); + if ((child->flags & MTD_WRITEABLE) && remainder) { +- child->flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", +- part->name); ++ if (wr_alignment_minor) { ++ tmp = mtd_get_master_ofs(child, 0) + child->part.size; ++ remainder_minor = do_div(tmp, wr_alignment_minor); ++ if (remainder_minor == 0) ++ child->erasesize = child->erasesize_minor; ++ } ++ if ((!wr_alignment_minor) || (wr_alignment_minor && remainder_minor != 0)) { ++ child->flags &= ~MTD_WRITEABLE; ++ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", ++ part->name); ++ } + } + + child->size = child->part.size; +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -10,6 +10,16 @@ menuconfig MTD_SPI_NOR + + if MTD_SPI_NOR + ++config MTD_SPI_NOR_USE_VARIABLE_ERASE ++ bool "Disable uniform_erase to allow use of all hardware supported erasesizes" ++ depends on !MTD_SPI_NOR_USE_4K_SECTORS ++ default n ++ help ++ Allow mixed use of all hardware supported erasesizes, ++ by forcing spi_nor to use the multiple eraseregions code path. ++ For example: A 68K erase will use one 64K erase, and one 4K erase ++ on supporting hardware. ++ + config MTD_SPI_NOR_USE_4K_SECTORS + bool "Use small 4096 B erase sectors" + default y +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1075,6 +1075,8 @@ static u8 spi_nor_convert_3to4_erase(u8 + + static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) + { ++ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE)) ++ return false; + return !!nor->params->erase_map.uniform_erase_type; + } + +@@ -2560,6 +2562,7 @@ static int spi_nor_select_erase(struct s + { + struct spi_nor_erase_map *map = &nor->params->erase_map; + const struct spi_nor_erase_type *erase = NULL; ++ const struct spi_nor_erase_type *erase_minor = NULL; + struct mtd_info *mtd = &nor->mtd; + u32 wanted_size = nor->info->sector_size; + int i; +@@ -2592,8 +2595,9 @@ static int spi_nor_select_erase(struct s + */ + for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { + if (map->erase_type[i].size) { +- erase = &map->erase_type[i]; +- break; ++ if (!erase) ++ erase = &map->erase_type[i]; ++ erase_minor = &map->erase_type[i]; + } + } + +@@ -2601,6 +2605,8 @@ static int spi_nor_select_erase(struct s + return -EINVAL; + + mtd->erasesize = erase->size; ++ if (erase_minor && erase_minor->size < erase->size) ++ mtd->erasesize_minor = erase_minor->size; + return 0; + } + +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -242,6 +242,8 @@ struct mtd_info { + * information below if they desire + */ + uint32_t erasesize; ++ /* "Minor" (smallest) erase size supported by the whole device */ ++ uint32_t erasesize_minor; + /* Minimal writable flash unit size. In case of NOR flash it is 1 (even + * though individual bits can be cleared), in case of NAND flash it is + * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR diff --git a/target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch b/target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch new file mode 100644 index 0000000000..353fa96748 --- /dev/null +++ b/target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch @@ -0,0 +1,76 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 6 May 2021 12:33:58 +0200 +Subject: [PATCH] mtd: parsers: ofpart: fix parsing subpartitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +ofpart was recently patched to not scan random partition nodes as +subpartitions. That change unfortunately broke scanning valid +subpartitions like: + +partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "fixed-partitions"; + label = "bootloader"; + reg = <0x0 0x100000>; + + partition@0 { + label = "config"; + reg = <0x80000 0x80000>; + }; + }; +}; + +Fix that regression by adding 1 more code path. We actually need 3 +conditional blocks to support 3 possible cases. This change also makes +code easier to understand & follow. + +Reported-by: David Bauer +Fixes: 2d751203aacf ("mtd: parsers: ofpart: limit parsing of deprecated DT syntax +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/parsers/ofpart_core.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -57,20 +57,22 @@ static int parse_fixed_partitions(struct + if (!mtd_node) + return 0; + +- ofpart_node = of_get_child_by_name(mtd_node, "partitions"); +- if (!ofpart_node && !master->parent) { +- /* +- * We might get here even when ofpart isn't used at all (e.g., +- * when using another parser), so don't be louder than +- * KERN_DEBUG +- */ +- pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", +- master->name, mtd_node); ++ if (!master->parent) { /* Master */ ++ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); ++ if (!ofpart_node) { ++ /* ++ * We might get here even when ofpart isn't used at all (e.g., ++ * when using another parser), so don't be louder than ++ * KERN_DEBUG ++ */ ++ pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", ++ master->name, mtd_node); ++ ofpart_node = mtd_node; ++ dedicated = false; ++ } ++ } else { /* Partition */ + ofpart_node = mtd_node; +- dedicated = false; + } +- if (!ofpart_node) +- return 0; + + of_id = of_match_node(parse_ofpart_match_table, ofpart_node); + if (dedicated && !of_id) { diff --git a/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch b/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch new file mode 100644 index 0000000000..7692f484ae --- /dev/null +++ b/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch @@ -0,0 +1,22 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] mtd: redboot: add of_match_table with DT binding +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows parsing RedBoot compatible partitions for properly described +flash device in DT. + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/mtd/parsers/redboot.c ++++ b/drivers/mtd/parsers/redboot.c +@@ -305,6 +305,7 @@ static int parse_redboot_partitions(stru + + static const struct of_device_id mtd_parser_redboot_of_match_table[] = { + { .compatible = "redboot-fis" }, ++ { .compatible = "ecoscentric,redboot-fis-partitions" }, + {}, + }; + MODULE_DEVICE_TABLE(of, mtd_parser_redboot_of_match_table); diff --git a/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch new file mode 100644 index 0000000000..a3cd4ecf1f --- /dev/null +++ b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +Subject: add patch for including unpartitioned space in the rootfs partition for redboot devices (if applicable) + +[john@phrozen.org: used by ixp and others] + +lede-commit: 394918851f84e4d00fa16eb900e7700e95091f00 +Signed-off-by: Felix Fietkau +--- + drivers/mtd/redboot.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/mtd/parsers/redboot.c ++++ b/drivers/mtd/parsers/redboot.c +@@ -279,14 +279,21 @@ static int parse_redboot_partitions(stru + #endif + names += strlen(names)+1; + +-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED + if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { +- i++; +- parts[i].offset = parts[i-1].size + parts[i-1].offset; +- parts[i].size = fl->next->img->flash_base - parts[i].offset; +- parts[i].name = nullname; +- } ++ if (!strcmp(parts[i].name, "rootfs")) { ++ parts[i].size = fl->next->img->flash_base; ++ parts[i].size &= ~(master->erasesize - 1); ++ parts[i].size -= parts[i].offset; ++#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED ++ nrparts--; ++ } else { ++ i++; ++ parts[i].offset = parts[i-1].size + parts[i-1].offset; ++ parts[i].size = fl->next->img->flash_base - parts[i].offset; ++ parts[i].name = nullname; + #endif ++ } ++ } + tmp_fl = fl; + fl = fl->next; + kfree(tmp_fl); diff --git a/target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch new file mode 100644 index 0000000000..0889c9a343 --- /dev/null +++ b/target/linux/generic/pending-5.15/430-mtd-add-myloader-partition-parser.patch @@ -0,0 +1,229 @@ +From: Florian Fainelli +Subject: Add myloader partition table parser + +[john@phozen.org: shoud be upstreamable] + +lede-commit: d8bf22859b51faa09d22c056fe221a45d2f7a3b8 +Signed-off-by: Florian Fainelli +[adjust for kernel 5.4, add myloader.c to patch] +Signed-off-by: Adrian Schmutzler + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -57,6 +57,22 @@ config MTD_CMDLINE_PARTS + + If unsure, say 'N'. + ++config MTD_MYLOADER_PARTS ++ tristate "MyLoader partition parsing" ++ depends on ADM5120 || ATH25 || ATH79 ++ help ++ MyLoader is a bootloader which allows the user to define partitions ++ in flash devices, by putting a table in the second erase block ++ on the device, similar to a partition table. This table gives the ++ offsets and lengths of the user defined partitions. ++ ++ If you need code which can detect and parse these tables, and ++ register MTD 'partitions' corresponding to each image detected, ++ enable this option. ++ ++ You will still need the parsing functions to be called by the driver ++ for your particular device. It won't happen automatically. ++ + config MTD_OF_PARTS + tristate "OpenFirmware (device tree) partitioning parser" + default y +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -3,6 +3,7 @@ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part. + obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o ++obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o + ofpart-y += ofpart_core.o + ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o +--- /dev/null ++++ b/drivers/mtd/parsers/myloader.c +@@ -0,0 +1,181 @@ ++/* ++ * Parse MyLoader-style flash partition tables and produce a Linux partition ++ * array to match. ++ * ++ * Copyright (C) 2007-2009 Gabor Juhos ++ * ++ * This file was based on drivers/mtd/redboot.c ++ * Author: Red Hat, Inc. - David Woodhouse ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BLOCK_LEN_MIN 0x10000 ++#define PART_NAME_LEN 32 ++ ++struct part_data { ++ struct mylo_partition_table tab; ++ char names[MYLO_MAX_PARTITIONS][PART_NAME_LEN]; ++}; ++ ++static int myloader_parse_partitions(struct mtd_info *master, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct part_data *buf; ++ struct mylo_partition_table *tab; ++ struct mylo_partition *part; ++ struct mtd_partition *mtd_parts; ++ struct mtd_partition *mtd_part; ++ int num_parts; ++ int ret, i; ++ size_t retlen; ++ char *names; ++ unsigned long offset; ++ unsigned long blocklen; ++ ++ buf = vmalloc(sizeof(*buf)); ++ if (!buf) { ++ return -ENOMEM; ++ goto out; ++ } ++ tab = &buf->tab; ++ ++ blocklen = master->erasesize; ++ if (blocklen < BLOCK_LEN_MIN) ++ blocklen = BLOCK_LEN_MIN; ++ ++ offset = blocklen; ++ ++ /* Find the partition table */ ++ for (i = 0; i < 4; i++, offset += blocklen) { ++ printk(KERN_DEBUG "%s: searching for MyLoader partition table" ++ " at offset 0x%lx\n", master->name, offset); ++ ++ ret = mtd_read(master, offset, sizeof(*buf), &retlen, ++ (void *)buf); ++ if (ret) ++ goto out_free_buf; ++ ++ if (retlen != sizeof(*buf)) { ++ ret = -EIO; ++ goto out_free_buf; ++ } ++ ++ /* Check for Partition Table magic number */ ++ if (tab->magic == le32_to_cpu(MYLO_MAGIC_PARTITIONS)) ++ break; ++ ++ } ++ ++ if (tab->magic != le32_to_cpu(MYLO_MAGIC_PARTITIONS)) { ++ printk(KERN_DEBUG "%s: no MyLoader partition table found\n", ++ master->name); ++ ret = 0; ++ goto out_free_buf; ++ } ++ ++ /* The MyLoader and the Partition Table is always present */ ++ num_parts = 2; ++ ++ /* Detect number of used partitions */ ++ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { ++ part = &tab->partitions[i]; ++ ++ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) ++ continue; ++ ++ num_parts++; ++ } ++ ++ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + ++ num_parts * PART_NAME_LEN), GFP_KERNEL); ++ ++ if (!mtd_parts) { ++ ret = -ENOMEM; ++ goto out_free_buf; ++ } ++ ++ mtd_part = mtd_parts; ++ names = (char *)&mtd_parts[num_parts]; ++ ++ strncpy(names, "myloader", PART_NAME_LEN); ++ mtd_part->name = names; ++ mtd_part->offset = 0; ++ mtd_part->size = offset; ++ mtd_part->mask_flags = MTD_WRITEABLE; ++ mtd_part++; ++ names += PART_NAME_LEN; ++ ++ strncpy(names, "partition_table", PART_NAME_LEN); ++ mtd_part->name = names; ++ mtd_part->offset = offset; ++ mtd_part->size = blocklen; ++ mtd_part->mask_flags = MTD_WRITEABLE; ++ mtd_part++; ++ names += PART_NAME_LEN; ++ ++ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { ++ part = &tab->partitions[i]; ++ ++ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) ++ continue; ++ ++ if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) ++ strncpy(names, buf->names[i], PART_NAME_LEN); ++ else ++ snprintf(names, PART_NAME_LEN, "partition%d", i); ++ ++ mtd_part->offset = le32_to_cpu(part->addr); ++ mtd_part->size = le32_to_cpu(part->size); ++ mtd_part->name = names; ++ mtd_part++; ++ names += PART_NAME_LEN; ++ } ++ ++ *pparts = mtd_parts; ++ ret = num_parts; ++ ++ out_free_buf: ++ vfree(buf); ++ out: ++ return ret; ++} ++ ++static struct mtd_part_parser myloader_mtd_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = myloader_parse_partitions, ++ .name = "MyLoader", ++}; ++ ++static int __init myloader_mtd_parser_init(void) ++{ ++ register_mtd_parser(&myloader_mtd_parser); ++ ++ return 0; ++} ++ ++static void __exit myloader_mtd_parser_exit(void) ++{ ++ deregister_mtd_parser(&myloader_mtd_parser); ++} ++ ++module_init(myloader_mtd_parser_init); ++module_exit(myloader_mtd_parser_exit); ++ ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/pending-5.15/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch b/target/linux/generic/pending-5.15/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch new file mode 100644 index 0000000000..bcea45d009 --- /dev/null +++ b/target/linux/generic/pending-5.15/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch @@ -0,0 +1,68 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/mtd/parsers/parser_trx.c ++++ b/drivers/mtd/parsers/parser_trx.c +@@ -25,6 +25,33 @@ struct trx_header { + uint32_t offset[3]; + } __packed; + ++/* ++ * Calculate real end offset (address) for a given amount of data. It checks ++ * all blocks skipping bad ones. ++ */ ++static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes) ++{ ++ size_t real_offset = 0; ++ ++ if (mtd_block_isbad(mtd, real_offset)) ++ pr_warn("Base offset shouldn't be at bad block"); ++ ++ while (bytes >= mtd->erasesize) { ++ bytes -= mtd->erasesize; ++ real_offset += mtd->erasesize; ++ while (mtd_block_isbad(mtd, real_offset)) { ++ real_offset += mtd->erasesize; ++ ++ if (real_offset >= mtd->size) ++ return real_offset - mtd->erasesize; ++ } ++ } ++ ++ real_offset += bytes; ++ ++ return real_offset; ++} ++ + static const char *parser_trx_data_part_name(struct mtd_info *master, + size_t offset) + { +@@ -86,21 +113,21 @@ static int parser_trx_parse(struct mtd_i + if (trx.offset[2]) { + part = &parts[curr_part++]; + part->name = "loader"; +- part->offset = trx.offset[i]; ++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); + i++; + } + + if (trx.offset[i]) { + part = &parts[curr_part++]; + part->name = "linux"; +- part->offset = trx.offset[i]; ++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); + i++; + } + + if (trx.offset[i]) { + part = &parts[curr_part++]; +- part->name = parser_trx_data_part_name(mtd, trx.offset[i]); +- part->offset = trx.offset[i]; ++ part->offset = parser_trx_real_offset(mtd, trx.offset[i]); ++ part->name = parser_trx_data_part_name(mtd, part->offset); + i++; + } + diff --git a/target/linux/generic/pending-5.15/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch b/target/linux/generic/pending-5.15/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch new file mode 100644 index 0000000000..852654d924 --- /dev/null +++ b/target/linux/generic/pending-5.15/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch @@ -0,0 +1,37 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: mtd: bcm47xxpart: detect T_Meter partition + +It can be found on many Netgear devices. It consists of many 0x30 blocks +starting with 4D 54. + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/bcm47xxpart.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/parsers/bcm47xxpart.c ++++ b/drivers/mtd/parsers/bcm47xxpart.c +@@ -35,6 +35,7 @@ + #define NVRAM_HEADER 0x48534C46 /* FLSH */ + #define POT_MAGIC1 0x54544f50 /* POTT */ + #define POT_MAGIC2 0x504f /* OP */ ++#define T_METER_MAGIC 0x4D540000 /* MT */ + #define ML_MAGIC1 0x39685a42 + #define ML_MAGIC2 0x26594131 + #define TRX_MAGIC 0x30524448 +@@ -178,6 +179,15 @@ static int bcm47xxpart_parse(struct mtd_ + MTD_WRITEABLE); + continue; + } ++ ++ /* T_Meter */ ++ if ((le32_to_cpu(buf[0x000 / 4]) & 0xFFFF0000) == T_METER_MAGIC && ++ (le32_to_cpu(buf[0x030 / 4]) & 0xFFFF0000) == T_METER_MAGIC && ++ (le32_to_cpu(buf[0x060 / 4]) & 0xFFFF0000) == T_METER_MAGIC) { ++ bcm47xxpart_add_part(&parts[curr_part++], "T_Meter", offset, ++ MTD_WRITEABLE); ++ continue; ++ } + + /* TRX */ + if (buf[0x000 / 4] == TRX_MAGIC) { diff --git a/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch new file mode 100644 index 0000000000..ab1e09a5f1 --- /dev/null +++ b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch @@ -0,0 +1,38 @@ +From 4437e01fb6bca63fccdba5d6c44888b0935885c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= +Date: Tue, 24 Mar 2020 11:45:07 +0100 +Subject: [PATCH] generic: routerboot partition build bits (5.4) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds routerbootpart kernel build bits + +Signed-off-by: Thibaut VARÈNE +--- + drivers/mtd/parsers/Kconfig | 9 +++++++++ + drivers/mtd/parsers/Makefile | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -195,3 +195,12 @@ config MTD_REDBOOT_PARTS_READONLY + 'FIS directory' images, enable this option. + + endif # MTD_REDBOOT_PARTS ++ ++config MTD_ROUTERBOOT_PARTS ++ tristate "RouterBoot flash partition parser" ++ depends on MTD && OF ++ help ++ MikroTik RouterBoot is implemented as a multi segment system on the ++ flash, some of which are fixed and some of which are located at ++ variable offsets. This parser handles both cases via properly ++ formatted DTS. +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -13,3 +13,4 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o + obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o + obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o ++obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o diff --git a/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch new file mode 100644 index 0000000000..9983971af5 --- /dev/null +++ b/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Subject: kernel: disable cfi cmdset 0002 erase suspend + +on some platforms, erase suspend leads to data corruption and lockups when write +ops collide with erase ops. this has been observed on the buffalo wzr-hp-g300nh. +rather than play whack-a-mole with a hard to reproduce issue on a variety of devices, +simply disable erase suspend, as it will usually not produce any useful gain on +the small filesystems used on embedded hardware. + +Signed-off-by: Felix Fietkau +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -913,7 +913,7 @@ static int get_chip(struct map_info *map + return 0; + + case FL_ERASING: +- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) || ++ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) || + !(mode == FL_READY || mode == FL_POINT || + (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) + goto sleep; diff --git a/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch new file mode 100644 index 0000000000..0bda2ed971 --- /dev/null +++ b/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch @@ -0,0 +1,17 @@ +From: George Kashperko +Subject: Issue map read after Write Buffer Load command to ensure chip is ready to receive data. + +Signed-off-by: George Kashperko +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 1 + + 1 file changed, 1 insertion(+) +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -2057,6 +2057,7 @@ static int __xipram do_write_buffer(stru + + /* Write Buffer Load */ + map_write(map, CMD(0x25), cmd_adr); ++ (void) map_read(map, cmd_adr); + + chip->state = FL_WRITING_TO_BUFFER; + diff --git a/target/linux/generic/pending-5.15/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-5.15/465-m25p80-mx-disable-software-protection.patch new file mode 100644 index 0000000000..f58d5452ab --- /dev/null +++ b/target/linux/generic/pending-5.15/465-m25p80-mx-disable-software-protection.patch @@ -0,0 +1,18 @@ +From: Felix Fietkau +Subject: Disable software protection bits for Macronix flashes. + +Signed-off-by: Felix Fietkau +--- + drivers/mtd/spi-nor/spi-nor.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/macronix.c ++++ b/drivers/mtd/spi-nor/macronix.c +@@ -93,6 +93,7 @@ static void macronix_default_init(struct + { + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; + nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; ++ nor->flags |= SNOR_F_HAS_LOCK; + } + + static const struct spi_nor_fixups macronix_fixups = { diff --git a/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch new file mode 100644 index 0000000000..2748192dd2 --- /dev/null +++ b/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch @@ -0,0 +1,71 @@ +From: Felix Fietkau +Date: Sat, 4 Nov 2017 07:40:23 +0100 +Subject: [PATCH] mtd: spi-nor: support limiting 4K sectors support based on + flash size + +Some devices need 4K sectors to be able to deal with small flash chips. +For instance, w25x05 is 64 KiB in size, and without 4K sectors, the +entire chip is just one erase block. +On bigger flash chip sizes, using 4K sectors can significantly slow down +many operations, including using a writable filesystem. There are several +platforms where it makes sense to use a single kernel on both kinds of +devices. + +To support this properly, allow configuring an upper flash chip size +limit for 4K sectors support. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -34,6 +34,17 @@ config MTD_SPI_NOR_USE_4K_SECTORS + Please note that some tools/drivers/filesystems may not work with + 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). + ++config MTD_SPI_NOR_USE_4K_SECTORS_LIMIT ++ int "Maximum flash chip size to use 4K sectors on (in KiB)" ++ depends on MTD_SPI_NOR_USE_4K_SECTORS ++ default "4096" ++ help ++ There are many flash chips that support 4K sectors, but are so large ++ that using them significantly slows down writing large amounts of ++ data or using a writable filesystem. ++ Any flash chip larger than the size specified in this option will ++ not use 4K sectors. ++ + source "drivers/mtd/spi-nor/controllers/Kconfig" + + endif # MTD_SPI_NOR +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -2792,6 +2792,21 @@ static void spi_nor_info_init_params(str + */ + erase_mask = 0; + i = 0; ++#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS ++ if ((info->flags & SECT_4K_PMC) && (params->size <= ++ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) { ++ erase_mask |= BIT(i); ++ spi_nor_set_erase_type(&map->erase_type[i], 4096u, ++ SPINOR_OP_BE_4K_PMC); ++ i++; ++ } else if ((info->flags & SECT_4K) && (params->size <= ++ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) { ++ erase_mask |= BIT(i); ++ spi_nor_set_erase_type(&map->erase_type[i], 4096u, ++ SPINOR_OP_BE_4K); ++ i++; ++ } ++#else + if (info->flags & SECT_4K_PMC) { + erase_mask |= BIT(i); + spi_nor_set_erase_type(&map->erase_type[i], 4096u, +@@ -2803,6 +2818,7 @@ static void spi_nor_info_init_params(str + SPINOR_OP_BE_4K); + i++; + } ++#endif + erase_mask |= BIT(i); + spi_nor_set_erase_type(&map->erase_type[i], info->sector_size, + SPINOR_OP_SE); diff --git a/target/linux/generic/pending-5.15/476-mtd-spi-nor-add-eon-en25q128.patch b/target/linux/generic/pending-5.15/476-mtd-spi-nor-add-eon-en25q128.patch new file mode 100644 index 0000000000..325fca62f3 --- /dev/null +++ b/target/linux/generic/pending-5.15/476-mtd-spi-nor-add-eon-en25q128.patch @@ -0,0 +1,18 @@ +From: Piotr Dymacz +Subject: kernel/mtd: add support for EON EN25Q128 + +Signed-off-by: Piotr Dymacz +--- + drivers/mtd/spi-nor/spi-nor.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/eon.c ++++ b/drivers/mtd/spi-nor/eon.c +@@ -15,6 +15,7 @@ static const struct flash_info eon_parts + { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, + { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, + { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, SECT_4K) }, + { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16, + SECT_4K | SPI_NOR_DUAL_READ) }, + { "en25qh16", INFO(0x1c7015, 0, 64 * 1024, 32, diff --git a/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch new file mode 100644 index 0000000000..796bf6becb --- /dev/null +++ b/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -0,0 +1,79 @@ +From patchwork Thu Feb 6 17:19:41 2020 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 1234465 +Date: Thu, 6 Feb 2020 19:19:41 +0200 +From: Daniel Golle +To: linux-mtd@lists.infradead.org +Subject: [PATCH v2] mtd: spi-nor: Add support for xt25f128b chip +Message-ID: <20200206171941.GA2398@makrotopia.org> +MIME-Version: 1.0 +Content-Disposition: inline +List-Subscribe: , + +Cc: Eitan Cohen , Piotr Dymacz , + Tudor Ambarus +Sender: "linux-mtd" +Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org + +Add XT25F128B made by XTX Technology (Shenzhen) Limited. +This chip supports dual and quad read and uniform 4K-byte erase. +Verified on Teltonika RUT955 which comes with XT25F128B in recent +versions of the device. + +Signed-off-by: Daniel Golle +Signed-off-by: Felix Fietkau +--- + drivers/mtd/spi-nor/spi-nor.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -17,6 +17,7 @@ spi-nor-objs += sst.o + spi-nor-objs += winbond.o + spi-nor-objs += xilinx.o + spi-nor-objs += xmc.o ++spi-nor-objs += xtx.o + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o + + obj-$(CONFIG_MTD_SPI_NOR) += controllers/ +--- /dev/null ++++ b/drivers/mtd/spi-nor/xtx.c +@@ -0,0 +1,15 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++ ++#include "core.h" ++ ++static const struct flash_info xtx_parts[] = { ++ /* XTX Technology (Shenzhen) Limited */ ++ { "xt25f128b", INFO(0x0B4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++}; ++ ++const struct spi_nor_manufacturer spi_nor_xtx = { ++ .name = "xtx", ++ .parts = xtx_parts, ++ .nparts = ARRAY_SIZE(xtx_parts), ++}; +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -2028,6 +2028,7 @@ static const struct spi_nor_manufacturer + &spi_nor_winbond, + &spi_nor_xilinx, + &spi_nor_xmc, ++ &spi_nor_xtx, + }; + + static const struct flash_info * +--- a/drivers/mtd/spi-nor/core.h ++++ b/drivers/mtd/spi-nor/core.h +@@ -398,6 +398,7 @@ extern const struct spi_nor_manufacturer + extern const struct spi_nor_manufacturer spi_nor_winbond; + extern const struct spi_nor_manufacturer spi_nor_xilinx; + extern const struct spi_nor_manufacturer spi_nor_xmc; ++extern const struct spi_nor_manufacturer spi_nor_xtx; + + int spi_nor_write_enable(struct spi_nor *nor); + int spi_nor_write_disable(struct spi_nor *nor); diff --git a/target/linux/generic/pending-5.15/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch b/target/linux/generic/pending-5.15/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch new file mode 100644 index 0000000000..c32cde559d --- /dev/null +++ b/target/linux/generic/pending-5.15/482-mtd-spi-nor-add-support-for-Gigadevice-GD25D05.patch @@ -0,0 +1,22 @@ +From d68b4aa22e8c625685bfad642dd7337948dc0ad1 Mon Sep 17 00:00:00 2001 +From: Koen Vandeputte +Date: Mon, 6 Jan 2020 13:07:56 +0100 +Subject: [PATCH] mtd: spi-nor: add support for Gigadevice GD25D05 + +Signed-off-by: Koen Vandeputte +--- + drivers/mtd/spi-nor/spi-nor.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/mtd/spi-nor/gigadevice.c ++++ b/drivers/mtd/spi-nor/gigadevice.c +@@ -24,6 +24,9 @@ static struct spi_nor_fixups gd25q256_fi + }; + + static const struct flash_info gigadevice_parts[] = { ++ { "gd25q05", INFO(0xc84010, 0, 64 * 1024, 1, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, diff --git a/target/linux/generic/pending-5.15/483-mtd-spi-nor-add-gd25q512.patch b/target/linux/generic/pending-5.15/483-mtd-spi-nor-add-gd25q512.patch new file mode 100644 index 0000000000..6f41546964 --- /dev/null +++ b/target/linux/generic/pending-5.15/483-mtd-spi-nor-add-gd25q512.patch @@ -0,0 +1,12 @@ +--- a/drivers/mtd/spi-nor/gigadevice.c ++++ b/drivers/mtd/spi-nor/gigadevice.c +@@ -53,6 +53,9 @@ static const struct flash_info gigadevic + SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | + SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6) + .fixups = &gd25q256_fixups }, ++ { "gd25q512", INFO(0xc84020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4B_OPCODES) }, + }; + + const struct spi_nor_manufacturer spi_nor_gigadevice = { diff --git a/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch b/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch new file mode 100644 index 0000000000..11590770cd --- /dev/null +++ b/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch @@ -0,0 +1,178 @@ +From a07e31adf2753cad2fd9790db5bfc047c81e8152 Mon Sep 17 00:00:00 2001 +From: Felix Matouschek +Date: Fri, 2 Jul 2021 20:31:23 +0200 +Subject: [PATCH] mtd: spinand: Add support for XTX XT26G0xA + +Add support for XTX Technology XT26G01AXXXXX, XTX26G02AXXXXX and +XTX26G04AXXXXX SPI NAND. + +These are 3V, 1G/2G/4Gbit serial SLC NAND flash devices with on-die ECC +(8bit strength per 512bytes). + +Tested on Teltonika RUTX10 flashed with OpenWrt. + +Datasheets available at +http://www.xtxtech.com/download/?AId=225 +https://datasheet.lcsc.com/szlcsc/2005251034_XTX-XT26G01AWSEGA_C558841.pdf + +Signed-off-by: Felix Matouschek +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/xtx.c | 122 ++++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 125 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/xtx.c + +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,3 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 +-spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o ++spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -760,6 +760,7 @@ static const struct spinand_manufacturer + ¶gon_spinand_manufacturer, + &toshiba_spinand_manufacturer, + &winbond_spinand_manufacturer, ++ &xtx_spinand_manufacturer, + }; + + static int spinand_manufacturer_match(struct spinand_device *spinand, +--- /dev/null ++++ b/drivers/mtd/nand/spi/xtx.c +@@ -0,0 +1,122 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Author: ++ * Felix Matouschek ++ */ ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_XTX 0x0B ++ ++#define XT26G0XA_STATUS_ECC_MASK GENMASK(5, 2) ++#define XT26G0XA_STATUS_ECC_NO_DETECTED (0 << 2) ++#define XT26G0XA_STATUS_ECC_8_CORRECTED (3 << 4) ++#define XT26G0XA_STATUS_ECC_UNCOR_ERROR (2 << 4) ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 8; ++ region->length = 40; ++ ++ return 0; ++} ++ ++static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 1; ++ region->length = 7; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = { ++ .ecc = xt26g0xa_ooblayout_ecc, ++ .free = xt26g0xa_ooblayout_free, ++}; ++ ++static int xt26g0xa_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & XT26G0XA_STATUS_ECC_MASK) { ++ case XT26G0XA_STATUS_ECC_NO_DETECTED: ++ return 0; ++ case XT26G0XA_STATUS_ECC_8_CORRECTED: ++ return 8; ++ case XT26G0XA_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ default: /* (1 << 2) through (7 << 2) are 1-7 corrected errors */ ++ return (status & XT26G0XA_STATUS_ECC_MASK) >> 2; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct spinand_info xtx_spinand_table[] = { ++ SPINAND_INFO("XT26G01A", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE1), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&xt26g0xa_ooblayout, ++ xt26g0xa_ecc_get_status)), ++ SPINAND_INFO("XT26G02A", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&xt26g0xa_ooblayout, ++ xt26g0xa_ecc_get_status)), ++ SPINAND_INFO("XT26G04A", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE3), ++ NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&xt26g0xa_ooblayout, ++ xt26g0xa_ecc_get_status)), ++}; ++ ++static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = { ++}; ++ ++const struct spinand_manufacturer xtx_spinand_manufacturer = { ++ .id = SPINAND_MFR_XTX, ++ .name = "XTX", ++ .chips = xtx_spinand_table, ++ .nchips = ARRAY_SIZE(xtx_spinand_table), ++ .ops = &xtx_spinand_manuf_ops, ++}; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -244,6 +244,7 @@ extern const struct spinand_manufacturer + extern const struct spinand_manufacturer paragon_spinand_manufacturer; + extern const struct spinand_manufacturer toshiba_spinand_manufacturer; + extern const struct spinand_manufacturer winbond_spinand_manufacturer; ++extern const struct spinand_manufacturer xtx_spinand_manufacturer; + + /** + * struct spinand_op_variants - SPI NAND operation variants diff --git a/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch b/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch new file mode 100644 index 0000000000..ce3857d511 --- /dev/null +++ b/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch @@ -0,0 +1,11 @@ +--- a/drivers/mtd/spi-nor/esmt.c ++++ b/drivers/mtd/spi-nor/esmt.c +@@ -10,6 +10,8 @@ + + static const struct flash_info esmt_parts[] = { + /* ESMT */ ++ { "f25l16pa-2s", INFO(0x8c2115, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_HAS_LOCK) }, + { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_HAS_LOCK) }, + { "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, diff --git a/target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch b/target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch new file mode 100644 index 0000000000..4b3f674170 --- /dev/null +++ b/target/linux/generic/pending-5.15/485-mtd-spi-nor-add-xmc-xm25qh128c.patch @@ -0,0 +1,11 @@ +--- a/drivers/mtd/spi-nor/xmc.c ++++ b/drivers/mtd/spi-nor/xmc.c +@@ -14,6 +14,8 @@ static const struct flash_info xmc_parts + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "XM25QH128C", INFO(0x204018, 0, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + }; + + const struct spi_nor_manufacturer spi_nor_xmc = { diff --git a/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch new file mode 100644 index 0000000000..7c9766fa7b --- /dev/null +++ b/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch @@ -0,0 +1,97 @@ +From: Daniel Golle +Subject: ubi: auto-attach mtd device named "ubi" or "data" on boot + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/build.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -1192,6 +1192,73 @@ static struct mtd_info * __init open_mtd + return mtd; + } + ++/* ++ * This function tries attaching mtd partitions named either "ubi" or "data" ++ * during boot. ++ */ ++static void __init ubi_auto_attach(void) ++{ ++ int err; ++ struct mtd_info *mtd; ++ loff_t offset = 0; ++ size_t len; ++ char magic[4]; ++ ++ /* try attaching mtd device named "ubi" or "data" */ ++ mtd = open_mtd_device("ubi"); ++ if (IS_ERR(mtd)) ++ mtd = open_mtd_device("data"); ++ ++ if (IS_ERR(mtd)) ++ return; ++ ++ /* get the first not bad block */ ++ if (mtd_can_have_bb(mtd)) ++ while (mtd_block_isbad(mtd, offset)) { ++ offset += mtd->erasesize; ++ ++ if (offset > mtd->size) { ++ pr_err("UBI error: Failed to find a non-bad " ++ "block on mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ } ++ ++ /* check if the read from flash was successful */ ++ err = mtd_read(mtd, offset, 4, &len, (void *) magic); ++ if ((err && !mtd_is_bitflip(err)) || len != 4) { ++ pr_err("UBI error: unable to read from mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ ++ /* check for a valid ubi magic */ ++ if (strncmp(magic, "UBI#", 4)) { ++ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ ++ /* don't auto-add media types where UBI doesn't makes sense */ ++ if (mtd->type != MTD_NANDFLASH && ++ mtd->type != MTD_NORFLASH && ++ mtd->type != MTD_DATAFLASH && ++ mtd->type != MTD_MLCNANDFLASH) ++ goto cleanup; ++ ++ mutex_lock(&ubi_devices_mutex); ++ pr_notice("UBI: auto-attach mtd%d\n", mtd->index); ++ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0); ++ mutex_unlock(&ubi_devices_mutex); ++ if (err < 0) { ++ pr_err("UBI error: cannot attach mtd%d\n", mtd->index); ++ goto cleanup; ++ } ++ ++ return; ++ ++cleanup: ++ put_mtd_device(mtd); ++} ++ + static int __init ubi_init(void) + { + int err, i, k; +@@ -1275,6 +1342,12 @@ static int __init ubi_init(void) + } + } + ++ /* auto-attach mtd devices only if built-in to the kernel and no ubi.mtd ++ * parameter was given */ ++ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && ++ !ubi_is_module() && !mtd_devs) ++ ubi_auto_attach(); ++ + err = ubiblock_init(); + if (err) { + pr_err("UBI error: block: cannot initialize, error %d\n", err); diff --git a/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch new file mode 100644 index 0000000000..a2b48fd4fc --- /dev/null +++ b/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch @@ -0,0 +1,69 @@ +From: Daniel Golle +Subject: ubi: auto-create ubiblock device for rootfs + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -652,6 +652,47 @@ static void __init ubiblock_create_from_ + } + } + ++#define UBIFS_NODE_MAGIC 0x06101831 ++static inline int ubi_vol_is_ubifs(struct ubi_volume_desc *desc) ++{ ++ int ret; ++ uint32_t magic_of, magic; ++ ret = ubi_read(desc, 0, (char *)&magic_of, 0, 4); ++ if (ret) ++ return 0; ++ magic = le32_to_cpu(magic_of); ++ return magic == UBIFS_NODE_MAGIC; ++} ++ ++static void __init ubiblock_create_auto_rootfs(void) ++{ ++ int ubi_num, ret, is_ubifs; ++ struct ubi_volume_desc *desc; ++ struct ubi_volume_info vi; ++ ++ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) { ++ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY); ++ if (IS_ERR(desc)) ++ desc = ubi_open_volume_nm(ubi_num, "fit", UBI_READONLY);; ++ ++ if (IS_ERR(desc)) ++ continue; ++ ++ ubi_get_volume_info(desc, &vi); ++ is_ubifs = ubi_vol_is_ubifs(desc); ++ ubi_close_volume(desc); ++ if (is_ubifs) ++ break; ++ ++ ret = ubiblock_create(&vi); ++ if (ret) ++ pr_err("UBI error: block: can't add '%s' volume, err=%d\n", ++ vi.name, ret); ++ /* always break if we get here */ ++ break; ++ } ++} ++ + static void ubiblock_remove_all(void) + { + struct ubiblock *next; +@@ -684,6 +725,10 @@ int __init ubiblock_init(void) + */ + ubiblock_create_from_param(); + ++ /* auto-attach "rootfs" volume if existing and non-ubifs */ ++ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV)) ++ ubiblock_create_auto_rootfs(); ++ + /* + * Block devices are only created upon user requests, so we ignore + * existing volumes. diff --git a/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch new file mode 100644 index 0000000000..e3c4dd2ef4 --- /dev/null +++ b/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -0,0 +1,53 @@ +From: Daniel Golle +Subject: try auto-mounting ubi0:rootfs in init/do_mounts.c + +Signed-off-by: Daniel Golle +--- + init/do_mounts.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +--- a/init/do_mounts.c ++++ b/init/do_mounts.c +@@ -474,7 +474,30 @@ retry: + out: + put_page(page); + } +- ++ ++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV ++static int __init mount_ubi_rootfs(void) ++{ ++ int flags = MS_SILENT; ++ int err, tried = 0; ++ ++ while (tried < 2) { ++ err = do_mount_root("ubi0:rootfs", "ubifs", flags, \ ++ root_mount_data); ++ switch (err) { ++ case -EACCES: ++ flags |= MS_RDONLY; ++ tried++; ++ break; ++ default: ++ return err; ++ } ++ } ++ ++ return -EINVAL; ++} ++#endif ++ + #ifdef CONFIG_ROOT_NFS + + #define NFSROOT_TIMEOUT_MIN 5 +@@ -567,6 +590,10 @@ void __init mount_root(void) + return; + } + #endif ++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV ++ if (!mount_ubi_rootfs()) ++ return; ++#endif + #ifdef CONFIG_BLOCK + { + int err = create_dev("/dev/root", ROOT_DEV); diff --git a/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch new file mode 100644 index 0000000000..2dff46807e --- /dev/null +++ b/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -0,0 +1,34 @@ +From: Daniel Golle +Subject: ubi: set ROOT_DEV to ubiblock "rootfs" if unset + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #include "ubi-media.h" + #include "ubi.h" +@@ -458,6 +459,15 @@ int ubiblock_create(struct ubi_volume_in + dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", + dev->ubi_num, dev->vol_id, vi->name); + mutex_unlock(&devices_mutex); ++ ++ if (!strcmp(vi->name, "rootfs") && ++ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && ++ ROOT_DEV == 0) { ++ pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n", ++ dev->ubi_num, dev->vol_id, vi->name); ++ ROOT_DEV = MKDEV(gd->major, gd->first_minor); ++ } ++ + return 0; + + out_free_queue: diff --git a/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch b/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch new file mode 100644 index 0000000000..81d32ca5a5 --- /dev/null +++ b/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch @@ -0,0 +1,60 @@ +From: Gabor Juhos +Subject: mtd: add EOF marker support to the UBI layer + +Signed-off-by: Gabor Juhos +--- + drivers/mtd/ubi/attach.c | 25 ++++++++++++++++++++++--- + drivers/mtd/ubi/ubi.h | 1 + + 2 files changed, 23 insertions(+), 3 deletions(-) + +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -926,6 +926,13 @@ static bool vol_ignored(int vol_id) + #endif + } + ++static bool ec_hdr_has_eof(struct ubi_ec_hdr *ech) ++{ ++ return ech->padding1[0] == 'E' && ++ ech->padding1[1] == 'O' && ++ ech->padding1[2] == 'F'; ++} ++ + /** + * scan_peb - scan and process UBI headers of a PEB. + * @ubi: UBI device description object +@@ -958,9 +965,21 @@ static int scan_peb(struct ubi_device *u + return 0; + } + +- err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); +- if (err < 0) +- return err; ++ if (!ai->eof_found) { ++ err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); ++ if (err < 0) ++ return err; ++ ++ if (ec_hdr_has_eof(ech)) { ++ pr_notice("UBI: EOF marker found, PEBs from %d will be erased\n", ++ pnum); ++ ai->eof_found = true; ++ } ++ } ++ ++ if (ai->eof_found) ++ err = UBI_IO_FF_BITFLIPS; ++ + switch (err) { + case 0: + break; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -782,6 +782,7 @@ struct ubi_attach_info { + int mean_ec; + uint64_t ec_sum; + int ec_count; ++ bool eof_found; + struct kmem_cache *aeb_slab_cache; + struct ubi_ec_hdr *ech; + struct ubi_vid_io_buf *vidb; diff --git a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch new file mode 100644 index 0000000000..d5db5fdd54 --- /dev/null +++ b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch @@ -0,0 +1,75 @@ +From 1bd1b740f208d1cf4071932cc51860d37266c402 Mon Sep 17 00:00:00 2001 +From: Bernhard Frauendienst +Date: Sat, 1 Sep 2018 00:30:11 +0200 +Subject: [PATCH 495/497] mtd: core: add get_mtd_device_by_node + +Add function to retrieve a mtd device by its OF node. Since drivers can +assign arbitrary names to mtd devices in the absence of a label +property, there is no other reliable way to retrieve a mtd device for a +given OF node. + +Signed-off-by: Bernhard Frauendienst +Reviewed-by: Miquel Raynal +--- + drivers/mtd/mtdcore.c | 38 ++++++++++++++++++++++++++++++++++++++ + include/linux/mtd/mtd.h | 2 ++ + 2 files changed, 40 insertions(+) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -1046,6 +1046,44 @@ out_unlock: + } + EXPORT_SYMBOL_GPL(get_mtd_device_nm); + ++/** ++ * get_mtd_device_by_node - obtain a validated handle for an MTD device ++ * by of_node ++ * @of_node: OF node of MTD device to open ++ * ++ * This function returns MTD device description structure in case of ++ * success and an error code in case of failure. ++ */ ++struct mtd_info *get_mtd_device_by_node(const struct device_node *of_node) ++{ ++ int err = -ENODEV; ++ struct mtd_info *mtd = NULL, *other; ++ ++ mutex_lock(&mtd_table_mutex); ++ ++ mtd_for_each_device(other) { ++ if (of_node == other->dev.of_node) { ++ mtd = other; ++ break; ++ } ++ } ++ ++ if (!mtd) ++ goto out_unlock; ++ ++ err = __get_mtd_device(mtd); ++ if (err) ++ goto out_unlock; ++ ++ mutex_unlock(&mtd_table_mutex); ++ return mtd; ++ ++out_unlock: ++ mutex_unlock(&mtd_table_mutex); ++ return ERR_PTR(err); ++} ++EXPORT_SYMBOL_GPL(get_mtd_device_by_node); ++ + void put_mtd_device(struct mtd_info *mtd) + { + mutex_lock(&mtd_table_mutex); +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -698,6 +698,8 @@ extern struct mtd_info *get_mtd_device(s + extern int __get_mtd_device(struct mtd_info *mtd); + extern void __put_mtd_device(struct mtd_info *mtd); + extern struct mtd_info *get_mtd_device_nm(const char *name); ++extern struct mtd_info *get_mtd_device_by_node( ++ const struct device_node *of_node); + extern void put_mtd_device(struct mtd_info *mtd); + + static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) diff --git a/target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch b/target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch new file mode 100644 index 0000000000..01f3b9ec2d --- /dev/null +++ b/target/linux/generic/pending-5.15/496-dt-bindings-add-bindings-for-mtd-concat-devices.patch @@ -0,0 +1,52 @@ +From 5734c6669fba7ddb5ef491ccff7159d15dba0b59 Mon Sep 17 00:00:00 2001 +From: Bernhard Frauendienst +Date: Wed, 5 Sep 2018 01:32:51 +0200 +Subject: [PATCH 496/497] dt-bindings: add bindings for mtd-concat devices + +Document virtual mtd-concat device bindings. + +Signed-off-by: Bernhard Frauendienst +--- + .../devicetree/bindings/mtd/mtd-concat.txt | 36 +++++++++++++++++++ + 1 file changed, 36 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/mtd-concat.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/mtd-concat.txt +@@ -0,0 +1,36 @@ ++Virtual MTD concat device ++ ++Requires properties: ++- devices: list of phandles to mtd nodes that should be concatenated ++ ++Example: ++ ++&spi { ++ flash0: flash@0 { ++ ... ++ }; ++ flash1: flash@1 { ++ ... ++ }; ++}; ++ ++flash { ++ compatible = "mtd-concat"; ++ ++ devices = <&flash0 &flash1>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ ++ partition@0 { ++ label = "boot"; ++ reg = <0x0000000 0x0040000>; ++ read-only; ++ }; ++ ++ partition@40000 { ++ label = "firmware"; ++ reg = <0x0040000 0x1fc0000>; ++ }; ++ } ++} diff --git a/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch new file mode 100644 index 0000000000..058cab09e5 --- /dev/null +++ b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch @@ -0,0 +1,216 @@ +From e53f712d8eac71f54399b61038ccf87d2cee99d7 Mon Sep 17 00:00:00 2001 +From: Bernhard Frauendienst +Date: Sat, 25 Aug 2018 12:35:22 +0200 +Subject: [PATCH 497/497] mtd: mtdconcat: add dt driver for concat devices + +Some mtd drivers like physmap variants have support for concatenating +multiple mtd devices, but there is no generic way to define such a +concat device from within the device tree. + +This is useful for some SoC boards that use multiple flash chips as +memory banks of a single mtd device, with partitions spanning chip +borders. + +This commit adds a driver for creating virtual mtd-concat devices. They +must have a compatible = "mtd-concat" line, and define a list of devices +to concat in the 'devices' property, for example: + +flash { + compatible = "mtd-concat"; + + devices = <&flash0 &flash1>; + + partitions { + ... + }; +}; + +The driver is added to the very end of the mtd Makefile to increase the +likelyhood of all child devices already being loaded at the time of +probing, preventing unnecessary deferred probes. + +Signed-off-by: Bernhard Frauendienst +--- + drivers/mtd/Kconfig | 2 + + drivers/mtd/Makefile | 3 + + drivers/mtd/composite/Kconfig | 12 +++ + drivers/mtd/composite/Makefile | 6 ++ + drivers/mtd/composite/virt_concat.c | 128 ++++++++++++++++++++++++++++ + 5 files changed, 151 insertions(+) + create mode 100644 drivers/mtd/composite/Kconfig + create mode 100644 drivers/mtd/composite/Makefile + create mode 100644 drivers/mtd/composite/virt_concat.c + +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -238,4 +238,6 @@ source "drivers/mtd/ubi/Kconfig" + + source "drivers/mtd/hyperbus/Kconfig" + ++source "drivers/mtd/composite/Kconfig" ++ + endif # MTD +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -33,3 +33,6 @@ obj-y += chips/ lpddr/ maps/ devices/ n + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-$(CONFIG_MTD_UBI) += ubi/ + obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ ++ ++# Composite drivers must be loaded last ++obj-y += composite/ +--- /dev/null ++++ b/drivers/mtd/composite/Kconfig +@@ -0,0 +1,12 @@ ++menu "Composite MTD device drivers" ++ depends on MTD!=n ++ ++config MTD_VIRT_CONCAT ++ tristate "Virtual concat MTD device" ++ help ++ This driver allows creation of a virtual MTD concat device, which ++ concatenates multiple underlying MTD devices to a single device. ++ This is required by some SoC boards where multiple memory banks are ++ used as one device with partitions spanning across device boundaries. ++ ++endmenu +--- /dev/null ++++ b/drivers/mtd/composite/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# linux/drivers/mtd/composite/Makefile ++# ++ ++obj-$(CONFIG_MTD_VIRT_CONCAT) += virt_concat.o +--- /dev/null ++++ b/drivers/mtd/composite/virt_concat.c +@@ -0,0 +1,128 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Virtual concat MTD device driver ++ * ++ * Copyright (C) 2018 Bernhard Frauendienst ++ * Author: Bernhard Frauendienst, kernel@nospam.obeliks.de ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * struct of_virt_concat - platform device driver data. ++ * @cmtd the final mtd_concat device ++ * @num_devices the number of devices in @devices ++ * @devices points to an array of devices already loaded ++ */ ++struct of_virt_concat { ++ struct mtd_info *cmtd; ++ int num_devices; ++ struct mtd_info **devices; ++}; ++ ++static int virt_concat_remove(struct platform_device *pdev) ++{ ++ struct of_virt_concat *info; ++ int i; ++ ++ info = platform_get_drvdata(pdev); ++ if (!info) ++ return 0; ++ ++ // unset data for when this is called after a probe error ++ platform_set_drvdata(pdev, NULL); ++ ++ if (info->cmtd) { ++ mtd_device_unregister(info->cmtd); ++ mtd_concat_destroy(info->cmtd); ++ } ++ ++ if (info->devices) { ++ for (i = 0; i < info->num_devices; i++) ++ put_mtd_device(info->devices[i]); ++ } ++ ++ return 0; ++} ++ ++static int virt_concat_probe(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ struct of_phandle_iterator it; ++ struct of_virt_concat *info; ++ struct mtd_info *mtd; ++ int err = 0, count; ++ ++ count = of_count_phandle_with_args(node, "devices", NULL); ++ if (count <= 0) ++ return -EINVAL; ++ ++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ info->devices = devm_kcalloc(&pdev->dev, count, ++ sizeof(*(info->devices)), GFP_KERNEL); ++ if (!info->devices) { ++ err = -ENOMEM; ++ goto err_remove; ++ } ++ ++ platform_set_drvdata(pdev, info); ++ ++ of_for_each_phandle(&it, err, node, "devices", NULL, 0) { ++ mtd = get_mtd_device_by_node(it.node); ++ if (IS_ERR(mtd)) { ++ of_node_put(it.node); ++ err = -EPROBE_DEFER; ++ goto err_remove; ++ } ++ ++ info->devices[info->num_devices++] = mtd; ++ } ++ ++ info->cmtd = mtd_concat_create(info->devices, info->num_devices, ++ dev_name(&pdev->dev)); ++ if (!info->cmtd) { ++ err = -ENXIO; ++ goto err_remove; ++ } ++ ++ info->cmtd->dev.parent = &pdev->dev; ++ mtd_set_of_node(info->cmtd, node); ++ mtd_device_register(info->cmtd, NULL, 0); ++ ++ return 0; ++ ++err_remove: ++ virt_concat_remove(pdev); ++ ++ return err; ++} ++ ++static const struct of_device_id virt_concat_of_match[] = { ++ { .compatible = "mtd-concat", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, virt_concat_of_match); ++ ++static struct platform_driver virt_concat_driver = { ++ .probe = virt_concat_probe, ++ .remove = virt_concat_remove, ++ .driver = { ++ .name = "virt-mtdconcat", ++ .of_match_table = virt_concat_of_match, ++ }, ++}; ++ ++module_platform_driver(virt_concat_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Bernhard Frauendienst "); ++MODULE_DESCRIPTION("Virtual concat MTD device driver"); diff --git a/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch b/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch new file mode 100644 index 0000000000..62e977c8d1 --- /dev/null +++ b/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch @@ -0,0 +1,34 @@ +From 8bf2ce6ea4ee840b70f55a27f80e1cd308051b13 Mon Sep 17 00:00:00 2001 +From: Nick Hainke +Date: Mon, 27 Dec 2021 00:38:13 +0100 +Subject: [PATCH 1/2] mtd: spi-nor: locking support for MX25L6405D + +Macronix MX25L6405D supports locking with four block-protection bits. +Currently, the driver only sets three bits. If the bootloader does not +sustain the flash chip in an unlocked state, the flash might be +non-writeable. Add the corresponding flag to enable locking support with +four bits in the status register. + +Tested on Nanostation M2 XM. + +Similar to commit 7ea40b54e83b ("mtd: spi-nor: enable locking support for +MX25L12805D") + +Signed-off-by: David Bauer +Signed-off-by: Nick Hainke +--- + drivers/mtd/spi-nor/macronix.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/macronix.c ++++ b/drivers/mtd/spi-nor/macronix.c +@@ -42,7 +42,8 @@ static const struct flash_info macronix_ + { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, + { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, + { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, +- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K | ++ SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP) }, + { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, + { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | diff --git a/target/linux/generic/pending-5.15/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch b/target/linux/generic/pending-5.15/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch new file mode 100644 index 0000000000..ec14f6341c --- /dev/null +++ b/target/linux/generic/pending-5.15/499-mtd-spi-nor-disable-16-bit-sr-for-macronix.patch @@ -0,0 +1,30 @@ +From 245224608b5368c10407da07557e546743d3c489 Mon Sep 17 00:00:00 2001 +From: Nick Hainke +Date: Mon, 27 Dec 2021 09:33:13 +0100 +Subject: [PATCH 2/2] mtd: spi-nor: disable 16-bit-sr for macronix + +Macronix flash chips seem to consist of only one status register. +These chips will not work with the "16-bit Write Status (01h) Command". +Disable SNOR_F_HAS_16BIT_SR for all Macronix chips. + +Tested with MX25L6405D. + +Fixes: 39d1e3340c73 ("mtd: spi-nor: Fix clearing of QE bit on +lock()/unlock()") + +Signed-off-by: David Bauer +Signed-off-by: Nick Hainke +--- + drivers/mtd/spi-nor/macronix.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/spi-nor/macronix.c ++++ b/drivers/mtd/spi-nor/macronix.c +@@ -94,6 +94,7 @@ static void macronix_default_init(struct + { + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; + nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; ++ nor->flags &= ~SNOR_F_HAS_16BIT_SR; + nor->flags |= SNOR_F_HAS_LOCK; + } + diff --git a/target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch b/target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch new file mode 100644 index 0000000000..0a5a3aae5d --- /dev/null +++ b/target/linux/generic/pending-5.15/500-fs_cdrom_dependencies.patch @@ -0,0 +1,40 @@ +--- a/fs/hfs/Kconfig ++++ b/fs/hfs/Kconfig +@@ -2,6 +2,7 @@ + config HFS_FS + tristate "Apple Macintosh file system support" + depends on BLOCK ++ select CDROM + select NLS + help + If you say Y here, you will be able to mount Macintosh-formatted +--- a/fs/hfsplus/Kconfig ++++ b/fs/hfsplus/Kconfig +@@ -2,6 +2,7 @@ + config HFSPLUS_FS + tristate "Apple Extended HFS file system support" + depends on BLOCK ++ select CDROM + select NLS + select NLS_UTF8 + help +--- a/fs/isofs/Kconfig ++++ b/fs/isofs/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + config ISO9660_FS + tristate "ISO 9660 CDROM file system support" ++ select CDROM + help + This is the standard file system used on CD-ROMs. It was previously + known as "High Sierra File System" and is called "hsfs" on other +--- a/fs/udf/Kconfig ++++ b/fs/udf/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + config UDF_FS + tristate "UDF file system support" ++ select CDROM + select CRC_ITU_T + select NLS + help diff --git a/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch new file mode 100644 index 0000000000..20483a391d --- /dev/null +++ b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch @@ -0,0 +1,5180 @@ +From: Alexandros C. Couloumbis +Subject: fs: add jffs2/lzma support (not activated by default yet) + +lede-commit: c2c88d315fa0e881f8b19da07b62859b915b11b2 +Signed-off-by: Alexandros C. Couloumbis +--- + fs/jffs2/Kconfig | 9 + + fs/jffs2/Makefile | 3 + + fs/jffs2/compr.c | 6 + + fs/jffs2/compr.h | 10 +- + fs/jffs2/compr_lzma.c | 128 +++ + fs/jffs2/super.c | 33 +- + include/linux/lzma.h | 62 ++ + include/linux/lzma/LzFind.h | 115 +++ + include/linux/lzma/LzHash.h | 54 + + include/linux/lzma/LzmaDec.h | 231 +++++ + include/linux/lzma/LzmaEnc.h | 80 ++ + include/linux/lzma/Types.h | 226 +++++ + include/uapi/linux/jffs2.h | 1 + + lib/Kconfig | 6 + + lib/Makefile | 12 + + lib/lzma/LzFind.c | 761 ++++++++++++++ + lib/lzma/LzmaDec.c | 999 +++++++++++++++++++ + lib/lzma/LzmaEnc.c | 2271 ++++++++++++++++++++++++++++++++++++++++++ + lib/lzma/Makefile | 7 + + 19 files changed, 5008 insertions(+), 6 deletions(-) + create mode 100644 fs/jffs2/compr_lzma.c + create mode 100644 include/linux/lzma.h + create mode 100644 include/linux/lzma/LzFind.h + create mode 100644 include/linux/lzma/LzHash.h + create mode 100644 include/linux/lzma/LzmaDec.h + create mode 100644 include/linux/lzma/LzmaEnc.h + create mode 100644 include/linux/lzma/Types.h + create mode 100644 lib/lzma/LzFind.c + create mode 100644 lib/lzma/LzmaDec.c + create mode 100644 lib/lzma/LzmaEnc.c + create mode 100644 lib/lzma/Makefile + +--- a/fs/jffs2/Kconfig ++++ b/fs/jffs2/Kconfig +@@ -136,6 +136,15 @@ config JFFS2_LZO + This feature was added in July, 2007. Say 'N' if you need + compatibility with older bootloaders or kernels. + ++config JFFS2_LZMA ++ bool "JFFS2 LZMA compression support" if JFFS2_COMPRESSION_OPTIONS ++ select LZMA_COMPRESS ++ select LZMA_DECOMPRESS ++ depends on JFFS2_FS ++ default n ++ help ++ JFFS2 wrapper to the LZMA C SDK ++ + config JFFS2_RTIME + bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS + depends on JFFS2_FS +--- a/fs/jffs2/Makefile ++++ b/fs/jffs2/Makefile +@@ -19,4 +19,7 @@ jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rub + jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o + jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o + jffs2-$(CONFIG_JFFS2_LZO) += compr_lzo.o ++jffs2-$(CONFIG_JFFS2_LZMA) += compr_lzma.o + jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o ++ ++CFLAGS_compr_lzma.o += -Iinclude/linux -Ilib/lzma +--- a/fs/jffs2/compr.c ++++ b/fs/jffs2/compr.c +@@ -378,6 +378,9 @@ int __init jffs2_compressors_init(void) + #ifdef CONFIG_JFFS2_LZO + jffs2_lzo_init(); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++ jffs2_lzma_init(); ++#endif + /* Setting default compression mode */ + #ifdef CONFIG_JFFS2_CMODE_NONE + jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; +@@ -401,6 +404,9 @@ int __init jffs2_compressors_init(void) + int jffs2_compressors_exit(void) + { + /* Unregistering compressors */ ++#ifdef CONFIG_JFFS2_LZMA ++ jffs2_lzma_exit(); ++#endif + #ifdef CONFIG_JFFS2_LZO + jffs2_lzo_exit(); + #endif +--- a/fs/jffs2/compr.h ++++ b/fs/jffs2/compr.h +@@ -29,9 +29,9 @@ + #define JFFS2_DYNRUBIN_PRIORITY 20 + #define JFFS2_LZARI_PRIORITY 30 + #define JFFS2_RTIME_PRIORITY 50 +-#define JFFS2_ZLIB_PRIORITY 60 +-#define JFFS2_LZO_PRIORITY 80 +- ++#define JFFS2_LZMA_PRIORITY 70 ++#define JFFS2_ZLIB_PRIORITY 80 ++#define JFFS2_LZO_PRIORITY 90 + + #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */ + #define JFFS2_DYNRUBIN_DISABLED /* for decompression */ +@@ -101,5 +101,9 @@ void jffs2_zlib_exit(void); + int jffs2_lzo_init(void); + void jffs2_lzo_exit(void); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++int jffs2_lzma_init(void); ++void jffs2_lzma_exit(void); ++#endif + + #endif /* __JFFS2_COMPR_H__ */ +--- /dev/null ++++ b/fs/jffs2/compr_lzma.c +@@ -0,0 +1,128 @@ ++/* ++ * JFFS2 -- Journalling Flash File System, Version 2. ++ * ++ * For licensing information, see the file 'LICENCE' in this directory. ++ * ++ * JFFS2 wrapper to the LZMA C SDK ++ * ++ */ ++ ++#include ++#include "compr.h" ++ ++#ifdef __KERNEL__ ++ static DEFINE_MUTEX(deflate_mutex); ++#endif ++ ++CLzmaEncHandle *p; ++Byte propsEncoded[LZMA_PROPS_SIZE]; ++SizeT propsSize = sizeof(propsEncoded); ++ ++STATIC void lzma_free_workspace(void) ++{ ++ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc); ++} ++ ++STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props) ++{ ++ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL) ++ { ++ PRINT_ERROR("Failed to allocate lzma deflate workspace\n"); ++ return -ENOMEM; ++ } ++ ++ if (LzmaEnc_SetProps(p, props) != SZ_OK) ++ { ++ lzma_free_workspace(); ++ return -1; ++ } ++ ++ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK) ++ { ++ lzma_free_workspace(); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out, ++ uint32_t *sourcelen, uint32_t *dstlen) ++{ ++ SizeT compress_size = (SizeT)(*dstlen); ++ int ret; ++ ++ #ifdef __KERNEL__ ++ mutex_lock(&deflate_mutex); ++ #endif ++ ++ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen, ++ 0, NULL, &lzma_alloc, &lzma_alloc); ++ ++ #ifdef __KERNEL__ ++ mutex_unlock(&deflate_mutex); ++ #endif ++ ++ if (ret != SZ_OK) ++ return -1; ++ ++ *dstlen = (uint32_t)compress_size; ++ ++ return 0; ++} ++ ++STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out, ++ uint32_t srclen, uint32_t destlen) ++{ ++ int ret; ++ SizeT dl = (SizeT)destlen; ++ SizeT sl = (SizeT)srclen; ++ ELzmaStatus status; ++ ++ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded, ++ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc); ++ ++ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen) ++ return -1; ++ ++ return 0; ++} ++ ++static struct jffs2_compressor jffs2_lzma_comp = { ++ .priority = JFFS2_LZMA_PRIORITY, ++ .name = "lzma", ++ .compr = JFFS2_COMPR_LZMA, ++ .compress = &jffs2_lzma_compress, ++ .decompress = &jffs2_lzma_decompress, ++ .disabled = 0, ++}; ++ ++int INIT jffs2_lzma_init(void) ++{ ++ int ret; ++ CLzmaEncProps props; ++ LzmaEncProps_Init(&props); ++ ++ props.dictSize = LZMA_BEST_DICT(0x2000); ++ props.level = LZMA_BEST_LEVEL; ++ props.lc = LZMA_BEST_LC; ++ props.lp = LZMA_BEST_LP; ++ props.pb = LZMA_BEST_PB; ++ props.fb = LZMA_BEST_FB; ++ ++ ret = lzma_alloc_workspace(&props); ++ if (ret < 0) ++ return ret; ++ ++ ret = jffs2_register_compressor(&jffs2_lzma_comp); ++ if (ret) ++ lzma_free_workspace(); ++ ++ return ret; ++} ++ ++void jffs2_lzma_exit(void) ++{ ++ jffs2_unregister_compressor(&jffs2_lzma_comp); ++ lzma_free_workspace(); ++} +--- a/fs/jffs2/super.c ++++ b/fs/jffs2/super.c +@@ -374,14 +374,41 @@ static int __init init_jffs2_fs(void) + BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68); + BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32); + +- pr_info("version 2.2." ++ pr_info("version 2.2" + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER + " (NAND)" + #endif + #ifdef CONFIG_JFFS2_SUMMARY +- " (SUMMARY) " ++ " (SUMMARY)" + #endif +- " © 2001-2006 Red Hat, Inc.\n"); ++#ifdef CONFIG_JFFS2_ZLIB ++ " (ZLIB)" ++#endif ++#ifdef CONFIG_JFFS2_LZO ++ " (LZO)" ++#endif ++#ifdef CONFIG_JFFS2_LZMA ++ " (LZMA)" ++#endif ++#ifdef CONFIG_JFFS2_RTIME ++ " (RTIME)" ++#endif ++#ifdef CONFIG_JFFS2_RUBIN ++ " (RUBIN)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_NONE ++ " (CMODE_NONE)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_PRIORITY ++ " (CMODE_PRIORITY)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_SIZE ++ " (CMODE_SIZE)" ++#endif ++#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO ++ " (CMODE_FAVOURLZO)" ++#endif ++ " (c) 2001-2006 Red Hat, Inc.\n"); + + jffs2_inode_cachep = kmem_cache_create("jffs2_i", + sizeof(struct jffs2_inode_info), +--- /dev/null ++++ b/include/linux/lzma.h +@@ -0,0 +1,62 @@ ++#ifndef __LZMA_H__ ++#define __LZMA_H__ ++ ++#ifdef __KERNEL__ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #define LZMA_MALLOC vmalloc ++ #define LZMA_FREE vfree ++ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg) ++ #define INIT __init ++ #define STATIC static ++#else ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #ifndef PAGE_SIZE ++ extern int page_size; ++ #define PAGE_SIZE page_size ++ #endif ++ #define LZMA_MALLOC malloc ++ #define LZMA_FREE free ++ #define PRINT_ERROR(msg) fprintf(stderr, msg) ++ #define INIT ++ #define STATIC ++#endif ++ ++#include "lzma/LzmaDec.h" ++#include "lzma/LzmaEnc.h" ++ ++#define LZMA_BEST_LEVEL (9) ++#define LZMA_BEST_LC (0) ++#define LZMA_BEST_LP (0) ++#define LZMA_BEST_PB (0) ++#define LZMA_BEST_FB (273) ++ ++#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2) ++ ++static void *p_lzma_malloc(void *p, size_t size) ++{ ++ if (size == 0) ++ return NULL; ++ ++ return LZMA_MALLOC(size); ++} ++ ++static void p_lzma_free(void *p, void *address) ++{ ++ if (address != NULL) ++ LZMA_FREE(address); ++} ++ ++static ISzAlloc lzma_alloc = { .Alloc = p_lzma_malloc, .Free = p_lzma_free }; ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzFind.h +@@ -0,0 +1,115 @@ ++/* LzFind.h -- Match finder for LZ algorithms ++2009-04-22 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZ_FIND_H ++#define __LZ_FIND_H ++ ++#include "Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef UInt32 CLzRef; ++ ++typedef struct _CMatchFinder ++{ ++ Byte *buffer; ++ UInt32 pos; ++ UInt32 posLimit; ++ UInt32 streamPos; ++ UInt32 lenLimit; ++ ++ UInt32 cyclicBufferPos; ++ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ ++ ++ UInt32 matchMaxLen; ++ CLzRef *hash; ++ CLzRef *son; ++ UInt32 hashMask; ++ UInt32 cutValue; ++ ++ Byte *bufferBase; ++ ISeqInStream *stream; ++ int streamEndWasReached; ++ ++ UInt32 blockSize; ++ UInt32 keepSizeBefore; ++ UInt32 keepSizeAfter; ++ ++ UInt32 numHashBytes; ++ int directInput; ++ size_t directInputRem; ++ int btMode; ++ int bigHash; ++ UInt32 historySize; ++ UInt32 fixedHashSize; ++ UInt32 hashSizeSum; ++ UInt32 numSons; ++ SRes result; ++ UInt32 crc[256]; ++} CMatchFinder; ++ ++#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) ++#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) ++ ++#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) ++ ++int MatchFinder_NeedMove(CMatchFinder *p); ++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); ++void MatchFinder_MoveBlock(CMatchFinder *p); ++void MatchFinder_ReadIfRequired(CMatchFinder *p); ++ ++void MatchFinder_Construct(CMatchFinder *p); ++ ++/* Conditions: ++ historySize <= 3 GB ++ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB ++*/ ++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc); ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); ++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); ++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); ++ ++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, ++ UInt32 *distances, UInt32 maxLen); ++ ++/* ++Conditions: ++ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. ++ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function ++*/ ++ ++typedef void (*Mf_Init_Func)(void *object); ++typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); ++typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); ++typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); ++typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); ++typedef void (*Mf_Skip_Func)(void *object, UInt32); ++ ++typedef struct _IMatchFinder ++{ ++ Mf_Init_Func Init; ++ Mf_GetIndexByte_Func GetIndexByte; ++ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; ++ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; ++ Mf_GetMatches_Func GetMatches; ++ Mf_Skip_Func Skip; ++} IMatchFinder; ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); ++ ++void MatchFinder_Init(CMatchFinder *p); ++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzHash.h +@@ -0,0 +1,54 @@ ++/* LzHash.h -- HASH functions for LZ algorithms ++2009-02-07 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZ_HASH_H ++#define __LZ_HASH_H ++ ++#define kHash2Size (1 << 10) ++#define kHash3Size (1 << 16) ++#define kHash4Size (1 << 20) ++ ++#define kFix3HashSize (kHash2Size) ++#define kFix4HashSize (kHash2Size + kHash3Size) ++#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) ++ ++#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); ++ ++#define HASH3_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } ++ ++#define HASH4_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } ++ ++#define HASH5_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ ++ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ ++ hash4Value &= (kHash4Size - 1); } ++ ++/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ ++#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; ++ ++ ++#define MT_HASH2_CALC \ ++ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); ++ ++#define MT_HASH3_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } ++ ++#define MT_HASH4_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaDec.h +@@ -0,0 +1,231 @@ ++/* LzmaDec.h -- LZMA Decoder ++2009-02-07 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZMA_DEC_H ++#define __LZMA_DEC_H ++ ++#include "Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* #define _LZMA_PROB32 */ ++/* _LZMA_PROB32 can increase the speed on some CPUs, ++ but memory usage for CLzmaDec::probs will be doubled in that case */ ++ ++#ifdef _LZMA_PROB32 ++#define CLzmaProb UInt32 ++#else ++#define CLzmaProb UInt16 ++#endif ++ ++ ++/* ---------- LZMA Properties ---------- */ ++ ++#define LZMA_PROPS_SIZE 5 ++ ++typedef struct _CLzmaProps ++{ ++ unsigned lc, lp, pb; ++ UInt32 dicSize; ++} CLzmaProps; ++ ++/* LzmaProps_Decode - decodes properties ++Returns: ++ SZ_OK ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++*/ ++ ++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); ++ ++ ++/* ---------- LZMA Decoder state ---------- */ ++ ++/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. ++ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ ++ ++#define LZMA_REQUIRED_INPUT_MAX 20 ++ ++typedef struct ++{ ++ CLzmaProps prop; ++ CLzmaProb *probs; ++ Byte *dic; ++ const Byte *buf; ++ UInt32 range, code; ++ SizeT dicPos; ++ SizeT dicBufSize; ++ UInt32 processedPos; ++ UInt32 checkDicSize; ++ unsigned state; ++ UInt32 reps[4]; ++ unsigned remainLen; ++ int needFlush; ++ int needInitState; ++ UInt32 numProbs; ++ unsigned tempBufSize; ++ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; ++} CLzmaDec; ++ ++#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } ++ ++void LzmaDec_Init(CLzmaDec *p); ++ ++/* There are two types of LZMA streams: ++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. ++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ ++ ++typedef enum ++{ ++ LZMA_FINISH_ANY, /* finish at any point */ ++ LZMA_FINISH_END /* block must be finished at the end */ ++} ELzmaFinishMode; ++ ++/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! ++ ++ You must use LZMA_FINISH_END, when you know that current output buffer ++ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. ++ ++ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, ++ and output value of destLen will be less than output buffer size limit. ++ You can check status result also. ++ ++ You can use multiple checks to test data integrity after full decompression: ++ 1) Check Result and "status" variable. ++ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. ++ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. ++ You must use correct finish mode in that case. */ ++ ++typedef enum ++{ ++ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ ++ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ ++ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ ++ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ ++} ELzmaStatus; ++ ++/* ELzmaStatus is used only as output value for function call */ ++ ++ ++/* ---------- Interfaces ---------- */ ++ ++/* There are 3 levels of interfaces: ++ 1) Dictionary Interface ++ 2) Buffer Interface ++ 3) One Call Interface ++ You can select any of these interfaces, but don't mix functions from different ++ groups for same object. */ ++ ++ ++/* There are two variants to allocate state for Dictionary Interface: ++ 1) LzmaDec_Allocate / LzmaDec_Free ++ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs ++ You can use variant 2, if you set dictionary buffer manually. ++ For Buffer Interface you must always use variant 1. ++ ++LzmaDec_Allocate* can return: ++ SZ_OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++*/ ++ ++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); ++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); ++ ++SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); ++void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); ++ ++/* ---------- Dictionary Interface ---------- */ ++ ++/* You can use it, if you want to eliminate the overhead for data copying from ++ dictionary to some other external buffer. ++ You must work with CLzmaDec variables directly in this interface. ++ ++ STEPS: ++ LzmaDec_Constr() ++ LzmaDec_Allocate() ++ for (each new stream) ++ { ++ LzmaDec_Init() ++ while (it needs more decompression) ++ { ++ LzmaDec_DecodeToDic() ++ use data from CLzmaDec::dic and update CLzmaDec::dicPos ++ } ++ } ++ LzmaDec_Free() ++*/ ++ ++/* LzmaDec_DecodeToDic ++ ++ The decoding to internal dictionary buffer (CLzmaDec::dic). ++ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (dicLimit). ++ LZMA_FINISH_ANY - Decode just dicLimit bytes. ++ LZMA_FINISH_END - Stream must be finished after dicLimit. ++ ++Returns: ++ SZ_OK ++ status: ++ LZMA_STATUS_FINISHED_WITH_MARK ++ LZMA_STATUS_NOT_FINISHED ++ LZMA_STATUS_NEEDS_MORE_INPUT ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++ SZ_ERROR_DATA - Data error ++*/ ++ ++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, ++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++ ++ ++/* ---------- Buffer Interface ---------- */ ++ ++/* It's zlib-like interface. ++ See LzmaDec_DecodeToDic description for information about STEPS and return results, ++ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need ++ to work with CLzmaDec variables manually. ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (*destLen). ++ LZMA_FINISH_ANY - Decode just destLen bytes. ++ LZMA_FINISH_END - Stream must be finished after (*destLen). ++*/ ++ ++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, ++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++ ++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaDecode ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (*destLen). ++ LZMA_FINISH_ANY - Decode just destLen bytes. ++ LZMA_FINISH_END - Stream must be finished after (*destLen). ++ ++Returns: ++ SZ_OK ++ status: ++ LZMA_STATUS_FINISHED_WITH_MARK ++ LZMA_STATUS_NOT_FINISHED ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++ SZ_ERROR_DATA - Data error ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). ++*/ ++ ++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++ ELzmaStatus *status, ISzAlloc *alloc); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaEnc.h +@@ -0,0 +1,80 @@ ++/* LzmaEnc.h -- LZMA Encoder ++2009-02-07 : Igor Pavlov : Public domain */ ++ ++#ifndef __LZMA_ENC_H ++#define __LZMA_ENC_H ++ ++#include "Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LZMA_PROPS_SIZE 5 ++ ++typedef struct _CLzmaEncProps ++{ ++ int level; /* 0 <= level <= 9 */ ++ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version ++ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version ++ default = (1 << 24) */ ++ int lc; /* 0 <= lc <= 8, default = 3 */ ++ int lp; /* 0 <= lp <= 4, default = 0 */ ++ int pb; /* 0 <= pb <= 4, default = 2 */ ++ int algo; /* 0 - fast, 1 - normal, default = 1 */ ++ int fb; /* 5 <= fb <= 273, default = 32 */ ++ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ ++ int numHashBytes; /* 2, 3 or 4, default = 4 */ ++ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ ++ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ ++ int numThreads; /* 1 or 2, default = 2 */ ++} CLzmaEncProps; ++ ++void LzmaEncProps_Init(CLzmaEncProps *p); ++void LzmaEncProps_Normalize(CLzmaEncProps *p); ++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); ++ ++ ++/* ---------- CLzmaEncHandle Interface ---------- */ ++ ++/* LzmaEnc_* functions can return the following exit codes: ++Returns: ++ SZ_OK - OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_PARAM - Incorrect paramater in props ++ SZ_ERROR_WRITE - Write callback error. ++ SZ_ERROR_PROGRESS - some break from progress callback ++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++*/ ++ ++typedef void * CLzmaEncHandle; ++ ++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); ++SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaEncode ++Return code: ++ SZ_OK - OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_PARAM - Incorrect paramater ++ SZ_ERROR_OUTPUT_EOF - output buffer overflow ++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++*/ ++ ++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/Types.h +@@ -0,0 +1,226 @@ ++/* Types.h -- Basic types ++2009-11-23 : Igor Pavlov : Public domain */ ++ ++#ifndef __7Z_TYPES_H ++#define __7Z_TYPES_H ++ ++#include ++ ++#ifdef _WIN32 ++#include ++#endif ++ ++#ifndef EXTERN_C_BEGIN ++#ifdef __cplusplus ++#define EXTERN_C_BEGIN extern "C" { ++#define EXTERN_C_END } ++#else ++#define EXTERN_C_BEGIN ++#define EXTERN_C_END ++#endif ++#endif ++ ++EXTERN_C_BEGIN ++ ++#define SZ_OK 0 ++ ++#define SZ_ERROR_DATA 1 ++#define SZ_ERROR_MEM 2 ++#define SZ_ERROR_CRC 3 ++#define SZ_ERROR_UNSUPPORTED 4 ++#define SZ_ERROR_PARAM 5 ++#define SZ_ERROR_INPUT_EOF 6 ++#define SZ_ERROR_OUTPUT_EOF 7 ++#define SZ_ERROR_READ 8 ++#define SZ_ERROR_WRITE 9 ++#define SZ_ERROR_PROGRESS 10 ++#define SZ_ERROR_FAIL 11 ++#define SZ_ERROR_THREAD 12 ++ ++#define SZ_ERROR_ARCHIVE 16 ++#define SZ_ERROR_NO_ARCHIVE 17 ++ ++typedef int SRes; ++ ++#ifdef _WIN32 ++typedef DWORD WRes; ++#else ++typedef int WRes; ++#endif ++ ++#ifndef RINOK ++#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } ++#endif ++ ++typedef unsigned char Byte; ++typedef short Int16; ++typedef unsigned short UInt16; ++ ++#ifdef _LZMA_UINT32_IS_ULONG ++typedef long Int32; ++typedef unsigned long UInt32; ++#else ++typedef int Int32; ++typedef unsigned int UInt32; ++#endif ++ ++#ifdef _SZ_NO_INT_64 ++ ++/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. ++ NOTES: Some code will work incorrectly in that case! */ ++ ++typedef long Int64; ++typedef unsigned long UInt64; ++ ++#else ++ ++#if defined(_MSC_VER) || defined(__BORLANDC__) ++typedef __int64 Int64; ++typedef unsigned __int64 UInt64; ++#else ++typedef long long int Int64; ++typedef unsigned long long int UInt64; ++#endif ++ ++#endif ++ ++#ifdef _LZMA_NO_SYSTEM_SIZE_T ++typedef UInt32 SizeT; ++#else ++typedef size_t SizeT; ++#endif ++ ++typedef int Bool; ++#define True 1 ++#define False 0 ++ ++ ++#ifdef _WIN32 ++#define MY_STD_CALL __stdcall ++#else ++#define MY_STD_CALL ++#endif ++ ++#ifdef _MSC_VER ++ ++#if _MSC_VER >= 1300 ++#define MY_NO_INLINE __declspec(noinline) ++#else ++#define MY_NO_INLINE ++#endif ++ ++#define MY_CDECL __cdecl ++#define MY_FAST_CALL __fastcall ++ ++#else ++ ++#define MY_CDECL ++#define MY_FAST_CALL ++ ++#endif ++ ++ ++/* The following interfaces use first parameter as pointer to structure */ ++ ++typedef struct ++{ ++ SRes (*Read)(void *p, void *buf, size_t *size); ++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. ++ (output(*size) < input(*size)) is allowed */ ++} ISeqInStream; ++ ++/* it can return SZ_ERROR_INPUT_EOF */ ++SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); ++SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); ++SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); ++ ++typedef struct ++{ ++ size_t (*Write)(void *p, const void *buf, size_t size); ++ /* Returns: result - the number of actually written bytes. ++ (result < size) means error */ ++} ISeqOutStream; ++ ++typedef enum ++{ ++ SZ_SEEK_SET = 0, ++ SZ_SEEK_CUR = 1, ++ SZ_SEEK_END = 2 ++} ESzSeek; ++ ++typedef struct ++{ ++ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ ++ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); ++} ISeekInStream; ++ ++typedef struct ++{ ++ SRes (*Look)(void *p, void **buf, size_t *size); ++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. ++ (output(*size) > input(*size)) is not allowed ++ (output(*size) < input(*size)) is allowed */ ++ SRes (*Skip)(void *p, size_t offset); ++ /* offset must be <= output(*size) of Look */ ++ ++ SRes (*Read)(void *p, void *buf, size_t *size); ++ /* reads directly (without buffer). It's same as ISeqInStream::Read */ ++ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); ++} ILookInStream; ++ ++SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); ++SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); ++ ++/* reads via ILookInStream::Read */ ++SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); ++SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); ++ ++#define LookToRead_BUF_SIZE (1 << 14) ++ ++typedef struct ++{ ++ ILookInStream s; ++ ISeekInStream *realStream; ++ size_t pos; ++ size_t size; ++ Byte buf[LookToRead_BUF_SIZE]; ++} CLookToRead; ++ ++void LookToRead_CreateVTable(CLookToRead *p, int lookahead); ++void LookToRead_Init(CLookToRead *p); ++ ++typedef struct ++{ ++ ISeqInStream s; ++ ILookInStream *realStream; ++} CSecToLook; ++ ++void SecToLook_CreateVTable(CSecToLook *p); ++ ++typedef struct ++{ ++ ISeqInStream s; ++ ILookInStream *realStream; ++} CSecToRead; ++ ++void SecToRead_CreateVTable(CSecToRead *p); ++ ++typedef struct ++{ ++ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); ++ /* Returns: result. (result != SZ_OK) means break. ++ Value (UInt64)(Int64)-1 for size means unknown value. */ ++} ICompressProgress; ++ ++typedef struct ++{ ++ void *(*Alloc)(void *p, size_t size); ++ void (*Free)(void *p, void *address); /* address can be 0 */ ++} ISzAlloc; ++ ++#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) ++#define IAlloc_Free(p, a) (p)->Free((p), a) ++ ++EXTERN_C_END ++ ++#endif +--- a/include/uapi/linux/jffs2.h ++++ b/include/uapi/linux/jffs2.h +@@ -46,6 +46,7 @@ + #define JFFS2_COMPR_DYNRUBIN 0x05 + #define JFFS2_COMPR_ZLIB 0x06 + #define JFFS2_COMPR_LZO 0x07 ++#define JFFS2_COMPR_LZMA 0x08 + /* Compatibility flags. */ + #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ + #define JFFS2_NODE_ACCURATE 0x2000 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -315,6 +315,12 @@ config ZSTD_DECOMPRESS + + source "lib/xz/Kconfig" + ++config LZMA_COMPRESS ++ tristate ++ ++config LZMA_DECOMPRESS ++ tristate ++ + # + # These all provide a common interface (hence the apparent duplication with + # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -136,6 +136,16 @@ CFLAGS_kobject.o += -DDEBUG + CFLAGS_kobject_uevent.o += -DDEBUG + endif + ++ifdef CONFIG_JFFS2_ZLIB ++ CONFIG_ZLIB_INFLATE:=y ++ CONFIG_ZLIB_DEFLATE:=y ++endif ++ ++ifdef CONFIG_JFFS2_LZMA ++ CONFIG_LZMA_DECOMPRESS:=y ++ CONFIG_LZMA_COMPRESS:=y ++endif ++ + obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o + CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any) + +@@ -191,6 +201,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ + obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/ + obj-$(CONFIG_XZ_DEC) += xz/ + obj-$(CONFIG_RAID6_PQ) += raid6/ ++obj-$(CONFIG_LZMA_COMPRESS) += lzma/ ++obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/ + + lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o + lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o +--- /dev/null ++++ b/lib/lzma/LzFind.c +@@ -0,0 +1,761 @@ ++/* LzFind.c -- Match finder for LZ algorithms ++2009-04-22 : Igor Pavlov : Public domain */ ++ ++#include ++ ++#include "LzFind.h" ++#include "LzHash.h" ++ ++#define kEmptyHashValue 0 ++#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) ++#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ ++#define kNormalizeMask (~(kNormalizeStepMin - 1)) ++#define kMaxHistorySize ((UInt32)3 << 30) ++ ++#define kStartMaxLen 3 ++ ++static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ if (!p->directInput) ++ { ++ alloc->Free(alloc, p->bufferBase); ++ p->bufferBase = 0; ++ } ++} ++ ++/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ ++ ++static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) ++{ ++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; ++ if (p->directInput) ++ { ++ p->blockSize = blockSize; ++ return 1; ++ } ++ if (p->bufferBase == 0 || p->blockSize != blockSize) ++ { ++ LzInWindow_Free(p, alloc); ++ p->blockSize = blockSize; ++ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); ++ } ++ return (p->bufferBase != 0); ++} ++ ++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } ++Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } ++ ++UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } ++ ++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) ++{ ++ p->posLimit -= subValue; ++ p->pos -= subValue; ++ p->streamPos -= subValue; ++} ++ ++static void MatchFinder_ReadBlock(CMatchFinder *p) ++{ ++ if (p->streamEndWasReached || p->result != SZ_OK) ++ return; ++ if (p->directInput) ++ { ++ UInt32 curSize = 0xFFFFFFFF - p->streamPos; ++ if (curSize > p->directInputRem) ++ curSize = (UInt32)p->directInputRem; ++ p->directInputRem -= curSize; ++ p->streamPos += curSize; ++ if (p->directInputRem == 0) ++ p->streamEndWasReached = 1; ++ return; ++ } ++ for (;;) ++ { ++ Byte *dest = p->buffer + (p->streamPos - p->pos); ++ size_t size = (p->bufferBase + p->blockSize - dest); ++ if (size == 0) ++ return; ++ p->result = p->stream->Read(p->stream, dest, &size); ++ if (p->result != SZ_OK) ++ return; ++ if (size == 0) ++ { ++ p->streamEndWasReached = 1; ++ return; ++ } ++ p->streamPos += (UInt32)size; ++ if (p->streamPos - p->pos > p->keepSizeAfter) ++ return; ++ } ++} ++ ++void MatchFinder_MoveBlock(CMatchFinder *p) ++{ ++ memmove(p->bufferBase, ++ p->buffer - p->keepSizeBefore, ++ (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); ++ p->buffer = p->bufferBase + p->keepSizeBefore; ++} ++ ++int MatchFinder_NeedMove(CMatchFinder *p) ++{ ++ if (p->directInput) ++ return 0; ++ /* if (p->streamEndWasReached) return 0; */ ++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); ++} ++ ++void MatchFinder_ReadIfRequired(CMatchFinder *p) ++{ ++ if (p->streamEndWasReached) ++ return; ++ if (p->keepSizeAfter >= p->streamPos - p->pos) ++ MatchFinder_ReadBlock(p); ++} ++ ++static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) ++{ ++ if (MatchFinder_NeedMove(p)) ++ MatchFinder_MoveBlock(p); ++ MatchFinder_ReadBlock(p); ++} ++ ++static void MatchFinder_SetDefaultSettings(CMatchFinder *p) ++{ ++ p->cutValue = 32; ++ p->btMode = 1; ++ p->numHashBytes = 4; ++ p->bigHash = 0; ++} ++ ++#define kCrcPoly 0xEDB88320 ++ ++void MatchFinder_Construct(CMatchFinder *p) ++{ ++ UInt32 i; ++ p->bufferBase = 0; ++ p->directInput = 0; ++ p->hash = 0; ++ MatchFinder_SetDefaultSettings(p); ++ ++ for (i = 0; i < 256; i++) ++ { ++ UInt32 r = i; ++ int j; ++ for (j = 0; j < 8; j++) ++ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); ++ p->crc[i] = r; ++ } ++} ++ ++static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->hash); ++ p->hash = 0; ++} ++ ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ MatchFinder_FreeThisClassMemory(p, alloc); ++ LzInWindow_Free(p, alloc); ++} ++ ++static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) ++{ ++ size_t sizeInBytes = (size_t)num * sizeof(CLzRef); ++ if (sizeInBytes / sizeof(CLzRef) != num) ++ return 0; ++ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); ++} ++ ++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc) ++{ ++ UInt32 sizeReserv; ++ if (historySize > kMaxHistorySize) ++ { ++ MatchFinder_Free(p, alloc); ++ return 0; ++ } ++ sizeReserv = historySize >> 1; ++ if (historySize > ((UInt32)2 << 30)) ++ sizeReserv = historySize >> 2; ++ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); ++ ++ p->keepSizeBefore = historySize + keepAddBufferBefore + 1; ++ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; ++ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ ++ if (LzInWindow_Create(p, sizeReserv, alloc)) ++ { ++ UInt32 newCyclicBufferSize = historySize + 1; ++ UInt32 hs; ++ p->matchMaxLen = matchMaxLen; ++ { ++ p->fixedHashSize = 0; ++ if (p->numHashBytes == 2) ++ hs = (1 << 16) - 1; ++ else ++ { ++ hs = historySize - 1; ++ hs |= (hs >> 1); ++ hs |= (hs >> 2); ++ hs |= (hs >> 4); ++ hs |= (hs >> 8); ++ hs >>= 1; ++ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ ++ if (hs > (1 << 24)) ++ { ++ if (p->numHashBytes == 3) ++ hs = (1 << 24) - 1; ++ else ++ hs >>= 1; ++ } ++ } ++ p->hashMask = hs; ++ hs++; ++ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; ++ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; ++ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; ++ hs += p->fixedHashSize; ++ } ++ ++ { ++ UInt32 prevSize = p->hashSizeSum + p->numSons; ++ UInt32 newSize; ++ p->historySize = historySize; ++ p->hashSizeSum = hs; ++ p->cyclicBufferSize = newCyclicBufferSize; ++ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); ++ newSize = p->hashSizeSum + p->numSons; ++ if (p->hash != 0 && prevSize == newSize) ++ return 1; ++ MatchFinder_FreeThisClassMemory(p, alloc); ++ p->hash = AllocRefs(newSize, alloc); ++ if (p->hash != 0) ++ { ++ p->son = p->hash + p->hashSizeSum; ++ return 1; ++ } ++ } ++ } ++ MatchFinder_Free(p, alloc); ++ return 0; ++} ++ ++static void MatchFinder_SetLimits(CMatchFinder *p) ++{ ++ UInt32 limit = kMaxValForNormalize - p->pos; ++ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; ++ if (limit2 < limit) ++ limit = limit2; ++ limit2 = p->streamPos - p->pos; ++ if (limit2 <= p->keepSizeAfter) ++ { ++ if (limit2 > 0) ++ limit2 = 1; ++ } ++ else ++ limit2 -= p->keepSizeAfter; ++ if (limit2 < limit) ++ limit = limit2; ++ { ++ UInt32 lenLimit = p->streamPos - p->pos; ++ if (lenLimit > p->matchMaxLen) ++ lenLimit = p->matchMaxLen; ++ p->lenLimit = lenLimit; ++ } ++ p->posLimit = p->pos + limit; ++} ++ ++void MatchFinder_Init(CMatchFinder *p) ++{ ++ UInt32 i; ++ for (i = 0; i < p->hashSizeSum; i++) ++ p->hash[i] = kEmptyHashValue; ++ p->cyclicBufferPos = 0; ++ p->buffer = p->bufferBase; ++ p->pos = p->streamPos = p->cyclicBufferSize; ++ p->result = SZ_OK; ++ p->streamEndWasReached = 0; ++ MatchFinder_ReadBlock(p); ++ MatchFinder_SetLimits(p); ++} ++ ++static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) ++{ ++ return (p->pos - p->historySize - 1) & kNormalizeMask; ++} ++ ++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) ++{ ++ UInt32 i; ++ for (i = 0; i < numItems; i++) ++ { ++ UInt32 value = items[i]; ++ if (value <= subValue) ++ value = kEmptyHashValue; ++ else ++ value -= subValue; ++ items[i] = value; ++ } ++} ++ ++static void MatchFinder_Normalize(CMatchFinder *p) ++{ ++ UInt32 subValue = MatchFinder_GetSubValue(p); ++ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); ++ MatchFinder_ReduceOffsets(p, subValue); ++} ++ ++static void MatchFinder_CheckLimits(CMatchFinder *p) ++{ ++ if (p->pos == kMaxValForNormalize) ++ MatchFinder_Normalize(p); ++ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) ++ MatchFinder_CheckAndMoveAndRead(p); ++ if (p->cyclicBufferPos == p->cyclicBufferSize) ++ p->cyclicBufferPos = 0; ++ MatchFinder_SetLimits(p); ++} ++ ++static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ ++ son[_cyclicBufferPos] = curMatch; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ return distances; ++ { ++ const Byte *pb = cur - delta; ++ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; ++ if (pb[maxLen] == cur[maxLen] && *pb == *cur) ++ { ++ UInt32 len = 0; ++ while (++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ if (maxLen < len) ++ { ++ *distances++ = maxLen = len; ++ *distances++ = delta - 1; ++ if (len == lenLimit) ++ return distances; ++ } ++ } ++ } ++ } ++} ++ ++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ ++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; ++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); ++ UInt32 len0 = 0, len1 = 0; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ { ++ *ptr0 = *ptr1 = kEmptyHashValue; ++ return distances; ++ } ++ { ++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); ++ const Byte *pb = cur - delta; ++ UInt32 len = (len0 < len1 ? len0 : len1); ++ if (pb[len] == cur[len]) ++ { ++ if (++len != lenLimit && pb[len] == cur[len]) ++ while (++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ if (maxLen < len) ++ { ++ *distances++ = maxLen = len; ++ *distances++ = delta - 1; ++ if (len == lenLimit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return distances; ++ } ++ } ++ } ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = curMatch; ++ ptr1 = pair + 1; ++ curMatch = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = curMatch; ++ ptr0 = pair; ++ curMatch = *ptr0; ++ len0 = len; ++ } ++ } ++ } ++} ++ ++static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) ++{ ++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; ++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); ++ UInt32 len0 = 0, len1 = 0; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ { ++ *ptr0 = *ptr1 = kEmptyHashValue; ++ return; ++ } ++ { ++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); ++ const Byte *pb = cur - delta; ++ UInt32 len = (len0 < len1 ? len0 : len1); ++ if (pb[len] == cur[len]) ++ { ++ while (++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ { ++ if (len == lenLimit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return; ++ } ++ } ++ } ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = curMatch; ++ ptr1 = pair + 1; ++ curMatch = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = curMatch; ++ ptr0 = pair; ++ curMatch = *ptr0; ++ len0 = len; ++ } ++ } ++ } ++} ++ ++#define MOVE_POS \ ++ ++p->cyclicBufferPos; \ ++ p->buffer++; \ ++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); ++ ++#define MOVE_POS_RET MOVE_POS return offset; ++ ++static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } ++ ++#define GET_MATCHES_HEADER2(minLen, ret_op) \ ++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ ++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ ++ cur = p->buffer; ++ ++#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) ++#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) ++ ++#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue ++ ++#define GET_MATCHES_FOOTER(offset, maxLen) \ ++ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ ++ distances + offset, maxLen) - distances); MOVE_POS_RET; ++ ++#define SKIP_FOOTER \ ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; ++ ++static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(2) ++ HASH2_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = 0; ++ GET_MATCHES_FOOTER(offset, 1) ++} ++ ++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = 0; ++ GET_MATCHES_FOOTER(offset, 2) ++} ++ ++static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, delta2, maxLen, offset; ++ GET_MATCHES_HEADER(3) ++ ++ HASH3_CALC; ++ ++ delta2 = p->pos - p->hash[hash2Value]; ++ curMatch = p->hash[kFix3HashSize + hashValue]; ++ ++ p->hash[hash2Value] = ++ p->hash[kFix3HashSize + hashValue] = p->pos; ++ ++ ++ maxLen = 2; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[0] = maxLen; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ if (maxLen == lenLimit) ++ { ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++ MOVE_POS_RET; ++ } ++ } ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ ++static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++ GET_MATCHES_HEADER(4) ++ ++ HASH4_CALC; ++ ++ delta2 = p->pos - p->hash[ hash2Value]; ++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ ++ maxLen = 1; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ distances[0] = maxLen = 2; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ } ++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++ { ++ maxLen = 3; ++ distances[offset + 1] = delta3 - 1; ++ offset += 2; ++ delta2 = delta3; ++ } ++ if (offset != 0) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[offset - 2] = maxLen; ++ if (maxLen == lenLimit) ++ { ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++ MOVE_POS_RET; ++ } ++ } ++ if (maxLen < 3) ++ maxLen = 3; ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ ++static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++ GET_MATCHES_HEADER(4) ++ ++ HASH4_CALC; ++ ++ delta2 = p->pos - p->hash[ hash2Value]; ++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ ++ maxLen = 1; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ distances[0] = maxLen = 2; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ } ++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++ { ++ maxLen = 3; ++ distances[offset + 1] = delta3 - 1; ++ offset += 2; ++ delta2 = delta3; ++ } ++ if (offset != 0) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[offset - 2] = maxLen; ++ if (maxLen == lenLimit) ++ { ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS_RET; ++ } ++ } ++ if (maxLen < 3) ++ maxLen = 3; ++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++ distances + offset, maxLen) - (distances)); ++ MOVE_POS_RET ++} ++ ++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++ distances, 2) - (distances)); ++ MOVE_POS_RET ++} ++ ++static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(2) ++ HASH2_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value; ++ SKIP_HEADER(3) ++ HASH3_CALC; ++ curMatch = p->hash[kFix3HashSize + hashValue]; ++ p->hash[hash2Value] = ++ p->hash[kFix3HashSize + hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value, hash3Value; ++ SKIP_HEADER(4) ++ HASH4_CALC; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = p->pos; ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value, hash3Value; ++ SKIP_HEADER(4) ++ HASH4_CALC; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS ++ } ++ while (--num != 0); ++} ++ ++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS ++ } ++ while (--num != 0); ++} ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) ++{ ++ vTable->Init = (Mf_Init_Func)MatchFinder_Init; ++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; ++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; ++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; ++ if (!p->btMode) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; ++ } ++ else if (p->numHashBytes == 2) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; ++ } ++ else if (p->numHashBytes == 3) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; ++ } ++ else ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; ++ } ++} +--- /dev/null ++++ b/lib/lzma/LzmaDec.c +@@ -0,0 +1,999 @@ ++/* LzmaDec.c -- LZMA Decoder ++2009-09-20 : Igor Pavlov : Public domain */ ++ ++#include "LzmaDec.h" ++ ++#include ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++ ++#define RC_INIT_SIZE 5 ++ ++#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } ++ ++#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) ++#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); ++#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); ++#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ ++ { UPDATE_0(p); i = (i + i); A0; } else \ ++ { UPDATE_1(p); i = (i + i) + 1; A1; } ++#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) ++ ++#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } ++#define TREE_DECODE(probs, limit, i) \ ++ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } ++ ++/* #define _LZMA_SIZE_OPT */ ++ ++#ifdef _LZMA_SIZE_OPT ++#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) ++#else ++#define TREE_6_DECODE(probs, i) \ ++ { i = 1; \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ i -= 0x40; } ++#endif ++ ++#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } ++ ++#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) ++#define UPDATE_0_CHECK range = bound; ++#define UPDATE_1_CHECK range -= bound; code -= bound; ++#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ ++ { UPDATE_0_CHECK; i = (i + i); A0; } else \ ++ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } ++#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) ++#define TREE_DECODE_CHECK(probs, limit, i) \ ++ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } ++ ++ ++#define kNumPosBitsMax 4 ++#define kNumPosStatesMax (1 << kNumPosBitsMax) ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define LenChoice 0 ++#define LenChoice2 (LenChoice + 1) ++#define LenLow (LenChoice2 + 1) ++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) ++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) ++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) ++ ++ ++#define kNumStates 12 ++#define kNumLitStates 7 ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#define kNumPosSlotBits 6 ++#define kNumLenToPosStates 4 ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++ ++#define kMatchMinLen 2 ++#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) ++ ++#define IsMatch 0 ++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) ++#define IsRepG0 (IsRep + kNumStates) ++#define IsRepG1 (IsRepG0 + kNumStates) ++#define IsRepG2 (IsRepG1 + kNumStates) ++#define IsRep0Long (IsRepG2 + kNumStates) ++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) ++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) ++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) ++#define LenCoder (Align + kAlignTableSize) ++#define RepLenCoder (LenCoder + kNumLenProbs) ++#define Literal (RepLenCoder + kNumLenProbs) ++ ++#define LZMA_BASE_SIZE 1846 ++#define LZMA_LIT_SIZE 768 ++ ++#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) ++ ++#if Literal != LZMA_BASE_SIZE ++StopCompilingDueBUG ++#endif ++ ++#define LZMA_DIC_MIN (1 << 12) ++ ++/* First LZMA-symbol is always decoded. ++And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization ++Out: ++ Result: ++ SZ_OK - OK ++ SZ_ERROR_DATA - Error ++ p->remainLen: ++ < kMatchSpecLenStart : normal remain ++ = kMatchSpecLenStart : finished ++ = kMatchSpecLenStart + 1 : Flush marker ++ = kMatchSpecLenStart + 2 : State Init Marker ++*/ ++ ++static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) ++{ ++ CLzmaProb *probs = p->probs; ++ ++ unsigned state = p->state; ++ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; ++ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; ++ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; ++ unsigned lc = p->prop.lc; ++ ++ Byte *dic = p->dic; ++ SizeT dicBufSize = p->dicBufSize; ++ SizeT dicPos = p->dicPos; ++ ++ UInt32 processedPos = p->processedPos; ++ UInt32 checkDicSize = p->checkDicSize; ++ unsigned len = 0; ++ ++ const Byte *buf = p->buf; ++ UInt32 range = p->range; ++ UInt32 code = p->code; ++ ++ do ++ { ++ CLzmaProb *prob; ++ UInt32 bound; ++ unsigned ttt; ++ unsigned posState = processedPos & pbMask; ++ ++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0(prob) ++ { ++ unsigned symbol; ++ UPDATE_0(prob); ++ prob = probs + Literal; ++ if (checkDicSize != 0 || processedPos != 0) ++ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + ++ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); ++ ++ if (state < kNumLitStates) ++ { ++ state -= (state < 4) ? state : 3; ++ symbol = 1; ++ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); ++ } ++ else ++ { ++ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ unsigned offs = 0x100; ++ state -= (state < 10) ? 3 : 6; ++ symbol = 1; ++ do ++ { ++ unsigned bit; ++ CLzmaProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & offs); ++ probLit = prob + offs + bit + symbol; ++ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) ++ } ++ while (symbol < 0x100); ++ } ++ dic[dicPos++] = (Byte)symbol; ++ processedPos++; ++ continue; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ prob = probs + IsRep + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ state += kNumStates; ++ prob = probs + LenCoder; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ if (checkDicSize == 0 && processedPos == 0) ++ return SZ_ERROR_DATA; ++ prob = probs + IsRepG0 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ dicPos++; ++ processedPos++; ++ state = state < kNumLitStates ? 9 : 11; ++ continue; ++ } ++ UPDATE_1(prob); ++ } ++ else ++ { ++ UInt32 distance; ++ UPDATE_1(prob); ++ prob = probs + IsRepG1 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ distance = rep1; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ prob = probs + IsRepG2 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ distance = rep2; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ distance = rep3; ++ rep3 = rep2; ++ } ++ rep2 = rep1; ++ } ++ rep1 = rep0; ++ rep0 = distance; ++ } ++ state = state < kNumLitStates ? 8 : 11; ++ prob = probs + RepLenCoder; ++ } ++ { ++ unsigned limit, offset; ++ CLzmaProb *probLen = prob + LenChoice; ++ IF_BIT_0(probLen) ++ { ++ UPDATE_0(probLen); ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ limit = (1 << kLenNumLowBits); ++ } ++ else ++ { ++ UPDATE_1(probLen); ++ probLen = prob + LenChoice2; ++ IF_BIT_0(probLen) ++ { ++ UPDATE_0(probLen); ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ limit = (1 << kLenNumMidBits); ++ } ++ else ++ { ++ UPDATE_1(probLen); ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ limit = (1 << kLenNumHighBits); ++ } ++ } ++ TREE_DECODE(probLen, limit, len); ++ len += offset; ++ } ++ ++ if (state >= kNumStates) ++ { ++ UInt32 distance; ++ prob = probs + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); ++ TREE_6_DECODE(prob, distance); ++ if (distance >= kStartPosModelIndex) ++ { ++ unsigned posSlot = (unsigned)distance; ++ int numDirectBits = (int)(((distance >> 1) - 1)); ++ distance = (2 | (distance & 1)); ++ if (posSlot < kEndPosModelIndex) ++ { ++ distance <<= numDirectBits; ++ prob = probs + SpecPos + distance - posSlot - 1; ++ { ++ UInt32 mask = 1; ++ unsigned i = 1; ++ do ++ { ++ GET_BIT2(prob + i, i, ; , distance |= mask); ++ mask <<= 1; ++ } ++ while (--numDirectBits != 0); ++ } ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ NORMALIZE ++ range >>= 1; ++ ++ { ++ UInt32 t; ++ code -= range; ++ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ ++ distance = (distance << 1) + (t + 1); ++ code += range & t; ++ } ++ /* ++ distance <<= 1; ++ if (code >= range) ++ { ++ code -= range; ++ distance |= 1; ++ } ++ */ ++ } ++ while (--numDirectBits != 0); ++ prob = probs + Align; ++ distance <<= kNumAlignBits; ++ { ++ unsigned i = 1; ++ GET_BIT2(prob + i, i, ; , distance |= 1); ++ GET_BIT2(prob + i, i, ; , distance |= 2); ++ GET_BIT2(prob + i, i, ; , distance |= 4); ++ GET_BIT2(prob + i, i, ; , distance |= 8); ++ } ++ if (distance == (UInt32)0xFFFFFFFF) ++ { ++ len += kMatchSpecLenStart; ++ state -= kNumStates; ++ break; ++ } ++ } ++ } ++ rep3 = rep2; ++ rep2 = rep1; ++ rep1 = rep0; ++ rep0 = distance + 1; ++ if (checkDicSize == 0) ++ { ++ if (distance >= processedPos) ++ return SZ_ERROR_DATA; ++ } ++ else if (distance >= checkDicSize) ++ return SZ_ERROR_DATA; ++ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; ++ } ++ ++ len += kMatchMinLen; ++ ++ if (limit == dicPos) ++ return SZ_ERROR_DATA; ++ { ++ SizeT rem = limit - dicPos; ++ unsigned curLen = ((rem < len) ? (unsigned)rem : len); ++ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); ++ ++ processedPos += curLen; ++ ++ len -= curLen; ++ if (pos + curLen <= dicBufSize) ++ { ++ Byte *dest = dic + dicPos; ++ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; ++ const Byte *lim = dest + curLen; ++ dicPos += curLen; ++ do ++ *(dest) = (Byte)*(dest + src); ++ while (++dest != lim); ++ } ++ else ++ { ++ do ++ { ++ dic[dicPos++] = dic[pos]; ++ if (++pos == dicBufSize) ++ pos = 0; ++ } ++ while (--curLen != 0); ++ } ++ } ++ } ++ } ++ while (dicPos < limit && buf < bufLimit); ++ NORMALIZE; ++ p->buf = buf; ++ p->range = range; ++ p->code = code; ++ p->remainLen = len; ++ p->dicPos = dicPos; ++ p->processedPos = processedPos; ++ p->reps[0] = rep0; ++ p->reps[1] = rep1; ++ p->reps[2] = rep2; ++ p->reps[3] = rep3; ++ p->state = state; ++ ++ return SZ_OK; ++} ++ ++static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) ++{ ++ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) ++ { ++ Byte *dic = p->dic; ++ SizeT dicPos = p->dicPos; ++ SizeT dicBufSize = p->dicBufSize; ++ unsigned len = p->remainLen; ++ UInt32 rep0 = p->reps[0]; ++ if (limit - dicPos < len) ++ len = (unsigned)(limit - dicPos); ++ ++ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) ++ p->checkDicSize = p->prop.dicSize; ++ ++ p->processedPos += len; ++ p->remainLen -= len; ++ while (len-- != 0) ++ { ++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ dicPos++; ++ } ++ p->dicPos = dicPos; ++ } ++} ++ ++static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) ++{ ++ do ++ { ++ SizeT limit2 = limit; ++ if (p->checkDicSize == 0) ++ { ++ UInt32 rem = p->prop.dicSize - p->processedPos; ++ if (limit - p->dicPos > rem) ++ limit2 = p->dicPos + rem; ++ } ++ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); ++ if (p->processedPos >= p->prop.dicSize) ++ p->checkDicSize = p->prop.dicSize; ++ LzmaDec_WriteRem(p, limit); ++ } ++ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); ++ ++ if (p->remainLen > kMatchSpecLenStart) ++ { ++ p->remainLen = kMatchSpecLenStart; ++ } ++ return 0; ++} ++ ++typedef enum ++{ ++ DUMMY_ERROR, /* unexpected end of input stream */ ++ DUMMY_LIT, ++ DUMMY_MATCH, ++ DUMMY_REP ++} ELzmaDummy; ++ ++static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) ++{ ++ UInt32 range = p->range; ++ UInt32 code = p->code; ++ const Byte *bufLimit = buf + inSize; ++ CLzmaProb *probs = p->probs; ++ unsigned state = p->state; ++ ELzmaDummy res; ++ ++ { ++ CLzmaProb *prob; ++ UInt32 bound; ++ unsigned ttt; ++ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); ++ ++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK ++ ++ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ ++ ++ prob = probs + Literal; ++ if (p->checkDicSize != 0 || p->processedPos != 0) ++ prob += (LZMA_LIT_SIZE * ++ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + ++ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); ++ ++ if (state < kNumLitStates) ++ { ++ unsigned symbol = 1; ++ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); ++ } ++ else ++ { ++ unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ++ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; ++ unsigned offs = 0x100; ++ unsigned symbol = 1; ++ do ++ { ++ unsigned bit; ++ CLzmaProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & offs); ++ probLit = prob + offs + bit + symbol; ++ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) ++ } ++ while (symbol < 0x100); ++ } ++ res = DUMMY_LIT; ++ } ++ else ++ { ++ unsigned len; ++ UPDATE_1_CHECK; ++ ++ prob = probs + IsRep + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ state = 0; ++ prob = probs + LenCoder; ++ res = DUMMY_MATCH; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ res = DUMMY_REP; ++ prob = probs + IsRepG0 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ NORMALIZE_CHECK; ++ return DUMMY_REP; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ } ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ prob = probs + IsRepG1 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ prob = probs + IsRepG2 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ } ++ } ++ } ++ state = kNumStates; ++ prob = probs + RepLenCoder; ++ } ++ { ++ unsigned limit, offset; ++ CLzmaProb *probLen = prob + LenChoice; ++ IF_BIT_0_CHECK(probLen) ++ { ++ UPDATE_0_CHECK; ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ limit = 1 << kLenNumLowBits; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ probLen = prob + LenChoice2; ++ IF_BIT_0_CHECK(probLen) ++ { ++ UPDATE_0_CHECK; ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ limit = 1 << kLenNumMidBits; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ limit = 1 << kLenNumHighBits; ++ } ++ } ++ TREE_DECODE_CHECK(probLen, limit, len); ++ len += offset; ++ } ++ ++ if (state < 4) ++ { ++ unsigned posSlot; ++ prob = probs + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << ++ kNumPosSlotBits); ++ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); ++ if (posSlot >= kStartPosModelIndex) ++ { ++ int numDirectBits = ((posSlot >> 1) - 1); ++ ++ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ ++ ++ if (posSlot < kEndPosModelIndex) ++ { ++ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ NORMALIZE_CHECK ++ range >>= 1; ++ code -= range & (((code - range) >> 31) - 1); ++ /* if (code >= range) code -= range; */ ++ } ++ while (--numDirectBits != 0); ++ prob = probs + Align; ++ numDirectBits = kNumAlignBits; ++ } ++ { ++ unsigned i = 1; ++ do ++ { ++ GET_BIT_CHECK(prob + i, i); ++ } ++ while (--numDirectBits != 0); ++ } ++ } ++ } ++ } ++ } ++ NORMALIZE_CHECK; ++ return res; ++} ++ ++ ++static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) ++{ ++ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); ++ p->range = 0xFFFFFFFF; ++ p->needFlush = 0; ++} ++ ++void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) ++{ ++ p->needFlush = 1; ++ p->remainLen = 0; ++ p->tempBufSize = 0; ++ ++ if (initDic) ++ { ++ p->processedPos = 0; ++ p->checkDicSize = 0; ++ p->needInitState = 1; ++ } ++ if (initState) ++ p->needInitState = 1; ++} ++ ++void LzmaDec_Init(CLzmaDec *p) ++{ ++ p->dicPos = 0; ++ LzmaDec_InitDicAndState(p, True, True); ++} ++ ++static void LzmaDec_InitStateReal(CLzmaDec *p) ++{ ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); ++ UInt32 i; ++ CLzmaProb *probs = p->probs; ++ for (i = 0; i < numProbs; i++) ++ probs[i] = kBitModelTotal >> 1; ++ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; ++ p->state = 0; ++ p->needInitState = 0; ++} ++ ++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ++ ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT inSize = *srcLen; ++ (*srcLen) = 0; ++ LzmaDec_WriteRem(p, dicLimit); ++ ++ *status = LZMA_STATUS_NOT_SPECIFIED; ++ ++ while (p->remainLen != kMatchSpecLenStart) ++ { ++ int checkEndMarkNow; ++ ++ if (p->needFlush != 0) ++ { ++ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) ++ p->tempBuf[p->tempBufSize++] = *src++; ++ if (p->tempBufSize < RC_INIT_SIZE) ++ { ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (p->tempBuf[0] != 0) ++ return SZ_ERROR_DATA; ++ ++ LzmaDec_InitRc(p, p->tempBuf); ++ p->tempBufSize = 0; ++ } ++ ++ checkEndMarkNow = 0; ++ if (p->dicPos >= dicLimit) ++ { ++ if (p->remainLen == 0 && p->code == 0) ++ { ++ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; ++ return SZ_OK; ++ } ++ if (finishMode == LZMA_FINISH_ANY) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_OK; ++ } ++ if (p->remainLen != 0) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ checkEndMarkNow = 1; ++ } ++ ++ if (p->needInitState) ++ LzmaDec_InitStateReal(p); ++ ++ if (p->tempBufSize == 0) ++ { ++ SizeT processed; ++ const Byte *bufLimit; ++ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) ++ { ++ int dummyRes = LzmaDec_TryDummy(p, src, inSize); ++ if (dummyRes == DUMMY_ERROR) ++ { ++ memcpy(p->tempBuf, src, inSize); ++ p->tempBufSize = (unsigned)inSize; ++ (*srcLen) += inSize; ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ bufLimit = src; ++ } ++ else ++ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; ++ p->buf = src; ++ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) ++ return SZ_ERROR_DATA; ++ processed = (SizeT)(p->buf - src); ++ (*srcLen) += processed; ++ src += processed; ++ inSize -= processed; ++ } ++ else ++ { ++ unsigned rem = p->tempBufSize, lookAhead = 0; ++ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) ++ p->tempBuf[rem++] = src[lookAhead++]; ++ p->tempBufSize = rem; ++ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) ++ { ++ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); ++ if (dummyRes == DUMMY_ERROR) ++ { ++ (*srcLen) += lookAhead; ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ } ++ p->buf = p->tempBuf; ++ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) ++ return SZ_ERROR_DATA; ++ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); ++ (*srcLen) += lookAhead; ++ src += lookAhead; ++ inSize -= lookAhead; ++ p->tempBufSize = 0; ++ } ++ } ++ if (p->code == 0) ++ *status = LZMA_STATUS_FINISHED_WITH_MARK; ++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; ++} ++ ++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT outSize = *destLen; ++ SizeT inSize = *srcLen; ++ *srcLen = *destLen = 0; ++ for (;;) ++ { ++ SizeT inSizeCur = inSize, outSizeCur, dicPos; ++ ELzmaFinishMode curFinishMode; ++ SRes res; ++ if (p->dicPos == p->dicBufSize) ++ p->dicPos = 0; ++ dicPos = p->dicPos; ++ if (outSize > p->dicBufSize - dicPos) ++ { ++ outSizeCur = p->dicBufSize; ++ curFinishMode = LZMA_FINISH_ANY; ++ } ++ else ++ { ++ outSizeCur = dicPos + outSize; ++ curFinishMode = finishMode; ++ } ++ ++ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); ++ src += inSizeCur; ++ inSize -= inSizeCur; ++ *srcLen += inSizeCur; ++ outSizeCur = p->dicPos - dicPos; ++ memcpy(dest, p->dic + dicPos, outSizeCur); ++ dest += outSizeCur; ++ outSize -= outSizeCur; ++ *destLen += outSizeCur; ++ if (res != 0) ++ return res; ++ if (outSizeCur == 0 || outSize == 0) ++ return SZ_OK; ++ } ++} ++ ++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->probs); ++ p->probs = 0; ++} ++ ++static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->dic); ++ p->dic = 0; ++} ++ ++void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ LzmaDec_FreeProbs(p, alloc); ++ LzmaDec_FreeDict(p, alloc); ++} ++ ++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) ++{ ++ UInt32 dicSize; ++ Byte d; ++ ++ if (size < LZMA_PROPS_SIZE) ++ return SZ_ERROR_UNSUPPORTED; ++ else ++ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); ++ ++ if (dicSize < LZMA_DIC_MIN) ++ dicSize = LZMA_DIC_MIN; ++ p->dicSize = dicSize; ++ ++ d = data[0]; ++ if (d >= (9 * 5 * 5)) ++ return SZ_ERROR_UNSUPPORTED; ++ ++ p->lc = d % 9; ++ d /= 9; ++ p->pb = d / 5; ++ p->lp = d % 5; ++ ++ return SZ_OK; ++} ++ ++static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) ++{ ++ UInt32 numProbs = LzmaProps_GetNumProbs(propNew); ++ if (p->probs == 0 || numProbs != p->numProbs) ++ { ++ LzmaDec_FreeProbs(p, alloc); ++ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); ++ p->numProbs = numProbs; ++ if (p->probs == 0) ++ return SZ_ERROR_MEM; ++ } ++ return SZ_OK; ++} ++ ++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++ p->prop = propNew; ++ return SZ_OK; ++} ++ ++SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; ++ SizeT dicBufSize; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++ dicBufSize = propNew.dicSize; ++ if (p->dic == 0 || dicBufSize != p->dicBufSize) ++ { ++ LzmaDec_FreeDict(p, alloc); ++ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); ++ if (p->dic == 0) ++ { ++ LzmaDec_FreeProbs(p, alloc); ++ return SZ_ERROR_MEM; ++ } ++ } ++ p->dicBufSize = dicBufSize; ++ p->prop = propNew; ++ return SZ_OK; ++} ++ ++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++ ELzmaStatus *status, ISzAlloc *alloc) ++{ ++ CLzmaDec p; ++ SRes res; ++ SizeT inSize = *srcLen; ++ SizeT outSize = *destLen; ++ *srcLen = *destLen = 0; ++ if (inSize < RC_INIT_SIZE) ++ return SZ_ERROR_INPUT_EOF; ++ ++ LzmaDec_Construct(&p); ++ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); ++ if (res != 0) ++ return res; ++ p.dic = dest; ++ p.dicBufSize = outSize; ++ ++ LzmaDec_Init(&p); ++ ++ *srcLen = inSize; ++ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); ++ ++ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) ++ res = SZ_ERROR_INPUT_EOF; ++ ++ (*destLen) = p.dicPos; ++ LzmaDec_FreeProbs(&p, alloc); ++ return res; ++} +--- /dev/null ++++ b/lib/lzma/LzmaEnc.c +@@ -0,0 +1,2271 @@ ++/* LzmaEnc.c -- LZMA Encoder ++2009-11-24 : Igor Pavlov : Public domain */ ++ ++#include ++ ++/* #define SHOW_STAT */ ++/* #define SHOW_STAT2 */ ++ ++#if defined(SHOW_STAT) || defined(SHOW_STAT2) ++#include ++#endif ++ ++#include "LzmaEnc.h" ++ ++/* disable MT */ ++#define _7ZIP_ST ++ ++#include "LzFind.h" ++#ifndef _7ZIP_ST ++#include "LzFindMt.h" ++#endif ++ ++#ifdef SHOW_STAT ++static int ttt = 0; ++#endif ++ ++#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) ++ ++#define kBlockSize (9 << 10) ++#define kUnpackBlockSize (1 << 18) ++#define kMatchArraySize (1 << 21) ++#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) ++ ++#define kNumMaxDirectBits (31) ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++#define kProbInitValue (kBitModelTotal >> 1) ++ ++#define kNumMoveReducingBits 4 ++#define kNumBitPriceShiftBits 4 ++#define kBitPrice (1 << kNumBitPriceShiftBits) ++ ++void LzmaEncProps_Init(CLzmaEncProps *p) ++{ ++ p->level = 5; ++ p->dictSize = p->mc = 0; ++ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; ++ p->writeEndMark = 0; ++} ++ ++void LzmaEncProps_Normalize(CLzmaEncProps *p) ++{ ++ int level = p->level; ++ if (level < 0) level = 5; ++ p->level = level; ++ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); ++ if (p->lc < 0) p->lc = 3; ++ if (p->lp < 0) p->lp = 0; ++ if (p->pb < 0) p->pb = 2; ++ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); ++ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); ++ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); ++ if (p->numHashBytes < 0) p->numHashBytes = 4; ++ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); ++ if (p->numThreads < 0) ++ p->numThreads = ++ #ifndef _7ZIP_ST ++ ((p->btMode && p->algo) ? 2 : 1); ++ #else ++ 1; ++ #endif ++} ++ ++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) ++{ ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++ return props.dictSize; ++} ++ ++/* #define LZMA_LOG_BSR */ ++/* Define it for Intel's CPU */ ++ ++ ++#ifdef LZMA_LOG_BSR ++ ++#define kDicLogSizeMaxCompress 30 ++ ++#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } ++ ++UInt32 GetPosSlot1(UInt32 pos) ++{ ++ UInt32 res; ++ BSR2_RET(pos, res); ++ return res; ++} ++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } ++#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } ++ ++#else ++ ++#define kNumLogBits (9 + (int)sizeof(size_t) / 2) ++#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) ++ ++void LzmaEnc_FastPosInit(Byte *g_FastPos) ++{ ++ int c = 2, slotFast; ++ g_FastPos[0] = 0; ++ g_FastPos[1] = 1; ++ ++ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) ++ { ++ UInt32 k = (1 << ((slotFast >> 1) - 1)); ++ UInt32 j; ++ for (j = 0; j < k; j++, c++) ++ g_FastPos[c] = (Byte)slotFast; ++ } ++} ++ ++#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ ++ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ ++ res = p->g_FastPos[pos >> i] + (i * 2); } ++/* ++#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ ++ p->g_FastPos[pos >> 6] + 12 : \ ++ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } ++*/ ++ ++#define GetPosSlot1(pos) p->g_FastPos[pos] ++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } ++#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } ++ ++#endif ++ ++ ++#define LZMA_NUM_REPS 4 ++ ++typedef unsigned CState; ++ ++typedef struct ++{ ++ UInt32 price; ++ ++ CState state; ++ int prev1IsChar; ++ int prev2; ++ ++ UInt32 posPrev2; ++ UInt32 backPrev2; ++ ++ UInt32 posPrev; ++ UInt32 backPrev; ++ UInt32 backs[LZMA_NUM_REPS]; ++} COptimal; ++ ++#define kNumOpts (1 << 12) ++ ++#define kNumLenToPosStates 4 ++#define kNumPosSlotBits 6 ++#define kDicLogSizeMin 0 ++#define kDicLogSizeMax 32 ++#define kDistTableSizeMax (kDicLogSizeMax * 2) ++ ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++#define kAlignMask (kAlignTableSize - 1) ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) ++ ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#ifdef _LZMA_PROB32 ++#define CLzmaProb UInt32 ++#else ++#define CLzmaProb UInt16 ++#endif ++ ++#define LZMA_PB_MAX 4 ++#define LZMA_LC_MAX 8 ++#define LZMA_LP_MAX 4 ++ ++#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) ++ ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) ++ ++#define LZMA_MATCH_LEN_MIN 2 ++#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) ++ ++#define kNumStates 12 ++ ++typedef struct ++{ ++ CLzmaProb choice; ++ CLzmaProb choice2; ++ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; ++ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; ++ CLzmaProb high[kLenNumHighSymbols]; ++} CLenEnc; ++ ++typedef struct ++{ ++ CLenEnc p; ++ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; ++ UInt32 tableSize; ++ UInt32 counters[LZMA_NUM_PB_STATES_MAX]; ++} CLenPriceEnc; ++ ++typedef struct ++{ ++ UInt32 range; ++ Byte cache; ++ UInt64 low; ++ UInt64 cacheSize; ++ Byte *buf; ++ Byte *bufLim; ++ Byte *bufBase; ++ ISeqOutStream *outStream; ++ UInt64 processed; ++ SRes res; ++} CRangeEnc; ++ ++typedef struct ++{ ++ CLzmaProb *litProbs; ++ ++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ CLzmaProb isRep[kNumStates]; ++ CLzmaProb isRepG0[kNumStates]; ++ CLzmaProb isRepG1[kNumStates]; ++ CLzmaProb isRepG2[kNumStates]; ++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ ++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; ++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; ++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; ++ ++ CLenPriceEnc lenEnc; ++ CLenPriceEnc repLenEnc; ++ ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 state; ++} CSaveState; ++ ++typedef struct ++{ ++ IMatchFinder matchFinder; ++ void *matchFinderObj; ++ ++ #ifndef _7ZIP_ST ++ Bool mtMode; ++ CMatchFinderMt matchFinderMt; ++ #endif ++ ++ CMatchFinder matchFinderBase; ++ ++ #ifndef _7ZIP_ST ++ Byte pad[128]; ++ #endif ++ ++ UInt32 optimumEndIndex; ++ UInt32 optimumCurrentIndex; ++ ++ UInt32 longestMatchLength; ++ UInt32 numPairs; ++ UInt32 numAvail; ++ COptimal opt[kNumOpts]; ++ ++ #ifndef LZMA_LOG_BSR ++ Byte g_FastPos[1 << kNumLogBits]; ++ #endif ++ ++ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; ++ UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; ++ UInt32 numFastBytes; ++ UInt32 additionalOffset; ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 state; ++ ++ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; ++ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; ++ UInt32 alignPrices[kAlignTableSize]; ++ UInt32 alignPriceCount; ++ ++ UInt32 distTableSize; ++ ++ unsigned lc, lp, pb; ++ unsigned lpMask, pbMask; ++ ++ CLzmaProb *litProbs; ++ ++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ CLzmaProb isRep[kNumStates]; ++ CLzmaProb isRepG0[kNumStates]; ++ CLzmaProb isRepG1[kNumStates]; ++ CLzmaProb isRepG2[kNumStates]; ++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ ++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; ++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; ++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; ++ ++ CLenPriceEnc lenEnc; ++ CLenPriceEnc repLenEnc; ++ ++ unsigned lclp; ++ ++ Bool fastMode; ++ ++ CRangeEnc rc; ++ ++ Bool writeEndMark; ++ UInt64 nowPos64; ++ UInt32 matchPriceCount; ++ Bool finished; ++ Bool multiThread; ++ ++ SRes result; ++ UInt32 dictSize; ++ UInt32 matchFinderCycles; ++ ++ int needInit; ++ ++ CSaveState saveState; ++} CLzmaEnc; ++ ++void LzmaEnc_SaveState(CLzmaEncHandle pp) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CSaveState *dest = &p->saveState; ++ int i; ++ dest->lenEnc = p->lenEnc; ++ dest->repLenEnc = p->repLenEnc; ++ dest->state = p->state; ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++ } ++ for (i = 0; i < kNumLenToPosStates; i++) ++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++ memcpy(dest->reps, p->reps, sizeof(p->reps)); ++ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); ++} ++ ++void LzmaEnc_RestoreState(CLzmaEncHandle pp) ++{ ++ CLzmaEnc *dest = (CLzmaEnc *)pp; ++ const CSaveState *p = &dest->saveState; ++ int i; ++ dest->lenEnc = p->lenEnc; ++ dest->repLenEnc = p->repLenEnc; ++ dest->state = p->state; ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++ } ++ for (i = 0; i < kNumLenToPosStates; i++) ++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++ memcpy(dest->reps, p->reps, sizeof(p->reps)); ++ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); ++} ++ ++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++ ++ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || ++ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) ++ return SZ_ERROR_PARAM; ++ p->dictSize = props.dictSize; ++ p->matchFinderCycles = props.mc; ++ { ++ unsigned fb = props.fb; ++ if (fb < 5) ++ fb = 5; ++ if (fb > LZMA_MATCH_LEN_MAX) ++ fb = LZMA_MATCH_LEN_MAX; ++ p->numFastBytes = fb; ++ } ++ p->lc = props.lc; ++ p->lp = props.lp; ++ p->pb = props.pb; ++ p->fastMode = (props.algo == 0); ++ p->matchFinderBase.btMode = props.btMode; ++ { ++ UInt32 numHashBytes = 4; ++ if (props.btMode) ++ { ++ if (props.numHashBytes < 2) ++ numHashBytes = 2; ++ else if (props.numHashBytes < 4) ++ numHashBytes = props.numHashBytes; ++ } ++ p->matchFinderBase.numHashBytes = numHashBytes; ++ } ++ ++ p->matchFinderBase.cutValue = props.mc; ++ ++ p->writeEndMark = props.writeEndMark; ++ ++ #ifndef _7ZIP_ST ++ /* ++ if (newMultiThread != _multiThread) ++ { ++ ReleaseMatchFinder(); ++ _multiThread = newMultiThread; ++ } ++ */ ++ p->multiThread = (props.numThreads > 1); ++ #endif ++ ++ return SZ_OK; ++} ++ ++static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; ++static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; ++static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; ++static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; ++ ++#define IsCharState(s) ((s) < 7) ++ ++#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) ++ ++#define kInfinityPrice (1 << 30) ++ ++static void RangeEnc_Construct(CRangeEnc *p) ++{ ++ p->outStream = 0; ++ p->bufBase = 0; ++} ++ ++#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) ++ ++#define RC_BUF_SIZE (1 << 16) ++static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) ++{ ++ if (p->bufBase == 0) ++ { ++ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); ++ if (p->bufBase == 0) ++ return 0; ++ p->bufLim = p->bufBase + RC_BUF_SIZE; ++ } ++ return 1; ++} ++ ++static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->bufBase); ++ p->bufBase = 0; ++} ++ ++static void RangeEnc_Init(CRangeEnc *p) ++{ ++ /* Stream.Init(); */ ++ p->low = 0; ++ p->range = 0xFFFFFFFF; ++ p->cacheSize = 1; ++ p->cache = 0; ++ ++ p->buf = p->bufBase; ++ ++ p->processed = 0; ++ p->res = SZ_OK; ++} ++ ++static void RangeEnc_FlushStream(CRangeEnc *p) ++{ ++ size_t num; ++ if (p->res != SZ_OK) ++ return; ++ num = p->buf - p->bufBase; ++ if (num != p->outStream->Write(p->outStream, p->bufBase, num)) ++ p->res = SZ_ERROR_WRITE; ++ p->processed += num; ++ p->buf = p->bufBase; ++} ++ ++static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) ++{ ++ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) ++ { ++ Byte temp = p->cache; ++ do ++ { ++ Byte *buf = p->buf; ++ *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); ++ p->buf = buf; ++ if (buf == p->bufLim) ++ RangeEnc_FlushStream(p); ++ temp = 0xFF; ++ } ++ while (--p->cacheSize != 0); ++ p->cache = (Byte)((UInt32)p->low >> 24); ++ } ++ p->cacheSize++; ++ p->low = (UInt32)p->low << 8; ++} ++ ++static void RangeEnc_FlushData(CRangeEnc *p) ++{ ++ int i; ++ for (i = 0; i < 5; i++) ++ RangeEnc_ShiftLow(p); ++} ++ ++static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) ++{ ++ do ++ { ++ p->range >>= 1; ++ p->low += p->range & (0 - ((value >> --numBits) & 1)); ++ if (p->range < kTopValue) ++ { ++ p->range <<= 8; ++ RangeEnc_ShiftLow(p); ++ } ++ } ++ while (numBits != 0); ++} ++ ++static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) ++{ ++ UInt32 ttt = *prob; ++ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; ++ if (symbol == 0) ++ { ++ p->range = newBound; ++ ttt += (kBitModelTotal - ttt) >> kNumMoveBits; ++ } ++ else ++ { ++ p->low += newBound; ++ p->range -= newBound; ++ ttt -= ttt >> kNumMoveBits; ++ } ++ *prob = (CLzmaProb)ttt; ++ if (p->range < kTopValue) ++ { ++ p->range <<= 8; ++ RangeEnc_ShiftLow(p); ++ } ++} ++ ++static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) ++{ ++ symbol |= 0x100; ++ do ++ { ++ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); ++ symbol <<= 1; ++ } ++ while (symbol < 0x10000); ++} ++ ++static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) ++{ ++ UInt32 offs = 0x100; ++ symbol |= 0x100; ++ do ++ { ++ matchByte <<= 1; ++ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); ++ symbol <<= 1; ++ offs &= ~(matchByte ^ symbol); ++ } ++ while (symbol < 0x10000); ++} ++ ++void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) ++{ ++ UInt32 i; ++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) ++ { ++ const int kCyclesBits = kNumBitPriceShiftBits; ++ UInt32 w = i; ++ UInt32 bitCount = 0; ++ int j; ++ for (j = 0; j < kCyclesBits; j++) ++ { ++ w = w * w; ++ bitCount <<= 1; ++ while (w >= ((UInt32)1 << 16)) ++ { ++ w >>= 1; ++ bitCount++; ++ } ++ } ++ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); ++ } ++} ++ ++ ++#define GET_PRICE(prob, symbol) \ ++ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; ++ ++#define GET_PRICEa(prob, symbol) \ ++ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; ++ ++#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] ++#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] ++ ++#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] ++#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] ++ ++static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ symbol |= 0x100; ++ do ++ { ++ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); ++ symbol <<= 1; ++ } ++ while (symbol < 0x10000); ++ return price; ++} ++ ++static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ UInt32 offs = 0x100; ++ symbol |= 0x100; ++ do ++ { ++ matchByte <<= 1; ++ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); ++ symbol <<= 1; ++ offs &= ~(matchByte ^ symbol); ++ } ++ while (symbol < 0x10000); ++ return price; ++} ++ ++ ++static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) ++{ ++ UInt32 m = 1; ++ int i; ++ for (i = numBitLevels; i != 0;) ++ { ++ UInt32 bit; ++ i--; ++ bit = (symbol >> i) & 1; ++ RangeEnc_EncodeBit(rc, probs + m, bit); ++ m = (m << 1) | bit; ++ } ++} ++ ++static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) ++{ ++ UInt32 m = 1; ++ int i; ++ for (i = 0; i < numBitLevels; i++) ++ { ++ UInt32 bit = symbol & 1; ++ RangeEnc_EncodeBit(rc, probs + m, bit); ++ m = (m << 1) | bit; ++ symbol >>= 1; ++ } ++} ++ ++static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ symbol |= (1 << numBitLevels); ++ while (symbol != 1) ++ { ++ price += GET_PRICEa(probs[symbol >> 1], symbol & 1); ++ symbol >>= 1; ++ } ++ return price; ++} ++ ++static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ UInt32 m = 1; ++ int i; ++ for (i = numBitLevels; i != 0; i--) ++ { ++ UInt32 bit = symbol & 1; ++ symbol >>= 1; ++ price += GET_PRICEa(probs[m], bit); ++ m = (m << 1) | bit; ++ } ++ return price; ++} ++ ++ ++static void LenEnc_Init(CLenEnc *p) ++{ ++ unsigned i; ++ p->choice = p->choice2 = kProbInitValue; ++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) ++ p->low[i] = kProbInitValue; ++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) ++ p->mid[i] = kProbInitValue; ++ for (i = 0; i < kLenNumHighSymbols; i++) ++ p->high[i] = kProbInitValue; ++} ++ ++static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) ++{ ++ if (symbol < kLenNumLowSymbols) ++ { ++ RangeEnc_EncodeBit(rc, &p->choice, 0); ++ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); ++ } ++ else ++ { ++ RangeEnc_EncodeBit(rc, &p->choice, 1); ++ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) ++ { ++ RangeEnc_EncodeBit(rc, &p->choice2, 0); ++ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); ++ } ++ else ++ { ++ RangeEnc_EncodeBit(rc, &p->choice2, 1); ++ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); ++ } ++ } ++} ++ ++static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) ++{ ++ UInt32 a0 = GET_PRICE_0a(p->choice); ++ UInt32 a1 = GET_PRICE_1a(p->choice); ++ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); ++ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); ++ UInt32 i = 0; ++ for (i = 0; i < kLenNumLowSymbols; i++) ++ { ++ if (i >= numSymbols) ++ return; ++ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); ++ } ++ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) ++ { ++ if (i >= numSymbols) ++ return; ++ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); ++ } ++ for (; i < numSymbols; i++) ++ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); ++} ++ ++static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) ++{ ++ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); ++ p->counters[posState] = p->tableSize; ++} ++ ++static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) ++{ ++ UInt32 posState; ++ for (posState = 0; posState < numPosStates; posState++) ++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); ++} ++ ++static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) ++{ ++ LenEnc_Encode(&p->p, rc, symbol, posState); ++ if (updatePrice) ++ if (--p->counters[posState] == 0) ++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); ++} ++ ++ ++ ++ ++static void MovePos(CLzmaEnc *p, UInt32 num) ++{ ++ #ifdef SHOW_STAT ++ ttt += num; ++ printf("\n MovePos %d", num); ++ #endif ++ if (num != 0) ++ { ++ p->additionalOffset += num; ++ p->matchFinder.Skip(p->matchFinderObj, num); ++ } ++} ++ ++static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) ++{ ++ UInt32 lenRes = 0, numPairs; ++ p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++ numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); ++ #ifdef SHOW_STAT ++ printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ++ ttt++; ++ { ++ UInt32 i; ++ for (i = 0; i < numPairs; i += 2) ++ printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); ++ } ++ #endif ++ if (numPairs > 0) ++ { ++ lenRes = p->matches[numPairs - 2]; ++ if (lenRes == p->numFastBytes) ++ { ++ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ UInt32 distance = p->matches[numPairs - 1] + 1; ++ UInt32 numAvail = p->numAvail; ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ { ++ const Byte *pby2 = pby - distance; ++ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); ++ } ++ } ++ } ++ p->additionalOffset++; ++ *numDistancePairsRes = numPairs; ++ return lenRes; ++} ++ ++ ++#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; ++#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; ++#define IsShortRep(p) ((p)->backPrev == 0) ++ ++static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) ++{ ++ return ++ GET_PRICE_0(p->isRepG0[state]) + ++ GET_PRICE_0(p->isRep0Long[state][posState]); ++} ++ ++static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) ++{ ++ UInt32 price; ++ if (repIndex == 0) ++ { ++ price = GET_PRICE_0(p->isRepG0[state]); ++ price += GET_PRICE_1(p->isRep0Long[state][posState]); ++ } ++ else ++ { ++ price = GET_PRICE_1(p->isRepG0[state]); ++ if (repIndex == 1) ++ price += GET_PRICE_0(p->isRepG1[state]); ++ else ++ { ++ price += GET_PRICE_1(p->isRepG1[state]); ++ price += GET_PRICE(p->isRepG2[state], repIndex - 2); ++ } ++ } ++ return price; ++} ++ ++static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) ++{ ++ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + ++ GetPureRepPrice(p, repIndex, state, posState); ++} ++ ++static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) ++{ ++ UInt32 posMem = p->opt[cur].posPrev; ++ UInt32 backMem = p->opt[cur].backPrev; ++ p->optimumEndIndex = cur; ++ do ++ { ++ if (p->opt[cur].prev1IsChar) ++ { ++ MakeAsChar(&p->opt[posMem]) ++ p->opt[posMem].posPrev = posMem - 1; ++ if (p->opt[cur].prev2) ++ { ++ p->opt[posMem - 1].prev1IsChar = False; ++ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; ++ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; ++ } ++ } ++ { ++ UInt32 posPrev = posMem; ++ UInt32 backCur = backMem; ++ ++ backMem = p->opt[posPrev].backPrev; ++ posMem = p->opt[posPrev].posPrev; ++ ++ p->opt[posPrev].backPrev = backCur; ++ p->opt[posPrev].posPrev = cur; ++ cur = posPrev; ++ } ++ } ++ while (cur != 0); ++ *backRes = p->opt[0].backPrev; ++ p->optimumCurrentIndex = p->opt[0].posPrev; ++ return p->optimumCurrentIndex; ++} ++ ++#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) ++ ++static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) ++{ ++ UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; ++ UInt32 matchPrice, repMatchPrice, normalMatchPrice; ++ UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; ++ UInt32 *matches; ++ const Byte *data; ++ Byte curByte, matchByte; ++ if (p->optimumEndIndex != p->optimumCurrentIndex) ++ { ++ const COptimal *opt = &p->opt[p->optimumCurrentIndex]; ++ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; ++ *backRes = opt->backPrev; ++ p->optimumCurrentIndex = opt->posPrev; ++ return lenRes; ++ } ++ p->optimumCurrentIndex = p->optimumEndIndex = 0; ++ ++ if (p->additionalOffset == 0) ++ mainLen = ReadMatchDistances(p, &numPairs); ++ else ++ { ++ mainLen = p->longestMatchLength; ++ numPairs = p->numPairs; ++ } ++ ++ numAvail = p->numAvail; ++ if (numAvail < 2) ++ { ++ *backRes = (UInt32)(-1); ++ return 1; ++ } ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ repMaxIndex = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 lenTest; ++ const Byte *data2; ++ reps[i] = p->reps[i]; ++ data2 = data - (reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ { ++ repLens[i] = 0; ++ continue; ++ } ++ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); ++ repLens[i] = lenTest; ++ if (lenTest > repLens[repMaxIndex]) ++ repMaxIndex = i; ++ } ++ if (repLens[repMaxIndex] >= p->numFastBytes) ++ { ++ UInt32 lenRes; ++ *backRes = repMaxIndex; ++ lenRes = repLens[repMaxIndex]; ++ MovePos(p, lenRes - 1); ++ return lenRes; ++ } ++ ++ matches = p->matches; ++ if (mainLen >= p->numFastBytes) ++ { ++ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; ++ MovePos(p, mainLen - 1); ++ return mainLen; ++ } ++ curByte = *data; ++ matchByte = *(data - (reps[0] + 1)); ++ ++ if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) ++ { ++ *backRes = (UInt32)-1; ++ return 1; ++ } ++ ++ p->opt[0].state = (CState)p->state; ++ ++ posState = (position & p->pbMask); ++ ++ { ++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); ++ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + ++ (!IsCharState(p->state) ? ++ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : ++ LitEnc_GetPrice(probs, curByte, p->ProbPrices)); ++ } ++ ++ MakeAsChar(&p->opt[1]); ++ ++ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); ++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); ++ ++ if (matchByte == curByte) ++ { ++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); ++ if (shortRepPrice < p->opt[1].price) ++ { ++ p->opt[1].price = shortRepPrice; ++ MakeAsShortRep(&p->opt[1]); ++ } ++ } ++ lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); ++ ++ if (lenEnd < 2) ++ { ++ *backRes = p->opt[1].backPrev; ++ return 1; ++ } ++ ++ p->opt[1].posPrev = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ p->opt[0].backs[i] = reps[i]; ++ ++ len = lenEnd; ++ do ++ p->opt[len--].price = kInfinityPrice; ++ while (len >= 2); ++ ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 repLen = repLens[i]; ++ UInt32 price; ++ if (repLen < 2) ++ continue; ++ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); ++ do ++ { ++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; ++ COptimal *opt = &p->opt[repLen]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = 0; ++ opt->backPrev = i; ++ opt->prev1IsChar = False; ++ } ++ } ++ while (--repLen >= 2); ++ } ++ ++ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); ++ ++ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); ++ if (len <= mainLen) ++ { ++ UInt32 offs = 0; ++ while (len > matches[offs]) ++ offs += 2; ++ for (; ; len++) ++ { ++ COptimal *opt; ++ UInt32 distance = matches[offs + 1]; ++ ++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; ++ UInt32 lenToPosState = GetLenToPosState(len); ++ if (distance < kNumFullDistances) ++ curAndLenPrice += p->distancesPrices[lenToPosState][distance]; ++ else ++ { ++ UInt32 slot; ++ GetPosSlot2(distance, slot); ++ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; ++ } ++ opt = &p->opt[len]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = 0; ++ opt->backPrev = distance + LZMA_NUM_REPS; ++ opt->prev1IsChar = False; ++ } ++ if (len == matches[offs]) ++ { ++ offs += 2; ++ if (offs == numPairs) ++ break; ++ } ++ } ++ } ++ ++ cur = 0; ++ ++ #ifdef SHOW_STAT2 ++ if (position >= 0) ++ { ++ unsigned i; ++ printf("\n pos = %4X", position); ++ for (i = cur; i <= lenEnd; i++) ++ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); ++ } ++ #endif ++ ++ for (;;) ++ { ++ UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; ++ UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; ++ Bool nextIsChar; ++ Byte curByte, matchByte; ++ const Byte *data; ++ COptimal *curOpt; ++ COptimal *nextOpt; ++ ++ cur++; ++ if (cur == lenEnd) ++ return Backward(p, backRes, cur); ++ ++ newLen = ReadMatchDistances(p, &numPairs); ++ if (newLen >= p->numFastBytes) ++ { ++ p->numPairs = numPairs; ++ p->longestMatchLength = newLen; ++ return Backward(p, backRes, cur); ++ } ++ position++; ++ curOpt = &p->opt[cur]; ++ posPrev = curOpt->posPrev; ++ if (curOpt->prev1IsChar) ++ { ++ posPrev--; ++ if (curOpt->prev2) ++ { ++ state = p->opt[curOpt->posPrev2].state; ++ if (curOpt->backPrev2 < LZMA_NUM_REPS) ++ state = kRepNextStates[state]; ++ else ++ state = kMatchNextStates[state]; ++ } ++ else ++ state = p->opt[posPrev].state; ++ state = kLiteralNextStates[state]; ++ } ++ else ++ state = p->opt[posPrev].state; ++ if (posPrev == cur - 1) ++ { ++ if (IsShortRep(curOpt)) ++ state = kShortRepNextStates[state]; ++ else ++ state = kLiteralNextStates[state]; ++ } ++ else ++ { ++ UInt32 pos; ++ const COptimal *prevOpt; ++ if (curOpt->prev1IsChar && curOpt->prev2) ++ { ++ posPrev = curOpt->posPrev2; ++ pos = curOpt->backPrev2; ++ state = kRepNextStates[state]; ++ } ++ else ++ { ++ pos = curOpt->backPrev; ++ if (pos < LZMA_NUM_REPS) ++ state = kRepNextStates[state]; ++ else ++ state = kMatchNextStates[state]; ++ } ++ prevOpt = &p->opt[posPrev]; ++ if (pos < LZMA_NUM_REPS) ++ { ++ UInt32 i; ++ reps[0] = prevOpt->backs[pos]; ++ for (i = 1; i <= pos; i++) ++ reps[i] = prevOpt->backs[i - 1]; ++ for (; i < LZMA_NUM_REPS; i++) ++ reps[i] = prevOpt->backs[i]; ++ } ++ else ++ { ++ UInt32 i; ++ reps[0] = (pos - LZMA_NUM_REPS); ++ for (i = 1; i < LZMA_NUM_REPS; i++) ++ reps[i] = prevOpt->backs[i - 1]; ++ } ++ } ++ curOpt->state = (CState)state; ++ ++ curOpt->backs[0] = reps[0]; ++ curOpt->backs[1] = reps[1]; ++ curOpt->backs[2] = reps[2]; ++ curOpt->backs[3] = reps[3]; ++ ++ curPrice = curOpt->price; ++ nextIsChar = False; ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ curByte = *data; ++ matchByte = *(data - (reps[0] + 1)); ++ ++ posState = (position & p->pbMask); ++ ++ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); ++ { ++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); ++ curAnd1Price += ++ (!IsCharState(state) ? ++ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : ++ LitEnc_GetPrice(probs, curByte, p->ProbPrices)); ++ } ++ ++ nextOpt = &p->opt[cur + 1]; ++ ++ if (curAnd1Price < nextOpt->price) ++ { ++ nextOpt->price = curAnd1Price; ++ nextOpt->posPrev = cur; ++ MakeAsChar(nextOpt); ++ nextIsChar = True; ++ } ++ ++ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); ++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); ++ ++ if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) ++ { ++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); ++ if (shortRepPrice <= nextOpt->price) ++ { ++ nextOpt->price = shortRepPrice; ++ nextOpt->posPrev = cur; ++ MakeAsShortRep(nextOpt); ++ nextIsChar = True; ++ } ++ } ++ numAvailFull = p->numAvail; ++ { ++ UInt32 temp = kNumOpts - 1 - cur; ++ if (temp < numAvailFull) ++ numAvailFull = temp; ++ } ++ ++ if (numAvailFull < 2) ++ continue; ++ numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); ++ ++ if (!nextIsChar && matchByte != curByte) /* speed optimization */ ++ { ++ /* try Literal + rep0 */ ++ UInt32 temp; ++ UInt32 lenTest2; ++ const Byte *data2 = data - (reps[0] + 1); ++ UInt32 limit = p->numFastBytes + 1; ++ if (limit > numAvailFull) ++ limit = numAvailFull; ++ ++ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); ++ lenTest2 = temp - 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kLiteralNextStates[state]; ++ UInt32 posStateNext = (position + 1) & p->pbMask; ++ UInt32 nextRepMatchPrice = curAnd1Price + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ UInt32 offset = cur + 1 + lenTest2; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = False; ++ } ++ } ++ } ++ } ++ ++ startLen = 2; /* speed optimization */ ++ { ++ UInt32 repIndex; ++ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) ++ { ++ UInt32 lenTest; ++ UInt32 lenTestTemp; ++ UInt32 price; ++ const Byte *data2 = data - (reps[repIndex] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); ++ while (lenEnd < cur + lenTest) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ lenTestTemp = lenTest; ++ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); ++ do ++ { ++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; ++ COptimal *opt = &p->opt[cur + lenTest]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur; ++ opt->backPrev = repIndex; ++ opt->prev1IsChar = False; ++ } ++ } ++ while (--lenTest >= 2); ++ lenTest = lenTestTemp; ++ ++ if (repIndex == 0) ++ startLen = lenTest + 1; ++ ++ /* if (_maxMode) */ ++ { ++ UInt32 lenTest2 = lenTest + 1; ++ UInt32 limit = lenTest2 + p->numFastBytes; ++ UInt32 nextRepMatchPrice; ++ if (limit > numAvailFull) ++ limit = numAvailFull; ++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); ++ lenTest2 -= lenTest + 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kRepNextStates[state]; ++ UInt32 posStateNext = (position + lenTest) & p->pbMask; ++ UInt32 curAndLenCharPrice = ++ price + p->repLenEnc.prices[posState][lenTest - 2] + ++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + ++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), ++ data[lenTest], data2[lenTest], p->ProbPrices); ++ state2 = kLiteralNextStates[state2]; ++ posStateNext = (position + lenTest + 1) & p->pbMask; ++ nextRepMatchPrice = curAndLenCharPrice + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ UInt32 offset = cur + lenTest + 1 + lenTest2; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + lenTest + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = True; ++ opt->posPrev2 = cur; ++ opt->backPrev2 = repIndex; ++ } ++ } ++ } ++ } ++ } ++ } ++ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ ++ if (newLen > numAvail) ++ { ++ newLen = numAvail; ++ for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); ++ matches[numPairs] = newLen; ++ numPairs += 2; ++ } ++ if (newLen >= startLen) ++ { ++ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); ++ UInt32 offs, curBack, posSlot; ++ UInt32 lenTest; ++ while (lenEnd < cur + newLen) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ ++ offs = 0; ++ while (startLen > matches[offs]) ++ offs += 2; ++ curBack = matches[offs + 1]; ++ GetPosSlot2(curBack, posSlot); ++ for (lenTest = /*2*/ startLen; ; lenTest++) ++ { ++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; ++ UInt32 lenToPosState = GetLenToPosState(lenTest); ++ COptimal *opt; ++ if (curBack < kNumFullDistances) ++ curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; ++ else ++ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; ++ ++ opt = &p->opt[cur + lenTest]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur; ++ opt->backPrev = curBack + LZMA_NUM_REPS; ++ opt->prev1IsChar = False; ++ } ++ ++ if (/*_maxMode && */lenTest == matches[offs]) ++ { ++ /* Try Match + Literal + Rep0 */ ++ const Byte *data2 = data - (curBack + 1); ++ UInt32 lenTest2 = lenTest + 1; ++ UInt32 limit = lenTest2 + p->numFastBytes; ++ UInt32 nextRepMatchPrice; ++ if (limit > numAvailFull) ++ limit = numAvailFull; ++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); ++ lenTest2 -= lenTest + 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kMatchNextStates[state]; ++ UInt32 posStateNext = (position + lenTest) & p->pbMask; ++ UInt32 curAndLenCharPrice = curAndLenPrice + ++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + ++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), ++ data[lenTest], data2[lenTest], p->ProbPrices); ++ state2 = kLiteralNextStates[state2]; ++ posStateNext = (posStateNext + 1) & p->pbMask; ++ nextRepMatchPrice = curAndLenCharPrice + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 offset = cur + lenTest + 1 + lenTest2; ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + lenTest + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = True; ++ opt->posPrev2 = cur; ++ opt->backPrev2 = curBack + LZMA_NUM_REPS; ++ } ++ } ++ } ++ offs += 2; ++ if (offs == numPairs) ++ break; ++ curBack = matches[offs + 1]; ++ if (curBack >= kNumFullDistances) ++ GetPosSlot2(curBack, posSlot); ++ } ++ } ++ } ++ } ++} ++ ++#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) ++ ++static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) ++{ ++ UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; ++ const Byte *data; ++ const UInt32 *matches; ++ ++ if (p->additionalOffset == 0) ++ mainLen = ReadMatchDistances(p, &numPairs); ++ else ++ { ++ mainLen = p->longestMatchLength; ++ numPairs = p->numPairs; ++ } ++ ++ numAvail = p->numAvail; ++ *backRes = (UInt32)-1; ++ if (numAvail < 2) ++ return 1; ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ ++ repLen = repIndex = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 len; ++ const Byte *data2 = data - (p->reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ for (len = 2; len < numAvail && data[len] == data2[len]; len++); ++ if (len >= p->numFastBytes) ++ { ++ *backRes = i; ++ MovePos(p, len - 1); ++ return len; ++ } ++ if (len > repLen) ++ { ++ repIndex = i; ++ repLen = len; ++ } ++ } ++ ++ matches = p->matches; ++ if (mainLen >= p->numFastBytes) ++ { ++ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; ++ MovePos(p, mainLen - 1); ++ return mainLen; ++ } ++ ++ mainDist = 0; /* for GCC */ ++ if (mainLen >= 2) ++ { ++ mainDist = matches[numPairs - 1]; ++ while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) ++ { ++ if (!ChangePair(matches[numPairs - 3], mainDist)) ++ break; ++ numPairs -= 2; ++ mainLen = matches[numPairs - 2]; ++ mainDist = matches[numPairs - 1]; ++ } ++ if (mainLen == 2 && mainDist >= 0x80) ++ mainLen = 1; ++ } ++ ++ if (repLen >= 2 && ( ++ (repLen + 1 >= mainLen) || ++ (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || ++ (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) ++ { ++ *backRes = repIndex; ++ MovePos(p, repLen - 1); ++ return repLen; ++ } ++ ++ if (mainLen < 2 || numAvail <= 2) ++ return 1; ++ ++ p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); ++ if (p->longestMatchLength >= 2) ++ { ++ UInt32 newDistance = matches[p->numPairs - 1]; ++ if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || ++ (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || ++ (p->longestMatchLength > mainLen + 1) || ++ (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) ++ return 1; ++ } ++ ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 len, limit; ++ const Byte *data2 = data - (p->reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ limit = mainLen - 1; ++ for (len = 2; len < limit && data[len] == data2[len]; len++); ++ if (len >= limit) ++ return 1; ++ } ++ *backRes = mainDist + LZMA_NUM_REPS; ++ MovePos(p, mainLen - 2); ++ return mainLen; ++} ++ ++static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) ++{ ++ UInt32 len; ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); ++ p->state = kMatchNextStates[p->state]; ++ len = LZMA_MATCH_LEN_MIN; ++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); ++ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); ++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); ++} ++ ++static SRes CheckErrors(CLzmaEnc *p) ++{ ++ if (p->result != SZ_OK) ++ return p->result; ++ if (p->rc.res != SZ_OK) ++ p->result = SZ_ERROR_WRITE; ++ if (p->matchFinderBase.result != SZ_OK) ++ p->result = SZ_ERROR_READ; ++ if (p->result != SZ_OK) ++ p->finished = True; ++ return p->result; ++} ++ ++static SRes Flush(CLzmaEnc *p, UInt32 nowPos) ++{ ++ /* ReleaseMFStream(); */ ++ p->finished = True; ++ if (p->writeEndMark) ++ WriteEndMarker(p, nowPos & p->pbMask); ++ RangeEnc_FlushData(&p->rc); ++ RangeEnc_FlushStream(&p->rc); ++ return CheckErrors(p); ++} ++ ++static void FillAlignPrices(CLzmaEnc *p) ++{ ++ UInt32 i; ++ for (i = 0; i < kAlignTableSize; i++) ++ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); ++ p->alignPriceCount = 0; ++} ++ ++static void FillDistancesPrices(CLzmaEnc *p) ++{ ++ UInt32 tempPrices[kNumFullDistances]; ++ UInt32 i, lenToPosState; ++ for (i = kStartPosModelIndex; i < kNumFullDistances; i++) ++ { ++ UInt32 posSlot = GetPosSlot1(i); ++ UInt32 footerBits = ((posSlot >> 1) - 1); ++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); ++ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); ++ } ++ ++ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) ++ { ++ UInt32 posSlot; ++ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; ++ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; ++ for (posSlot = 0; posSlot < p->distTableSize; posSlot++) ++ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); ++ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) ++ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); ++ ++ { ++ UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; ++ UInt32 i; ++ for (i = 0; i < kStartPosModelIndex; i++) ++ distancesPrices[i] = posSlotPrices[i]; ++ for (; i < kNumFullDistances; i++) ++ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; ++ } ++ } ++ p->matchPriceCount = 0; ++} ++ ++void LzmaEnc_Construct(CLzmaEnc *p) ++{ ++ RangeEnc_Construct(&p->rc); ++ MatchFinder_Construct(&p->matchFinderBase); ++ #ifndef _7ZIP_ST ++ MatchFinderMt_Construct(&p->matchFinderMt); ++ p->matchFinderMt.MatchFinder = &p->matchFinderBase; ++ #endif ++ ++ { ++ CLzmaEncProps props; ++ LzmaEncProps_Init(&props); ++ LzmaEnc_SetProps(p, &props); ++ } ++ ++ #ifndef LZMA_LOG_BSR ++ LzmaEnc_FastPosInit(p->g_FastPos); ++ #endif ++ ++ LzmaEnc_InitPriceTables(p->ProbPrices); ++ p->litProbs = 0; ++ p->saveState.litProbs = 0; ++} ++ ++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) ++{ ++ void *p; ++ p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); ++ if (p != 0) ++ LzmaEnc_Construct((CLzmaEnc *)p); ++ return p; ++} ++ ++void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->litProbs); ++ alloc->Free(alloc, p->saveState.litProbs); ++ p->litProbs = 0; ++ p->saveState.litProbs = 0; ++} ++ ++void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ #ifndef _7ZIP_ST ++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); ++ #endif ++ MatchFinder_Free(&p->matchFinderBase, allocBig); ++ LzmaEnc_FreeLits(p, alloc); ++ RangeEnc_Free(&p->rc, alloc); ++} ++ ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); ++ alloc->Free(alloc, p); ++} ++ ++static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) ++{ ++ UInt32 nowPos32, startPos32; ++ if (p->needInit) ++ { ++ p->matchFinder.Init(p->matchFinderObj); ++ p->needInit = 0; ++ } ++ ++ if (p->finished) ++ return p->result; ++ RINOK(CheckErrors(p)); ++ ++ nowPos32 = (UInt32)p->nowPos64; ++ startPos32 = nowPos32; ++ ++ if (p->nowPos64 == 0) ++ { ++ UInt32 numPairs; ++ Byte curByte; ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) ++ return Flush(p, nowPos32); ++ ReadMatchDistances(p, &numPairs); ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); ++ p->state = kLiteralNextStates[p->state]; ++ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); ++ LitEnc_Encode(&p->rc, p->litProbs, curByte); ++ p->additionalOffset--; ++ nowPos32++; ++ } ++ ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) ++ for (;;) ++ { ++ UInt32 pos, len, posState; ++ ++ if (p->fastMode) ++ len = GetOptimumFast(p, &pos); ++ else ++ len = GetOptimum(p, nowPos32, &pos); ++ ++ #ifdef SHOW_STAT2 ++ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); ++ #endif ++ ++ posState = nowPos32 & p->pbMask; ++ if (len == 1 && pos == (UInt32)-1) ++ { ++ Byte curByte; ++ CLzmaProb *probs; ++ const Byte *data; ++ ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++ curByte = *data; ++ probs = LIT_PROBS(nowPos32, *(data - 1)); ++ if (IsCharState(p->state)) ++ LitEnc_Encode(&p->rc, probs, curByte); ++ else ++ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); ++ p->state = kLiteralNextStates[p->state]; ++ } ++ else ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); ++ if (pos < LZMA_NUM_REPS) ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); ++ if (pos == 0) ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); ++ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); ++ } ++ else ++ { ++ UInt32 distance = p->reps[pos]; ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); ++ if (pos == 1) ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); ++ else ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); ++ if (pos == 3) ++ p->reps[3] = p->reps[2]; ++ p->reps[2] = p->reps[1]; ++ } ++ p->reps[1] = p->reps[0]; ++ p->reps[0] = distance; ++ } ++ if (len == 1) ++ p->state = kShortRepNextStates[p->state]; ++ else ++ { ++ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ p->state = kRepNextStates[p->state]; ++ } ++ } ++ else ++ { ++ UInt32 posSlot; ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); ++ p->state = kMatchNextStates[p->state]; ++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ pos -= LZMA_NUM_REPS; ++ GetPosSlot(pos, posSlot); ++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); ++ ++ if (posSlot >= kStartPosModelIndex) ++ { ++ UInt32 footerBits = ((posSlot >> 1) - 1); ++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); ++ UInt32 posReduced = pos - base; ++ ++ if (posSlot < kEndPosModelIndex) ++ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); ++ else ++ { ++ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); ++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); ++ p->alignPriceCount++; ++ } ++ } ++ p->reps[3] = p->reps[2]; ++ p->reps[2] = p->reps[1]; ++ p->reps[1] = p->reps[0]; ++ p->reps[0] = pos; ++ p->matchPriceCount++; ++ } ++ } ++ p->additionalOffset -= len; ++ nowPos32 += len; ++ if (p->additionalOffset == 0) ++ { ++ UInt32 processed; ++ if (!p->fastMode) ++ { ++ if (p->matchPriceCount >= (1 << 7)) ++ FillDistancesPrices(p); ++ if (p->alignPriceCount >= kAlignTableSize) ++ FillAlignPrices(p); ++ } ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) ++ break; ++ processed = nowPos32 - startPos32; ++ if (useLimits) ++ { ++ if (processed + kNumOpts + 300 >= maxUnpackSize || ++ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) ++ break; ++ } ++ else if (processed >= (1 << 15)) ++ { ++ p->nowPos64 += nowPos32 - startPos32; ++ return CheckErrors(p); ++ } ++ } ++ } ++ p->nowPos64 += nowPos32 - startPos32; ++ return Flush(p, nowPos32); ++} ++ ++#define kBigHashDicLimit ((UInt32)1 << 24) ++ ++static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ UInt32 beforeSize = kNumOpts; ++ Bool btMode; ++ if (!RangeEnc_Alloc(&p->rc, alloc)) ++ return SZ_ERROR_MEM; ++ btMode = (p->matchFinderBase.btMode != 0); ++ #ifndef _7ZIP_ST ++ p->mtMode = (p->multiThread && !p->fastMode && btMode); ++ #endif ++ ++ { ++ unsigned lclp = p->lc + p->lp; ++ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) ++ { ++ LzmaEnc_FreeLits(p, alloc); ++ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); ++ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); ++ if (p->litProbs == 0 || p->saveState.litProbs == 0) ++ { ++ LzmaEnc_FreeLits(p, alloc); ++ return SZ_ERROR_MEM; ++ } ++ p->lclp = lclp; ++ } ++ } ++ ++ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); ++ ++ if (beforeSize + p->dictSize < keepWindowSize) ++ beforeSize = keepWindowSize - p->dictSize; ++ ++ #ifndef _7ZIP_ST ++ if (p->mtMode) ++ { ++ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); ++ p->matchFinderObj = &p->matchFinderMt; ++ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); ++ } ++ else ++ #endif ++ { ++ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) ++ return SZ_ERROR_MEM; ++ p->matchFinderObj = &p->matchFinderBase; ++ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); ++ } ++ return SZ_OK; ++} ++ ++void LzmaEnc_Init(CLzmaEnc *p) ++{ ++ UInt32 i; ++ p->state = 0; ++ for (i = 0 ; i < LZMA_NUM_REPS; i++) ++ p->reps[i] = 0; ++ ++ RangeEnc_Init(&p->rc); ++ ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ UInt32 j; ++ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) ++ { ++ p->isMatch[i][j] = kProbInitValue; ++ p->isRep0Long[i][j] = kProbInitValue; ++ } ++ p->isRep[i] = kProbInitValue; ++ p->isRepG0[i] = kProbInitValue; ++ p->isRepG1[i] = kProbInitValue; ++ p->isRepG2[i] = kProbInitValue; ++ } ++ ++ { ++ UInt32 num = 0x300 << (p->lp + p->lc); ++ for (i = 0; i < num; i++) ++ p->litProbs[i] = kProbInitValue; ++ } ++ ++ { ++ for (i = 0; i < kNumLenToPosStates; i++) ++ { ++ CLzmaProb *probs = p->posSlotEncoder[i]; ++ UInt32 j; ++ for (j = 0; j < (1 << kNumPosSlotBits); j++) ++ probs[j] = kProbInitValue; ++ } ++ } ++ { ++ for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) ++ p->posEncoders[i] = kProbInitValue; ++ } ++ ++ LenEnc_Init(&p->lenEnc.p); ++ LenEnc_Init(&p->repLenEnc.p); ++ ++ for (i = 0; i < (1 << kNumAlignBits); i++) ++ p->posAlignEncoder[i] = kProbInitValue; ++ ++ p->optimumEndIndex = 0; ++ p->optimumCurrentIndex = 0; ++ p->additionalOffset = 0; ++ ++ p->pbMask = (1 << p->pb) - 1; ++ p->lpMask = (1 << p->lp) - 1; ++} ++ ++void LzmaEnc_InitPrices(CLzmaEnc *p) ++{ ++ if (!p->fastMode) ++ { ++ FillDistancesPrices(p); ++ FillAlignPrices(p); ++ } ++ ++ p->lenEnc.tableSize = ++ p->repLenEnc.tableSize = ++ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; ++ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); ++ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); ++} ++ ++static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ UInt32 i; ++ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) ++ if (p->dictSize <= ((UInt32)1 << i)) ++ break; ++ p->distTableSize = i * 2; ++ ++ p->finished = False; ++ p->result = SZ_OK; ++ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); ++ LzmaEnc_Init(p); ++ LzmaEnc_InitPrices(p); ++ p->nowPos64 = 0; ++ return SZ_OK; ++} ++ ++static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ p->matchFinderBase.stream = inStream; ++ p->needInit = 1; ++ p->rc.outStream = outStream; ++ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); ++} ++ ++SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ++ ISeqInStream *inStream, UInt32 keepWindowSize, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ p->matchFinderBase.stream = inStream; ++ p->needInit = 1; ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ ++static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) ++{ ++ p->matchFinderBase.directInput = 1; ++ p->matchFinderBase.bufferBase = (Byte *)src; ++ p->matchFinderBase.directInputRem = srcLen; ++} ++ ++SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, ++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ LzmaEnc_SetInputBuf(p, src, srcLen); ++ p->needInit = 1; ++ ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ ++void LzmaEnc_Finish(CLzmaEncHandle pp) ++{ ++ #ifndef _7ZIP_ST ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ if (p->mtMode) ++ MatchFinderMt_ReleaseStream(&p->matchFinderMt); ++ #else ++ pp = pp; ++ #endif ++} ++ ++typedef struct ++{ ++ ISeqOutStream funcTable; ++ Byte *data; ++ SizeT rem; ++ Bool overflow; ++} CSeqOutStreamBuf; ++ ++static size_t MyWrite(void *pp, const void *data, size_t size) ++{ ++ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; ++ if (p->rem < size) ++ { ++ size = p->rem; ++ p->overflow = True; ++ } ++ memcpy(p->data, data, size); ++ p->rem -= size; ++ p->data += size; ++ return size; ++} ++ ++ ++UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) ++{ ++ const CLzmaEnc *p = (CLzmaEnc *)pp; ++ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++} ++ ++const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) ++{ ++ const CLzmaEnc *p = (CLzmaEnc *)pp; ++ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++} ++ ++SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, ++ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ UInt64 nowPos64; ++ SRes res; ++ CSeqOutStreamBuf outStream; ++ ++ outStream.funcTable.Write = MyWrite; ++ outStream.data = dest; ++ outStream.rem = *destLen; ++ outStream.overflow = False; ++ ++ p->writeEndMark = False; ++ p->finished = False; ++ p->result = SZ_OK; ++ ++ if (reInit) ++ LzmaEnc_Init(p); ++ LzmaEnc_InitPrices(p); ++ nowPos64 = p->nowPos64; ++ RangeEnc_Init(&p->rc); ++ p->rc.outStream = &outStream.funcTable; ++ ++ res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); ++ ++ *unpackSize = (UInt32)(p->nowPos64 - nowPos64); ++ *destLen -= outStream.rem; ++ if (outStream.overflow) ++ return SZ_ERROR_OUTPUT_EOF; ++ ++ return res; ++} ++ ++static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) ++{ ++ SRes res = SZ_OK; ++ ++ #ifndef _7ZIP_ST ++ Byte allocaDummy[0x300]; ++ int i = 0; ++ for (i = 0; i < 16; i++) ++ allocaDummy[i] = (Byte)i; ++ #endif ++ ++ for (;;) ++ { ++ res = LzmaEnc_CodeOneBlock(p, False, 0, 0); ++ if (res != SZ_OK || p->finished != 0) ++ break; ++ if (progress != 0) ++ { ++ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); ++ if (res != SZ_OK) ++ { ++ res = SZ_ERROR_PROGRESS; ++ break; ++ } ++ } ++ } ++ LzmaEnc_Finish(p); ++ return res; ++} ++ ++SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); ++ return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); ++} ++ ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ int i; ++ UInt32 dictSize = p->dictSize; ++ if (*size < LZMA_PROPS_SIZE) ++ return SZ_ERROR_PARAM; ++ *size = LZMA_PROPS_SIZE; ++ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); ++ ++ for (i = 11; i <= 30; i++) ++ { ++ if (dictSize <= ((UInt32)2 << i)) ++ { ++ dictSize = (2 << i); ++ break; ++ } ++ if (dictSize <= ((UInt32)3 << i)) ++ { ++ dictSize = (3 << i); ++ break; ++ } ++ } ++ ++ for (i = 0; i < 4; i++) ++ props[1 + i] = (Byte)(dictSize >> (8 * i)); ++ return SZ_OK; ++} ++ ++SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ SRes res; ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ ++ CSeqOutStreamBuf outStream; ++ ++ LzmaEnc_SetInputBuf(p, src, srcLen); ++ ++ outStream.funcTable.Write = MyWrite; ++ outStream.data = dest; ++ outStream.rem = *destLen; ++ outStream.overflow = False; ++ ++ p->writeEndMark = writeEndMark; ++ ++ p->rc.outStream = &outStream.funcTable; ++ res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); ++ if (res == SZ_OK) ++ res = LzmaEnc_Encode2(p, progress); ++ ++ *destLen -= outStream.rem; ++ if (outStream.overflow) ++ return SZ_ERROR_OUTPUT_EOF; ++ return res; ++} ++ ++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); ++ SRes res; ++ if (p == 0) ++ return SZ_ERROR_MEM; ++ ++ res = LzmaEnc_SetProps(p, props); ++ if (res == SZ_OK) ++ { ++ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); ++ if (res == SZ_OK) ++ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, ++ writeEndMark, progress, alloc, allocBig); ++ } ++ ++ LzmaEnc_Destroy(p, alloc, allocBig); ++ return res; ++} +--- /dev/null ++++ b/lib/lzma/Makefile +@@ -0,0 +1,7 @@ ++lzma_compress-objs := LzFind.o LzmaEnc.o ++lzma_decompress-objs := LzmaDec.o ++ ++obj-$(CONFIG_LZMA_COMPRESS) += lzma_compress.o ++obj-$(CONFIG_LZMA_DECOMPRESS) += lzma_decompress.o ++ ++EXTRA_CFLAGS += -Iinclude/linux -Iinclude/linux/lzma -include types.h diff --git a/target/linux/generic/pending-5.15/532-jffs2_eofdetect.patch b/target/linux/generic/pending-5.15/532-jffs2_eofdetect.patch new file mode 100644 index 0000000000..a1d7dc1a69 --- /dev/null +++ b/target/linux/generic/pending-5.15/532-jffs2_eofdetect.patch @@ -0,0 +1,65 @@ +From: Felix Fietkau +Subject: fs: jffs2: EOF marker + +Signed-off-by: Felix Fietkau +--- + fs/jffs2/build.c | 10 ++++++++++ + fs/jffs2/scan.c | 21 +++++++++++++++++++-- + 2 files changed, 29 insertions(+), 2 deletions(-) + +--- a/fs/jffs2/build.c ++++ b/fs/jffs2/build.c +@@ -117,6 +117,16 @@ static int jffs2_build_filesystem(struct + dbg_fsbuild("scanned flash completely\n"); + jffs2_dbg_dump_block_lists_nolock(c); + ++ if (c->flags & (1 << 7)) { ++ printk("%s(): unlocking the mtd device... ", __func__); ++ mtd_unlock(c->mtd, 0, c->mtd->size); ++ printk("done.\n"); ++ ++ printk("%s(): erasing all blocks after the end marker... ", __func__); ++ jffs2_erase_pending_blocks(c, -1); ++ printk("done.\n"); ++ } ++ + dbg_fsbuild("pass 1 starting\n"); + c->flags |= JFFS2_SB_FLAG_BUILDING; + /* Now scan the directory tree, increasing nlink according to every dirent found. */ +--- a/fs/jffs2/scan.c ++++ b/fs/jffs2/scan.c +@@ -148,8 +148,14 @@ int jffs2_scan_medium(struct jffs2_sb_in + /* reset summary info for next eraseblock scan */ + jffs2_sum_reset_collected(s); + +- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), +- buf_size, s); ++ if (c->flags & (1 << 7)) { ++ if (mtd_block_isbad(c->mtd, jeb->offset)) ++ ret = BLK_STATE_BADBLOCK; ++ else ++ ret = BLK_STATE_ALLFF; ++ } else ++ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), ++ buf_size, s); + + if (ret < 0) + goto out; +@@ -565,6 +571,17 @@ full_scan: + return err; + } + ++ if ((buf[0] == 0xde) && ++ (buf[1] == 0xad) && ++ (buf[2] == 0xc0) && ++ (buf[3] == 0xde)) { ++ /* end of filesystem. erase everything after this point */ ++ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset); ++ c->flags |= (1 << 7); ++ ++ return BLK_STATE_ALLFF; ++ } ++ + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ + ofs = 0; + max_ofs = EMPTY_SCAN_SIZE(c->sector_size); diff --git a/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch b/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch new file mode 100644 index 0000000000..ab6953e557 --- /dev/null +++ b/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch @@ -0,0 +1,88 @@ +From: Felix Fietkau +Subject: netfilter: add support for flushing conntrack via /proc + +lede-commit 8193bbe59a74d34d6a26d4a8cb857b1952905314 +Signed-off-by: Felix Fietkau +--- + net/netfilter/nf_conntrack_standalone.c | 59 ++++++++++++++++++++++++++++++++- + 1 file changed, 58 insertions(+), 1 deletion(-) + +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #ifdef CONFIG_SYSCTL + #include +@@ -457,6 +458,56 @@ static int ct_cpu_seq_show(struct seq_fi + return 0; + } + ++struct kill_request { ++ u16 family; ++ union nf_inet_addr addr; ++}; ++ ++static int kill_matching(struct nf_conn *i, void *data) ++{ ++ struct kill_request *kr = data; ++ struct nf_conntrack_tuple *t1 = &i->tuplehash[IP_CT_DIR_ORIGINAL].tuple; ++ struct nf_conntrack_tuple *t2 = &i->tuplehash[IP_CT_DIR_REPLY].tuple; ++ ++ if (!kr->family) ++ return 1; ++ ++ if (t1->src.l3num != kr->family) ++ return 0; ++ ++ return (nf_inet_addr_cmp(&kr->addr, &t1->src.u3) || ++ nf_inet_addr_cmp(&kr->addr, &t1->dst.u3) || ++ nf_inet_addr_cmp(&kr->addr, &t2->src.u3) || ++ nf_inet_addr_cmp(&kr->addr, &t2->dst.u3)); ++} ++ ++static int ct_file_write(struct file *file, char *buf, size_t count) ++{ ++ struct seq_file *seq = file->private_data; ++ struct net *net = seq_file_net(seq); ++ struct kill_request kr = { }; ++ ++ if (count == 0) ++ return 0; ++ ++ if (count >= INET6_ADDRSTRLEN) ++ count = INET6_ADDRSTRLEN - 1; ++ ++ if (strnchr(buf, count, ':')) { ++ kr.family = AF_INET6; ++ if (!in6_pton(buf, count, (void *)&kr.addr, '\n', NULL)) ++ return -EINVAL; ++ } else if (strnchr(buf, count, '.')) { ++ kr.family = AF_INET; ++ if (!in4_pton(buf, count, (void *)&kr.addr, '\n', NULL)) ++ return -EINVAL; ++ } ++ ++ nf_ct_iterate_cleanup_net(net, kill_matching, &kr, 0, 0); ++ ++ return 0; ++} ++ + static const struct seq_operations ct_cpu_seq_ops = { + .start = ct_cpu_seq_start, + .next = ct_cpu_seq_next, +@@ -470,8 +521,9 @@ static int nf_conntrack_standalone_init_ + kuid_t root_uid; + kgid_t root_gid; + +- pde = proc_create_net("nf_conntrack", 0440, net->proc_net, &ct_seq_ops, +- sizeof(struct ct_iter_state)); ++ pde = proc_create_net_data_write("nf_conntrack", 0440, net->proc_net, ++ &ct_seq_ops, &ct_file_write, ++ sizeof(struct ct_iter_state), NULL); + if (!pde) + goto out_nf_conntrack; + diff --git a/target/linux/generic/pending-5.15/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-5.15/610-netfilter_match_bypass_default_checks.patch new file mode 100644 index 0000000000..457703121c --- /dev/null +++ b/target/linux/generic/pending-5.15/610-netfilter_match_bypass_default_checks.patch @@ -0,0 +1,110 @@ +From: Felix Fietkau +Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 + +Signed-off-by: Felix Fietkau +--- + include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + + net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/include/uapi/linux/netfilter_ipv4/ip_tables.h ++++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h +@@ -89,6 +89,7 @@ struct ipt_ip { + #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ + #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ + #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ ++#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ + + /* Values for "inv" field in struct ipt_ip. */ + #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -50,6 +50,9 @@ ip_packet_match(const struct iphdr *ip, + { + unsigned long ret; + ++ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) ++ return true; ++ + if (NF_INVF(ipinfo, IPT_INV_SRCIP, + (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || + NF_INVF(ipinfo, IPT_INV_DSTIP, +@@ -80,6 +83,29 @@ ip_packet_match(const struct iphdr *ip, + return true; + } + ++static void ++ip_checkdefault(struct ipt_ip *ip) ++{ ++ static const char iface_mask[IFNAMSIZ] = {}; ++ ++ if (ip->invflags || ip->flags & IPT_F_FRAG) ++ return; ++ ++ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) ++ return; ++ ++ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) ++ return; ++ ++ if (ip->smsk.s_addr || ip->dmsk.s_addr) ++ return; ++ ++ if (ip->proto) ++ return; ++ ++ ip->flags |= IPT_F_NO_DEF_MATCH; ++} ++ + static bool + ip_checkentry(const struct ipt_ip *ip) + { +@@ -524,6 +550,8 @@ find_check_entry(struct ipt_entry *e, st + struct xt_mtchk_param mtpar; + struct xt_entry_match *ematch; + ++ ip_checkdefault(&e->ip); ++ + if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) + return -ENOMEM; + +@@ -818,6 +846,7 @@ copy_entries_to_user(unsigned int total_ + const struct xt_table_info *private = table->private; + int ret = 0; + const void *loc_cpu_entry; ++ u8 flags; + + counters = alloc_counters(table); + if (IS_ERR(counters)) +@@ -845,6 +874,14 @@ copy_entries_to_user(unsigned int total_ + goto free_counters; + } + ++ flags = e->ip.flags & IPT_F_MASK; ++ if (copy_to_user(userptr + off ++ + offsetof(struct ipt_entry, ip.flags), ++ &flags, sizeof(flags)) != 0) { ++ ret = -EFAULT; ++ goto free_counters; ++ } ++ + for (i = sizeof(struct ipt_entry); + i < e->target_offset; + i += m->u.match_size) { +@@ -1223,12 +1260,15 @@ compat_copy_entry_to_user(struct ipt_ent + compat_uint_t origsize; + const struct xt_entry_match *ematch; + int ret = 0; ++ u8 flags = e->ip.flags & IPT_F_MASK; + + origsize = *size; + ce = *dstptr; + if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || + copy_to_user(&ce->counters, &counters[i], +- sizeof(counters[i])) != 0) ++ sizeof(counters[i])) != 0 || ++ copy_to_user(&ce->ip.flags, &flags, ++ sizeof(flags)) != 0) + return -EFAULT; + + *dstptr += sizeof(struct compat_ipt_entry); diff --git a/target/linux/generic/pending-5.15/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-5.15/611-netfilter_match_bypass_default_table.patch new file mode 100644 index 0000000000..baf738a8d2 --- /dev/null +++ b/target/linux/generic/pending-5.15/611-netfilter_match_bypass_default_table.patch @@ -0,0 +1,106 @@ +From: Felix Fietkau +Subject: netfilter: match bypass default table + +Signed-off-by: Felix Fietkau +--- + net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- + 1 file changed, 58 insertions(+), 21 deletions(-) + +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -246,6 +246,33 @@ struct ipt_entry *ipt_next_entry(const s + return (void *)entry + entry->next_offset; + } + ++static bool ++ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) ++{ ++ struct xt_entry_target *t; ++ struct xt_standard_target *st; ++ ++ if (e->target_offset != sizeof(struct ipt_entry)) ++ return false; ++ ++ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) ++ return false; ++ ++ t = ipt_get_target(e); ++ if (t->u.kernel.target->target) ++ return false; ++ ++ st = (struct xt_standard_target *) t; ++ if (st->verdict == XT_RETURN) ++ return false; ++ ++ if (st->verdict >= 0) ++ return false; ++ ++ *verdict = (unsigned)(-st->verdict) - 1; ++ return true; ++} ++ + /* Returns one of the generic firewall policies, like NF_ACCEPT. */ + unsigned int + ipt_do_table(struct sk_buff *skb, +@@ -266,27 +293,28 @@ ipt_do_table(struct sk_buff *skb, + unsigned int addend; + + /* Initialization */ ++ WARN_ON(!(table->valid_hooks & (1 << hook))); ++ local_bh_disable(); ++ private = READ_ONCE(table->private); /* Address dependency. */ ++ cpu = smp_processor_id(); ++ table_base = private->entries; ++ ++ e = get_entry(table_base, private->hook_entry[hook]); ++ if (ipt_handle_default_rule(e, &verdict)) { ++ struct xt_counters *counter; ++ ++ counter = xt_get_this_cpu_counter(&e->counters); ++ ADD_COUNTER(*counter, skb->len, 1); ++ local_bh_enable(); ++ return verdict; ++ } ++ + stackidx = 0; + ip = ip_hdr(skb); + indev = state->in ? state->in->name : nulldevname; + outdev = state->out ? state->out->name : nulldevname; +- /* We handle fragments by dealing with the first fragment as +- * if it was a normal packet. All other fragments are treated +- * normally, except that they will NEVER match rules that ask +- * things we don't know, ie. tcp syn flag or ports). If the +- * rule is also a fragment-specific rule, non-fragments won't +- * match it. */ +- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; +- acpar.thoff = ip_hdrlen(skb); +- acpar.hotdrop = false; +- acpar.state = state; + +- WARN_ON(!(table->valid_hooks & (1 << hook))); +- local_bh_disable(); + addend = xt_write_recseq_begin(); +- private = READ_ONCE(table->private); /* Address dependency. */ +- cpu = smp_processor_id(); +- table_base = private->entries; + jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; + + /* Switch to alternate jumpstack if we're being invoked via TEE. +@@ -299,7 +327,16 @@ ipt_do_table(struct sk_buff *skb, + if (static_key_false(&xt_tee_enabled)) + jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); + +- e = get_entry(table_base, private->hook_entry[hook]); ++ /* We handle fragments by dealing with the first fragment as ++ * if it was a normal packet. All other fragments are treated ++ * normally, except that they will NEVER match rules that ask ++ * things we don't know, ie. tcp syn flag or ports). If the ++ * rule is also a fragment-specific rule, non-fragments won't ++ * match it. */ ++ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; ++ acpar.thoff = ip_hdrlen(skb); ++ acpar.hotdrop = false; ++ acpar.state = state; + + do { + const struct xt_entry_target *t; diff --git a/target/linux/generic/pending-5.15/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-5.15/612-netfilter_match_reduce_memory_access.patch new file mode 100644 index 0000000000..79da6778b6 --- /dev/null +++ b/target/linux/generic/pending-5.15/612-netfilter_match_reduce_memory_access.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Subject: netfilter: reduce match memory access + +Signed-off-by: Felix Fietkau +--- + net/ipv4/netfilter/ip_tables.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -53,9 +53,9 @@ ip_packet_match(const struct iphdr *ip, + if (ipinfo->flags & IPT_F_NO_DEF_MATCH) + return true; + +- if (NF_INVF(ipinfo, IPT_INV_SRCIP, ++ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && + (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || +- NF_INVF(ipinfo, IPT_INV_DSTIP, ++ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && + (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) + return false; + diff --git a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch new file mode 100644 index 0000000000..97e449510d --- /dev/null +++ b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch @@ -0,0 +1,73 @@ +From: Felix Fietkau +Subject: netfilter: optional tcp window check + +Signed-off-by: Felix Fietkau +--- + net/netfilter/nf_conntrack_proto_tcp.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -31,6 +31,9 @@ + #include + #include + ++/* Do not check the TCP window for incoming packets */ ++static int nf_ct_tcp_no_window_check __read_mostly = 1; ++ + /* "Be conservative in what you do, + be liberal in what you accept from others." + If it's non-zero, we mark only out of window RST segments as INVALID. */ +@@ -476,6 +479,9 @@ static bool tcp_in_window(const struct n + s32 receiver_offset; + bool res, in_recv_win; + ++ if (nf_ct_tcp_no_window_check) ++ return true; ++ + /* + * Get the required data from the packet. + */ +@@ -1130,7 +1136,7 @@ int nf_conntrack_tcp_packet(struct nf_co + IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && + timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) + timeout = timeouts[TCP_CONNTRACK_UNACK]; +- else if (ct->proto.tcp.last_win == 0 && ++ else if (!nf_ct_tcp_no_window_check && ct->proto.tcp.last_win == 0 && + timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS]) + timeout = timeouts[TCP_CONNTRACK_RETRANS]; + else +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -25,6 +25,9 @@ + #include + #include + ++/* Do not check the TCP window for incoming packets */ ++static int nf_ct_tcp_no_window_check __read_mostly = 1; ++ + static bool enable_hooks __read_mostly; + MODULE_PARM_DESC(enable_hooks, "Always enable conntrack hooks"); + module_param(enable_hooks, bool, 0000); +@@ -660,6 +663,7 @@ enum nf_ct_sysctl_index { + NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM, + #endif + ++ NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK, + __NF_SYSCTL_CT_LAST_SYSCTL, + }; + +@@ -1014,6 +1018,13 @@ static struct ctl_table nf_ct_sysctl_tab + .proc_handler = proc_dointvec_jiffies, + }, + #endif ++ [NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK] = { ++ .procname = "nf_conntrack_tcp_no_window_check", ++ .data = &nf_ct_tcp_no_window_check, ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ }, + {} + }; + diff --git a/target/linux/generic/pending-5.15/620-net_sched-codel-do-not-defer-queue-length-update.patch b/target/linux/generic/pending-5.15/620-net_sched-codel-do-not-defer-queue-length-update.patch new file mode 100644 index 0000000000..4b4825ae3b --- /dev/null +++ b/target/linux/generic/pending-5.15/620-net_sched-codel-do-not-defer-queue-length-update.patch @@ -0,0 +1,86 @@ +From: Konstantin Khlebnikov +Date: Mon, 21 Aug 2017 11:14:14 +0300 +Subject: [PATCH] net_sched/codel: do not defer queue length update + +When codel wants to drop last packet in ->dequeue() it cannot call +qdisc_tree_reduce_backlog() right away - it will notify parent qdisc +about zero qlen and HTB/HFSC will deactivate class. The same class will +be deactivated second time by caller of ->dequeue(). Currently codel and +fq_codel defer update. This triggers warning in HFSC when it's qlen != 0 +but there is no active classes. + +This patch update parent queue length immediately: just temporary increase +qlen around qdisc_tree_reduce_backlog() to prevent first class deactivation +if we have skb to return. + +This might open another problem in HFSC - now operation peek could fail and +deactivate parent class. + +Signed-off-by: Konstantin Khlebnikov +Link: https://bugzilla.kernel.org/show_bug.cgi?id=109581 +--- + +--- a/net/sched/sch_codel.c ++++ b/net/sched/sch_codel.c +@@ -95,11 +95,17 @@ static struct sk_buff *codel_qdisc_deque + &q->stats, qdisc_pkt_len, codel_get_enqueue_time, + drop_func, dequeue_func); + +- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, +- * or HTB crashes. Defer it for next round. ++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate ++ * parent class, dequeue in parent qdisc will do the same if we ++ * return skb. Temporary increment qlen if we have skb. + */ +- if (q->stats.drop_count && sch->q.qlen) { +- qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len); ++ if (q->stats.drop_count) { ++ if (skb) ++ sch->q.qlen++; ++ qdisc_tree_reduce_backlog(sch, q->stats.drop_count, ++ q->stats.drop_len); ++ if (skb) ++ sch->q.qlen--; + q->stats.drop_count = 0; + q->stats.drop_len = 0; + } +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -304,6 +304,21 @@ begin: + &flow->cvars, &q->cstats, qdisc_pkt_len, + codel_get_enqueue_time, drop_func, dequeue_func); + ++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate ++ * parent class, dequeue in parent qdisc will do the same if we ++ * return skb. Temporary increment qlen if we have skb. ++ */ ++ if (q->cstats.drop_count) { ++ if (skb) ++ sch->q.qlen++; ++ qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, ++ q->cstats.drop_len); ++ if (skb) ++ sch->q.qlen--; ++ q->cstats.drop_count = 0; ++ q->cstats.drop_len = 0; ++ } ++ + if (!skb) { + /* force a pass through old_flows to prevent starvation */ + if ((head == &q->new_flows) && !list_empty(&q->old_flows)) +@@ -314,15 +329,6 @@ begin: + } + qdisc_bstats_update(sch, skb); + flow->deficit -= qdisc_pkt_len(skb); +- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, +- * or HTB crashes. Defer it for next round. +- */ +- if (q->cstats.drop_count && sch->q.qlen) { +- qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, +- q->cstats.drop_len); +- q->cstats.drop_count = 0; +- q->cstats.drop_len = 0; +- } + return skb; + } + diff --git a/target/linux/generic/pending-5.15/630-packet_socket_type.patch b/target/linux/generic/pending-5.15/630-packet_socket_type.patch new file mode 100644 index 0000000000..5b396c3a8c --- /dev/null +++ b/target/linux/generic/pending-5.15/630-packet_socket_type.patch @@ -0,0 +1,138 @@ +From: Felix Fietkau +Subject: net: add an optimization for dealing with raw sockets + +lede-commit: 4898039703d7315f0f3431c860123338ec3be0f6 +Signed-off-by: Felix Fietkau +--- + include/uapi/linux/if_packet.h | 3 +++ + net/packet/af_packet.c | 34 +++++++++++++++++++++++++++------- + net/packet/internal.h | 1 + + 3 files changed, 31 insertions(+), 7 deletions(-) + +--- a/include/uapi/linux/if_packet.h ++++ b/include/uapi/linux/if_packet.h +@@ -33,6 +33,8 @@ struct sockaddr_ll { + #define PACKET_KERNEL 7 /* To kernel space */ + /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */ + #define PACKET_FASTROUTE 6 /* Fastrouted frame */ ++#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */ ++ + + /* Packet socket options */ + +@@ -59,6 +61,7 @@ struct sockaddr_ll { + #define PACKET_ROLLOVER_STATS 21 + #define PACKET_FANOUT_DATA 22 + #define PACKET_IGNORE_OUTGOING 23 ++#define PACKET_RECV_TYPE 24 + + #define PACKET_FANOUT_HASH 0 + #define PACKET_FANOUT_LB 1 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1822,6 +1822,7 @@ static int packet_rcv_spkt(struct sk_buf + { + struct sock *sk; + struct sockaddr_pkt *spkt; ++ struct packet_sock *po; + + /* + * When we registered the protocol we saved the socket in the data +@@ -1829,6 +1830,7 @@ static int packet_rcv_spkt(struct sk_buf + */ + + sk = pt->af_packet_priv; ++ po = pkt_sk(sk); + + /* + * Yank back the headers [hope the device set this +@@ -1841,7 +1843,7 @@ static int packet_rcv_spkt(struct sk_buf + * so that this procedure is noop. + */ + +- if (skb->pkt_type == PACKET_LOOPBACK) ++ if (!(po->pkt_type & (1 << skb->pkt_type))) + goto out; + + if (!net_eq(dev_net(dev), sock_net(sk))) +@@ -2079,12 +2081,12 @@ static int packet_rcv(struct sk_buff *sk + unsigned int snaplen, res; + bool is_drop_n_account = false; + +- if (skb->pkt_type == PACKET_LOOPBACK) +- goto drop; +- + sk = pt->af_packet_priv; + po = pkt_sk(sk); + ++ if (!(po->pkt_type & (1 << skb->pkt_type))) ++ goto drop; ++ + if (!net_eq(dev_net(dev), sock_net(sk))) + goto drop; + +@@ -2210,12 +2212,12 @@ static int tpacket_rcv(struct sk_buff *s + BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); + BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); + +- if (skb->pkt_type == PACKET_LOOPBACK) +- goto drop; +- + sk = pt->af_packet_priv; + po = pkt_sk(sk); + ++ if (!(po->pkt_type & (1 << skb->pkt_type))) ++ goto drop; ++ + if (!net_eq(dev_net(dev), sock_net(sk))) + goto drop; + +@@ -3325,6 +3327,7 @@ static int packet_create(struct net *net + mutex_init(&po->pg_vec_lock); + po->rollover = NULL; + po->prot_hook.func = packet_rcv; ++ po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK); + + if (sock->type == SOCK_PACKET) + po->prot_hook.func = packet_rcv_spkt; +@@ -3969,6 +3972,16 @@ packet_setsockopt(struct socket *sock, i + po->xmit = val ? packet_direct_xmit : dev_queue_xmit; + return 0; + } ++ case PACKET_RECV_TYPE: ++ { ++ unsigned int val; ++ if (optlen != sizeof(val)) ++ return -EINVAL; ++ if (copy_from_sockptr(&val, optval, sizeof(val))) ++ return -EFAULT; ++ po->pkt_type = val & ~BIT(PACKET_LOOPBACK); ++ return 0; ++ } + default: + return -ENOPROTOOPT; + } +@@ -4025,6 +4038,13 @@ static int packet_getsockopt(struct sock + case PACKET_VNET_HDR: + val = po->has_vnet_hdr; + break; ++ case PACKET_RECV_TYPE: ++ if (len > sizeof(unsigned int)) ++ len = sizeof(unsigned int); ++ val = po->pkt_type; ++ ++ data = &val; ++ break; + case PACKET_VERSION: + val = po->tp_version; + break; +--- a/net/packet/internal.h ++++ b/net/packet/internal.h +@@ -137,6 +137,7 @@ struct packet_sock { + int (*xmit)(struct sk_buff *skb); + struct packet_type prot_hook ____cacheline_aligned_in_smp; + atomic_t tp_drops ____cacheline_aligned_in_smp; ++ unsigned int pkt_type; + }; + + static struct packet_sock *pkt_sk(struct sock *sk) diff --git a/target/linux/generic/pending-5.15/655-increase_skb_pad.patch b/target/linux/generic/pending-5.15/655-increase_skb_pad.patch new file mode 100644 index 0000000000..ff39ddb8b3 --- /dev/null +++ b/target/linux/generic/pending-5.15/655-increase_skb_pad.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Subject: kernel: add a few patches for avoiding unnecessary skb reallocations - significantly improves ethernet<->wireless performance + +lede-commit: 6f89cffc9add6939d44a6b54cf9a5e77849aa7fd +Signed-off-by: Felix Fietkau +--- + include/linux/skbuff.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2676,7 +2676,7 @@ static inline int pskb_network_may_pull( + * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) + */ + #ifndef NET_SKB_PAD +-#define NET_SKB_PAD max(32, L1_CACHE_BYTES) ++#define NET_SKB_PAD max(64, L1_CACHE_BYTES) + #endif + + int ___pskb_trim(struct sk_buff *skb, unsigned int len); diff --git a/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch new file mode 100644 index 0000000000..89eb7d61b3 --- /dev/null +++ b/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -0,0 +1,511 @@ +From: Steven Barth +Subject: Add support for MAP-E FMRs (mesh mode) + +MAP-E FMRs (draft-ietf-softwire-map-10) are rules for IPv4-communication +between MAP CEs (mesh mode) without the need to forward such data to a +border relay. This is similar to how 6rd works but for IPv4 over IPv6. + +Signed-off-by: Steven Barth +--- + include/net/ip6_tunnel.h | 13 ++ + include/uapi/linux/if_tunnel.h | 13 ++ + net/ipv6/ip6_tunnel.c | 276 +++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 291 insertions(+), 11 deletions(-) + +--- a/include/net/ip6_tunnel.h ++++ b/include/net/ip6_tunnel.h +@@ -18,6 +18,18 @@ + /* determine capability on a per-packet basis */ + #define IP6_TNL_F_CAP_PER_PACKET 0x40000 + ++/* IPv6 tunnel FMR */ ++struct __ip6_tnl_fmr { ++ struct __ip6_tnl_fmr *next; /* next fmr in list */ ++ struct in6_addr ip6_prefix; ++ struct in_addr ip4_prefix; ++ ++ __u8 ip6_prefix_len; ++ __u8 ip4_prefix_len; ++ __u8 ea_len; ++ __u8 offset; ++}; ++ + struct __ip6_tnl_parm { + char name[IFNAMSIZ]; /* name of tunnel device */ + int link; /* ifindex of underlying L2 interface */ +@@ -29,6 +41,7 @@ struct __ip6_tnl_parm { + __u32 flags; /* tunnel flags */ + struct in6_addr laddr; /* local tunnel end-point address */ + struct in6_addr raddr; /* remote tunnel end-point address */ ++ struct __ip6_tnl_fmr *fmrs; /* FMRs */ + + __be16 i_flags; + __be16 o_flags; +--- a/include/uapi/linux/if_tunnel.h ++++ b/include/uapi/linux/if_tunnel.h +@@ -77,10 +77,23 @@ enum { + IFLA_IPTUN_ENCAP_DPORT, + IFLA_IPTUN_COLLECT_METADATA, + IFLA_IPTUN_FWMARK, ++ IFLA_IPTUN_FMRS, + __IFLA_IPTUN_MAX, + }; + #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + ++enum { ++ IFLA_IPTUN_FMR_UNSPEC, ++ IFLA_IPTUN_FMR_IP6_PREFIX, ++ IFLA_IPTUN_FMR_IP4_PREFIX, ++ IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ++ IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ++ IFLA_IPTUN_FMR_EA_LEN, ++ IFLA_IPTUN_FMR_OFFSET, ++ __IFLA_IPTUN_FMR_MAX, ++}; ++#define IFLA_IPTUN_FMR_MAX (__IFLA_IPTUN_FMR_MAX - 1) ++ + enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -11,6 +11,9 @@ + * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c + * + * RFC 2473 ++ * ++ * Changes: ++ * Steven Barth : MAP-E FMR support + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +@@ -67,9 +70,9 @@ static bool log_ecn_error = true; + module_param(log_ecn_error, bool, 0644); + MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); + +-static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) ++static u32 HASH(const struct in6_addr *addr) + { +- u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); ++ u32 hash = ipv6_addr_hash(addr); + + return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT); + } +@@ -144,17 +147,33 @@ static struct ip6_tnl * + ip6_tnl_lookup(struct net *net, int link, + const struct in6_addr *remote, const struct in6_addr *local) + { +- unsigned int hash = HASH(remote, local); ++ unsigned int hash = HASH(local); + struct ip6_tnl *t, *cand = NULL; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct in6_addr any; + + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (!ipv6_addr_equal(local, &t->parms.laddr) || +- !ipv6_addr_equal(remote, &t->parms.raddr) || + !(t->dev->flags & IFF_UP)) + continue; + ++ if (!ipv6_addr_equal(remote, &t->parms.raddr)) { ++ struct __ip6_tnl_fmr *fmr; ++ bool found = false; ++ ++ for (fmr = t->parms.fmrs; fmr; fmr = fmr->next) { ++ if (!ipv6_prefix_equal(remote, &fmr->ip6_prefix, ++ fmr->ip6_prefix_len)) ++ continue; ++ ++ found = true; ++ break; ++ } ++ ++ if (!found) ++ continue; ++ } ++ + if (link == t->parms.link) + return t; + else +@@ -162,7 +181,7 @@ ip6_tnl_lookup(struct net *net, int link + } + + memset(&any, 0, sizeof(any)); +- hash = HASH(&any, local); ++ hash = HASH(local); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (!ipv6_addr_equal(local, &t->parms.laddr) || + !ipv6_addr_any(&t->parms.raddr) || +@@ -175,7 +194,7 @@ ip6_tnl_lookup(struct net *net, int link + cand = t; + } + +- hash = HASH(remote, &any); ++ hash = HASH(&any); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (!ipv6_addr_equal(remote, &t->parms.raddr) || + !ipv6_addr_any(&t->parms.laddr) || +@@ -223,7 +242,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, + + if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { + prio = 1; +- h = HASH(remote, local); ++ h = HASH(local); + } + return &ip6n->tnls[prio][h]; + } +@@ -405,6 +424,12 @@ ip6_tnl_dev_uninit(struct net_device *de + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + ++ while (t->parms.fmrs) { ++ struct __ip6_tnl_fmr *next = t->parms.fmrs->next; ++ kfree(t->parms.fmrs); ++ t->parms.fmrs = next; ++ } ++ + if (dev == ip6n->fb_tnl_dev) + RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); + else +@@ -821,6 +846,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, + } + EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl); + ++/** ++ * ip4ip6_fmr_calc - calculate target / source IPv6-address based on FMR ++ * @dest: destination IPv6 address buffer ++ * @skb: received socket buffer ++ * @fmr: MAP FMR ++ * @xmit: Calculate for xmit or rcv ++ **/ ++static void ip4ip6_fmr_calc(struct in6_addr *dest, ++ const struct iphdr *iph, const uint8_t *end, ++ const struct __ip6_tnl_fmr *fmr, bool xmit) ++{ ++ int psidlen = fmr->ea_len - (32 - fmr->ip4_prefix_len); ++ u8 *portp = NULL; ++ bool use_dest_addr; ++ const struct iphdr *dsth = iph; ++ ++ if ((u8*)dsth >= end) ++ return; ++ ++ /* find significant IP header */ ++ if (iph->protocol == IPPROTO_ICMP) { ++ struct icmphdr *ih = (struct icmphdr*)(((u8*)dsth) + dsth->ihl * 4); ++ if (ih && ((u8*)&ih[1]) <= end && ( ++ ih->type == ICMP_DEST_UNREACH || ++ ih->type == ICMP_SOURCE_QUENCH || ++ ih->type == ICMP_TIME_EXCEEDED || ++ ih->type == ICMP_PARAMETERPROB || ++ ih->type == ICMP_REDIRECT)) ++ dsth = (const struct iphdr*)&ih[1]; ++ } ++ ++ /* in xmit-path use dest port by default and source port only if ++ this is an ICMP reply to something else; vice versa in rcv-path */ ++ use_dest_addr = (xmit && dsth == iph) || (!xmit && dsth != iph); ++ ++ /* get dst port */ ++ if (((u8*)&dsth[1]) <= end && ( ++ dsth->protocol == IPPROTO_UDP || ++ dsth->protocol == IPPROTO_TCP || ++ dsth->protocol == IPPROTO_SCTP || ++ dsth->protocol == IPPROTO_DCCP)) { ++ /* for UDP, TCP, SCTP and DCCP source and dest port ++ follow IPv4 header directly */ ++ portp = ((u8*)dsth) + dsth->ihl * 4; ++ ++ if (use_dest_addr) ++ portp += sizeof(u16); ++ } else if (iph->protocol == IPPROTO_ICMP) { ++ struct icmphdr *ih = (struct icmphdr*)(((u8*)dsth) + dsth->ihl * 4); ++ ++ /* use icmp identifier as port */ ++ if (((u8*)&ih) <= end && ( ++ (use_dest_addr && ( ++ ih->type == ICMP_ECHOREPLY || ++ ih->type == ICMP_TIMESTAMPREPLY || ++ ih->type == ICMP_INFO_REPLY || ++ ih->type == ICMP_ADDRESSREPLY)) || ++ (!use_dest_addr && ( ++ ih->type == ICMP_ECHO || ++ ih->type == ICMP_TIMESTAMP || ++ ih->type == ICMP_INFO_REQUEST || ++ ih->type == ICMP_ADDRESS) ++ ))) ++ portp = (u8*)&ih->un.echo.id; ++ } ++ ++ if ((portp && &portp[2] <= end) || psidlen == 0) { ++ int frombyte = fmr->ip6_prefix_len / 8; ++ int fromrem = fmr->ip6_prefix_len % 8; ++ int bytes = sizeof(struct in6_addr) - frombyte; ++ const u32 *addr = (use_dest_addr) ? &iph->daddr : &iph->saddr; ++ u64 eabits = ((u64)ntohl(*addr)) << (32 + fmr->ip4_prefix_len); ++ u64 t = 0; ++ ++ /* extract PSID from port and add it to eabits */ ++ u16 psidbits = 0; ++ if (psidlen > 0) { ++ psidbits = ((u16)portp[0]) << 8 | ((u16)portp[1]); ++ psidbits >>= 16 - psidlen - fmr->offset; ++ psidbits = (u16)(psidbits << (16 - psidlen)); ++ eabits |= ((u64)psidbits) << (48 - (fmr->ea_len - psidlen)); ++ } ++ ++ /* rewrite destination address */ ++ *dest = fmr->ip6_prefix; ++ memcpy(&dest->s6_addr[10], addr, sizeof(*addr)); ++ dest->s6_addr16[7] = htons(psidbits >> (16 - psidlen)); ++ ++ if (bytes > sizeof(u64)) ++ bytes = sizeof(u64); ++ ++ /* insert eabits */ ++ memcpy(&t, &dest->s6_addr[frombyte], bytes); ++ t = be64_to_cpu(t) & ~(((((u64)1) << fmr->ea_len) - 1) ++ << (64 - fmr->ea_len - fromrem)); ++ t = cpu_to_be64(t | (eabits >> fromrem)); ++ memcpy(&dest->s6_addr[frombyte], &t, bytes); ++ } ++} ++ ++ + static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, +@@ -873,6 +999,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl + skb_reset_network_header(skb); + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + ++ if (tpi->proto == htons(ETH_P_IP) && tunnel->parms.fmrs && ++ !ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) { ++ /* Packet didn't come from BR, so lookup FMR */ ++ struct __ip6_tnl_fmr *fmr; ++ struct in6_addr expected = tunnel->parms.raddr; ++ for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next) ++ if (ipv6_prefix_equal(&ipv6h->saddr, ++ &fmr->ip6_prefix, fmr->ip6_prefix_len)) ++ break; ++ ++ /* Check that IPv6 matches IPv4 source to prevent spoofing */ ++ if (fmr) ++ ip4ip6_fmr_calc(&expected, ip_hdr(skb), ++ skb_tail_pointer(skb), fmr, false); ++ ++ if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) { ++ rcu_read_unlock(); ++ goto drop; ++ } ++ } ++ + __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); + + err = dscp_ecn_decapsulate(tunnel, ipv6h, skb); +@@ -1024,6 +1171,7 @@ static void init_tel_txopt(struct ipv6_t + opt->ops.opt_nflen = 8; + } + ++ + /** + * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own + * @t: the outgoing tunnel device +@@ -1304,6 +1452,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str + u8 protocol) + { + struct ip6_tnl *t = netdev_priv(dev); ++ struct __ip6_tnl_fmr *fmr; + struct ipv6hdr *ipv6h; + const struct iphdr *iph; + int encap_limit = -1; +@@ -1403,6 +1552,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str + fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield); + ++ /* try to find matching FMR */ ++ for (fmr = t->parms.fmrs; fmr; fmr = fmr->next) { ++ unsigned mshift = 32 - fmr->ip4_prefix_len; ++ if (ntohl(fmr->ip4_prefix.s_addr) >> mshift == ++ ntohl(ip_hdr(skb)->daddr) >> mshift) ++ break; ++ } ++ ++ /* change dstaddr according to FMR */ ++ if (fmr) ++ ip4ip6_fmr_calc(&fl6.daddr, ip_hdr(skb), skb_tail_pointer(skb), fmr, true); ++ + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + +@@ -1555,6 +1716,14 @@ ip6_tnl_change(struct ip6_tnl *t, const + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.fwmark = p->fwmark; ++ ++ while (t->parms.fmrs) { ++ struct __ip6_tnl_fmr *next = t->parms.fmrs->next; ++ kfree(t->parms.fmrs); ++ t->parms.fmrs = next; ++ } ++ t->parms.fmrs = p->fmrs; ++ + dst_cache_reset(&t->dst_cache); + ip6_tnl_link_config(t); + return 0; +@@ -1593,6 +1762,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ + p->flowinfo = u->flowinfo; + p->link = u->link; + p->proto = u->proto; ++ p->fmrs = NULL; + memcpy(p->name, u->name, sizeof(u->name)); + } + +@@ -1978,6 +2148,15 @@ static int ip6_tnl_validate(struct nlatt + return 0; + } + ++static const struct nla_policy ip6_tnl_fmr_policy[IFLA_IPTUN_FMR_MAX + 1] = { ++ [IFLA_IPTUN_FMR_IP6_PREFIX] = { .len = sizeof(struct in6_addr) }, ++ [IFLA_IPTUN_FMR_IP4_PREFIX] = { .len = sizeof(struct in_addr) }, ++ [IFLA_IPTUN_FMR_IP6_PREFIX_LEN] = { .type = NLA_U8 }, ++ [IFLA_IPTUN_FMR_IP4_PREFIX_LEN] = { .type = NLA_U8 }, ++ [IFLA_IPTUN_FMR_EA_LEN] = { .type = NLA_U8 }, ++ [IFLA_IPTUN_FMR_OFFSET] = { .type = NLA_U8 } ++}; ++ + static void ip6_tnl_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) + { +@@ -2015,6 +2194,46 @@ static void ip6_tnl_netlink_parms(struct + + if (data[IFLA_IPTUN_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); ++ ++ if (data[IFLA_IPTUN_FMRS]) { ++ unsigned rem; ++ struct nlattr *fmr; ++ nla_for_each_nested(fmr, data[IFLA_IPTUN_FMRS], rem) { ++ struct nlattr *fmrd[IFLA_IPTUN_FMR_MAX + 1], *c; ++ struct __ip6_tnl_fmr *nfmr; ++ ++ nla_parse_nested(fmrd, IFLA_IPTUN_FMR_MAX, ++ fmr, ip6_tnl_fmr_policy, NULL); ++ ++ if (!(nfmr = kzalloc(sizeof(*nfmr), GFP_KERNEL))) ++ continue; ++ ++ nfmr->offset = 6; ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP6_PREFIX])) ++ nla_memcpy(&nfmr->ip6_prefix, fmrd[IFLA_IPTUN_FMR_IP6_PREFIX], ++ sizeof(nfmr->ip6_prefix)); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP4_PREFIX])) ++ nla_memcpy(&nfmr->ip4_prefix, fmrd[IFLA_IPTUN_FMR_IP4_PREFIX], ++ sizeof(nfmr->ip4_prefix)); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP6_PREFIX_LEN])) ++ nfmr->ip6_prefix_len = nla_get_u8(c); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_IP4_PREFIX_LEN])) ++ nfmr->ip4_prefix_len = nla_get_u8(c); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_EA_LEN])) ++ nfmr->ea_len = nla_get_u8(c); ++ ++ if ((c = fmrd[IFLA_IPTUN_FMR_OFFSET])) ++ nfmr->offset = nla_get_u8(c); ++ ++ nfmr->next = parms->fmrs; ++ parms->fmrs = nfmr; ++ } ++ } + } + + static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], +@@ -2130,6 +2349,12 @@ static void ip6_tnl_dellink(struct net_d + + static size_t ip6_tnl_get_size(const struct net_device *dev) + { ++ const struct ip6_tnl *t = netdev_priv(dev); ++ struct __ip6_tnl_fmr *c; ++ int fmrs = 0; ++ for (c = t->parms.fmrs; c; c = c->next) ++ ++fmrs; ++ + return + /* IFLA_IPTUN_LINK */ + nla_total_size(4) + +@@ -2159,6 +2384,24 @@ static size_t ip6_tnl_get_size(const str + nla_total_size(0) + + /* IFLA_IPTUN_FWMARK */ + nla_total_size(4) + ++ /* IFLA_IPTUN_FMRS */ ++ nla_total_size(0) + ++ ( ++ /* nest */ ++ nla_total_size(0) + ++ /* IFLA_IPTUN_FMR_IP6_PREFIX */ ++ nla_total_size(sizeof(struct in6_addr)) + ++ /* IFLA_IPTUN_FMR_IP4_PREFIX */ ++ nla_total_size(sizeof(struct in_addr)) + ++ /* IFLA_IPTUN_FMR_EA_LEN */ ++ nla_total_size(1) + ++ /* IFLA_IPTUN_FMR_IP6_PREFIX_LEN */ ++ nla_total_size(1) + ++ /* IFLA_IPTUN_FMR_IP4_PREFIX_LEN */ ++ nla_total_size(1) + ++ /* IFLA_IPTUN_FMR_OFFSET */ ++ nla_total_size(1) ++ ) * fmrs + + 0; + } + +@@ -2166,6 +2409,9 @@ static int ip6_tnl_fill_info(struct sk_b + { + struct ip6_tnl *tunnel = netdev_priv(dev); + struct __ip6_tnl_parm *parm = &tunnel->parms; ++ struct __ip6_tnl_fmr *c; ++ int fmrcnt = 0; ++ struct nlattr *fmrs; + + if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || + nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || +@@ -2175,9 +2421,27 @@ static int ip6_tnl_fill_info(struct sk_b + nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || + nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || + nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || +- nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark)) ++ nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark) || ++ !(fmrs = nla_nest_start(skb, IFLA_IPTUN_FMRS))) + goto nla_put_failure; + ++ for (c = parm->fmrs; c; c = c->next) { ++ struct nlattr *fmr = nla_nest_start(skb, ++fmrcnt); ++ if (!fmr || ++ nla_put(skb, IFLA_IPTUN_FMR_IP6_PREFIX, ++ sizeof(c->ip6_prefix), &c->ip6_prefix) || ++ nla_put(skb, IFLA_IPTUN_FMR_IP4_PREFIX, ++ sizeof(c->ip4_prefix), &c->ip4_prefix) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, c->ip6_prefix_len) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, c->ip4_prefix_len) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_EA_LEN, c->ea_len) || ++ nla_put_u8(skb, IFLA_IPTUN_FMR_OFFSET, c->offset)) ++ goto nla_put_failure; ++ ++ nla_nest_end(skb, fmr); ++ } ++ nla_nest_end(skb, fmrs); ++ + if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || +@@ -2217,6 +2481,7 @@ static const struct nla_policy ip6_tnl_p + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, ++ [IFLA_IPTUN_FMRS] = { .type = NLA_NESTED }, + }; + + static struct rtnl_link_ops ip6_link_ops __read_mostly = { diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch new file mode 100644 index 0000000000..d85735531b --- /dev/null +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -0,0 +1,263 @@ +From: Jonas Gorski +Subject: ipv6: allow rejecting with "source address failed policy" + +RFC6204 L-14 requires rejecting traffic from invalid addresses with +ICMPv6 Destination Unreachable, Code 5 (Source address failed ingress/ +egress policy) on the LAN side, so add an appropriate rule for that. + +Signed-off-by: Jonas Gorski +--- + include/net/netns/ipv6.h | 1 + + include/uapi/linux/fib_rules.h | 4 +++ + include/uapi/linux/rtnetlink.h | 1 + + net/ipv4/fib_semantics.c | 4 +++ + net/ipv4/fib_trie.c | 1 + + net/ipv4/ipmr.c | 1 + + net/ipv6/fib6_rules.c | 4 +++ + net/ipv6/ip6mr.c | 2 ++ + net/ipv6/route.c | 58 +++++++++++++++++++++++++++++++++++++++++- + 9 files changed, 75 insertions(+), 1 deletion(-) + +--- a/include/net/netns/ipv6.h ++++ b/include/net/netns/ipv6.h +@@ -88,6 +88,7 @@ struct netns_ipv6 { + unsigned int fib6_routes_require_src; + #endif + struct rt6_info *ip6_prohibit_entry; ++ struct rt6_info *ip6_policy_failed_entry; + struct rt6_info *ip6_blk_hole_entry; + struct fib6_table *fib6_local_tbl; + struct fib_rules_ops *fib6_rules_ops; +--- a/include/uapi/linux/fib_rules.h ++++ b/include/uapi/linux/fib_rules.h +@@ -82,6 +82,10 @@ enum { + FR_ACT_BLACKHOLE, /* Drop without notification */ + FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ + FR_ACT_PROHIBIT, /* Drop with EACCES */ ++ FR_ACT_RES9, ++ FR_ACT_RES10, ++ FR_ACT_RES11, ++ FR_ACT_POLICY_FAILED, /* Drop with EACCES */ + __FR_ACT_MAX, + }; + +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -249,6 +249,7 @@ enum { + RTN_THROW, /* Not in this table */ + RTN_NAT, /* Translate this address */ + RTN_XRESOLVE, /* Use external resolver */ ++ RTN_POLICY_FAILED, /* Failed ingress/egress policy */ + __RTN_MAX + }; + +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -142,6 +142,10 @@ const struct fib_prop fib_props[RTN_MAX + .error = -EINVAL, + .scope = RT_SCOPE_NOWHERE, + }, ++ [RTN_POLICY_FAILED] = { ++ .error = -EACCES, ++ .scope = RT_SCOPE_UNIVERSE, ++ }, + }; + + static void rt_fibinfo_free(struct rtable __rcu **rtp) +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -2734,6 +2734,7 @@ static const char *const rtn_type_names[ + [RTN_THROW] = "THROW", + [RTN_NAT] = "NAT", + [RTN_XRESOLVE] = "XRESOLVE", ++ [RTN_POLICY_FAILED] = "POLICY_FAILED", + }; + + static inline const char *rtn_type(char *buf, size_t len, unsigned int t) +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -175,6 +175,7 @@ static int ipmr_rule_action(struct fib_r + case FR_ACT_UNREACHABLE: + return -ENETUNREACH; + case FR_ACT_PROHIBIT: ++ case FR_ACT_POLICY_FAILED: + return -EACCES; + case FR_ACT_BLACKHOLE: + default: +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -220,6 +220,10 @@ static int __fib6_rule_action(struct fib + err = -EACCES; + rt = net->ipv6.ip6_prohibit_entry; + goto discard_pkt; ++ case FR_ACT_POLICY_FAILED: ++ err = -EACCES; ++ rt = net->ipv6.ip6_policy_failed_entry; ++ goto discard_pkt; + } + + tb_id = fib_rule_get_table(rule, arg); +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -163,6 +163,8 @@ static int ip6mr_rule_action(struct fib_ + return -ENETUNREACH; + case FR_ACT_PROHIBIT: + return -EACCES; ++ case FR_ACT_POLICY_FAILED: ++ return -EACCES; + case FR_ACT_BLACKHOLE: + default: + return -EINVAL; +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -95,6 +95,8 @@ static int ip6_pkt_discard(struct sk_bu + static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); + static int ip6_pkt_prohibit(struct sk_buff *skb); + static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb); ++static int ip6_pkt_policy_failed(struct sk_buff *skb); ++static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb); + static void ip6_link_failure(struct sk_buff *skb); + static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, u32 mtu, +@@ -310,6 +312,18 @@ static const struct rt6_info ip6_prohibi + .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), + }; + ++static const struct rt6_info ip6_policy_failed_entry_template = { ++ .dst = { ++ .__refcnt = ATOMIC_INIT(1), ++ .__use = 1, ++ .obsolete = DST_OBSOLETE_FORCE_CHK, ++ .error = -EACCES, ++ .input = ip6_pkt_policy_failed, ++ .output = ip6_pkt_policy_failed_out, ++ }, ++ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), ++}; ++ + static const struct rt6_info ip6_blk_hole_entry_template = { + .dst = { + .__refcnt = ATOMIC_INIT(1), +@@ -1031,6 +1045,7 @@ static const int fib6_prop[RTN_MAX + 1] + [RTN_BLACKHOLE] = -EINVAL, + [RTN_UNREACHABLE] = -EHOSTUNREACH, + [RTN_PROHIBIT] = -EACCES, ++ [RTN_POLICY_FAILED] = -EACCES, + [RTN_THROW] = -EAGAIN, + [RTN_NAT] = -EINVAL, + [RTN_XRESOLVE] = -EINVAL, +@@ -1066,6 +1081,10 @@ static void ip6_rt_init_dst_reject(struc + rt->dst.output = ip6_pkt_prohibit_out; + rt->dst.input = ip6_pkt_prohibit; + break; ++ case RTN_POLICY_FAILED: ++ rt->dst.output = ip6_pkt_policy_failed_out; ++ rt->dst.input = ip6_pkt_policy_failed; ++ break; + case RTN_THROW: + case RTN_UNREACHABLE: + default: +@@ -4448,6 +4467,17 @@ static int ip6_pkt_prohibit_out(struct n + return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); + } + ++static int ip6_pkt_policy_failed(struct sk_buff *skb) ++{ ++ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES); ++} ++ ++static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb) ++{ ++ skb->dev = skb_dst(skb)->dev; ++ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES); ++} ++ + /* + * Allocate a dst for local (unicast / anycast) address. + */ +@@ -4928,7 +4958,8 @@ static int rtm_to_fib6_config(struct sk_ + if (rtm->rtm_type == RTN_UNREACHABLE || + rtm->rtm_type == RTN_BLACKHOLE || + rtm->rtm_type == RTN_PROHIBIT || +- rtm->rtm_type == RTN_THROW) ++ rtm->rtm_type == RTN_THROW || ++ rtm->rtm_type == RTN_POLICY_FAILED) + cfg->fc_flags |= RTF_REJECT; + + if (rtm->rtm_type == RTN_LOCAL) +@@ -6127,6 +6158,8 @@ static int ip6_route_dev_notify(struct n + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + net->ipv6.ip6_prohibit_entry->dst.dev = dev; + net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); ++ net->ipv6.ip6_policy_failed_entry->dst.dev = dev; ++ net->ipv6.ip6_policy_failed_entry->rt6i_idev = in6_dev_get(dev); + net->ipv6.ip6_blk_hole_entry->dst.dev = dev; + net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); + #endif +@@ -6138,6 +6171,7 @@ static int ip6_route_dev_notify(struct n + in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); ++ in6_dev_put_clear(&net->ipv6.ip6_policy_failed_entry->rt6i_idev); + in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); + #endif + } +@@ -6329,6 +6363,8 @@ static int __net_init ip6_route_net_init + + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + net->ipv6.fib6_has_custom_rules = false; ++ ++ + net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, + sizeof(*net->ipv6.ip6_prohibit_entry), + GFP_KERNEL); +@@ -6339,11 +6375,21 @@ static int __net_init ip6_route_net_init + ip6_template_metrics, true); + INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); + ++ net->ipv6.ip6_policy_failed_entry = ++ kmemdup(&ip6_policy_failed_entry_template, ++ sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL); ++ if (!net->ipv6.ip6_policy_failed_entry) ++ goto out_ip6_prohibit_entry; ++ net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops; ++ dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst, ++ ip6_template_metrics, true); ++ INIT_LIST_HEAD(&net->ipv6.ip6_policy_failed_entry->rt6i_uncached); ++ + net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, + sizeof(*net->ipv6.ip6_blk_hole_entry), + GFP_KERNEL); + if (!net->ipv6.ip6_blk_hole_entry) +- goto out_ip6_prohibit_entry; ++ goto out_ip6_policy_failed_entry; + net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, + ip6_template_metrics, true); +@@ -6370,6 +6416,8 @@ out: + return ret; + + #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++out_ip6_policy_failed_entry: ++ kfree(net->ipv6.ip6_policy_failed_entry); + out_ip6_prohibit_entry: + kfree(net->ipv6.ip6_prohibit_entry); + out_ip6_null_entry: +@@ -6389,6 +6437,7 @@ static void __net_exit ip6_route_net_exi + kfree(net->ipv6.ip6_null_entry); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + kfree(net->ipv6.ip6_prohibit_entry); ++ kfree(net->ipv6.ip6_policy_failed_entry); + kfree(net->ipv6.ip6_blk_hole_entry); + #endif + dst_entries_destroy(&net->ipv6.ip6_dst_ops); +@@ -6466,6 +6515,9 @@ void __init ip6_route_init_special_entri + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); ++ init_net.ipv6.ip6_policy_failed_entry->dst.dev = init_net.loopback_dev; ++ init_net.ipv6.ip6_policy_failed_entry->rt6i_idev = ++ in6_dev_get(init_net.loopback_dev); + #endif + } + diff --git a/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch b/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch new file mode 100644 index 0000000000..0e7f35db89 --- /dev/null +++ b/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch @@ -0,0 +1,50 @@ +From: Jonas Gorski +Subject: net: provide defines for _POLICY_FAILED until all code is updated + +Upstream introduced ICMPV6_POLICY_FAIL for code 5 of destination +unreachable, conflicting with our name. + +Add appropriate defines to allow our code to build with the new +name until we have updated our local patches for older kernels +and userspace packages. + +Signed-off-by: Jonas Gorski +--- + include/uapi/linux/fib_rules.h | 2 ++ + include/uapi/linux/icmpv6.h | 2 ++ + include/uapi/linux/rtnetlink.h | 2 ++ + 3 files changed, 6 insertions(+) + +--- a/include/uapi/linux/fib_rules.h ++++ b/include/uapi/linux/fib_rules.h +@@ -89,6 +89,8 @@ enum { + __FR_ACT_MAX, + }; + ++#define FR_ACT_FAILED_POLICY FR_ACT_POLICY_FAILED ++ + #define FR_ACT_MAX (__FR_ACT_MAX - 1) + + #endif +--- a/include/uapi/linux/icmpv6.h ++++ b/include/uapi/linux/icmpv6.h +@@ -126,6 +126,8 @@ struct icmp6hdr { + #define ICMPV6_POLICY_FAIL 5 + #define ICMPV6_REJECT_ROUTE 6 + ++#define ICMPV6_FAILED_POLICY ICMPV6_POLICY_FAIL ++ + /* + * Codes for Time Exceeded + */ +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -253,6 +253,8 @@ enum { + __RTN_MAX + }; + ++#define RTN_FAILED_POLICY RTN_POLICY_FAILED ++ + #define RTN_MAX (__RTN_MAX - 1) + + diff --git a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch new file mode 100644 index 0000000000..e64e0421e1 --- /dev/null +++ b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -0,0 +1,149 @@ +From: Felix Fietkau +Subject: net: replace GRO optimization patch with a new one that supports VLANs/bridges with different MAC addresses + +Signed-off-by: Felix Fietkau +--- + include/linux/netdevice.h | 2 ++ + include/linux/skbuff.h | 3 ++- + net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ + net/ethernet/eth.c | 18 +++++++++++++++++- + 4 files changed, 69 insertions(+), 2 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2036,6 +2036,8 @@ struct net_device { + struct netdev_hw_addr_list mc; + struct netdev_hw_addr_list dev_addrs; + ++ unsigned char local_addr_mask[MAX_ADDR_LEN]; ++ + #ifdef CONFIG_SYSFS + struct kset *queues_kset; + #endif +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -858,6 +858,7 @@ struct sk_buff { + #ifdef CONFIG_TLS_DEVICE + __u8 decrypted:1; + #endif ++ __u8 gro_skip:1; + + #ifdef CONFIG_NET_SCHED + __u16 tc_index; /* traffic control index */ +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6062,6 +6062,9 @@ static enum gro_result dev_gro_receive(s + int same_flow; + int grow; + ++ if (skb->gro_skip) ++ goto normal; ++ + if (netif_elide_gro(skb->dev)) + goto normal; + +@@ -8039,6 +8042,48 @@ static void __netdev_adjacent_dev_unlink + &upper_dev->adj_list.lower); + } + ++static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr, ++ struct net_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < dev->addr_len; i++) ++ mask[i] |= addr[i] ^ dev->dev_addr[i]; ++} ++ ++static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev, ++ struct net_device *lower) ++{ ++ struct net_device *cur; ++ struct list_head *iter; ++ ++ netdev_for_each_upper_dev_rcu(dev, cur, iter) { ++ __netdev_addr_mask(mask, cur->dev_addr, lower); ++ __netdev_upper_mask(mask, cur, lower); ++ } ++} ++ ++static void __netdev_update_addr_mask(struct net_device *dev) ++{ ++ unsigned char mask[MAX_ADDR_LEN]; ++ struct net_device *cur; ++ struct list_head *iter; ++ ++ memset(mask, 0, sizeof(mask)); ++ __netdev_upper_mask(mask, dev, dev); ++ memcpy(dev->local_addr_mask, mask, dev->addr_len); ++ ++ netdev_for_each_lower_dev(dev, cur, iter) ++ __netdev_update_addr_mask(cur); ++} ++ ++static void netdev_update_addr_mask(struct net_device *dev) ++{ ++ rcu_read_lock(); ++ __netdev_update_addr_mask(dev); ++ rcu_read_unlock(); ++} ++ + static int __netdev_upper_dev_link(struct net_device *dev, + struct net_device *upper_dev, bool master, + void *upper_priv, void *upper_info, +@@ -8090,6 +8135,7 @@ static int __netdev_upper_dev_link(struc + if (ret) + return ret; + ++ netdev_update_addr_mask(dev); + ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, + &changeupper_info.info); + ret = notifier_to_errno(ret); +@@ -8186,6 +8232,7 @@ static void __netdev_upper_dev_unlink(st + + __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); + ++ netdev_update_addr_mask(dev); + call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, + &changeupper_info.info); + +@@ -8972,6 +9019,7 @@ int dev_set_mac_address(struct net_devic + if (err) + return err; + dev->addr_assign_type = NET_ADDR_SET; ++ netdev_update_addr_mask(dev); + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + add_device_randomness(dev->dev_addr, dev->addr_len); + return 0; +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -143,6 +143,18 @@ u32 eth_get_headlen(const struct net_dev + } + EXPORT_SYMBOL(eth_get_headlen); + ++static inline bool ++eth_check_local_mask(const void *addr1, const void *addr2, const void *mask) ++{ ++ const u16 *a1 = addr1; ++ const u16 *a2 = addr2; ++ const u16 *m = mask; ++ ++ return (((a1[0] ^ a2[0]) & ~m[0]) | ++ ((a1[1] ^ a2[1]) & ~m[1]) | ++ ((a1[2] ^ a2[2]) & ~m[2])); ++} ++ + /** + * eth_type_trans - determine the packet's protocol ID. + * @skb: received socket data +@@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk + } else { + skb->pkt_type = PACKET_OTHERHOST; + } ++ ++ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, ++ dev->local_addr_mask)) ++ skb->gro_skip = 1; + } + + /* diff --git a/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch b/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch new file mode 100644 index 0000000000..82e81f37c5 --- /dev/null +++ b/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch @@ -0,0 +1,89 @@ +From 844c273286f328acf0dab5fbd5d864366b4904dc Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 30 Mar 2021 18:21:14 +0200 +Subject: [PATCH] of_net: add mac-address-increment support + +Lots of embedded devices use the mac-address of other interface +extracted from nvmem cells and increments it by one or two. Add two +bindings to integrate this and directly use the right mac-address for +the interface. Some example are some routers that use the gmac +mac-address stored in the art partition and increments it by one for the +wifi. mac-address-increment-byte bindings is used to tell what byte of +the mac-address has to be increased (if not defined the last byte is +increased) and mac-address-increment tells how much the byte decided +early has to be increased. + +Signed-off-by: Ansuel Smith +--- + drivers/of/of_net.c | 43 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 39 insertions(+), 4 deletions(-) + +--- a/drivers/of/of_net.c ++++ b/drivers/of/of_net.c +@@ -115,27 +115,62 @@ static int of_get_mac_addr_nvmem(struct + * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists + * but is all zeros. + * ++ * DT can tell the system to increment the mac-address after is extracted by ++ * using: ++ * - mac-address-increment-byte to decide what byte to increase ++ * (if not defined is increased the last byte) ++ * - mac-address-increment to decide how much to increase. The value WILL ++ * overflow to other bytes if the increment is over 255 or the total ++ * increment will exceed 255 of the current byte. ++ * (example 00:01:02:03:04:ff + 1 == 00:01:02:03:05:00) ++ * (example 00:01:02:03:04:fe + 5 == 00:01:02:03:05:03) ++ * + * Return: 0 on success and errno in case of error. + */ + int of_get_mac_address(struct device_node *np, u8 *addr) + { ++ u32 inc_idx, mac_inc, mac_val; + int ret; + ++ /* Check first if the increment byte is present and valid. ++ * If not set assume to increment the last byte if found. ++ */ ++ if (of_property_read_u32(np, "mac-address-increment-byte", &inc_idx)) ++ inc_idx = 5; ++ if (inc_idx < 3 || inc_idx > 5) ++ return -EINVAL; ++ + if (!np) + return -ENODEV; + + ret = of_get_mac_addr(np, "mac-address", addr); + if (!ret) +- return 0; ++ goto found; + + ret = of_get_mac_addr(np, "local-mac-address", addr); + if (!ret) +- return 0; ++ goto found; + + ret = of_get_mac_addr(np, "address", addr); + if (!ret) +- return 0; ++ goto found; ++ ++ ret = of_get_mac_addr_nvmem(np, addr); ++ if (ret) ++ return ret; ++ ++found: ++ if (!of_property_read_u32(np, "mac-address-increment", &mac_inc)) { ++ /* Convert to a contiguous value */ ++ mac_val = (addr[3] << 16) + (addr[4] << 8) + addr[5]; ++ mac_val += mac_inc << 8 * (5-inc_idx); ++ ++ /* Apply the incremented value handling overflow case */ ++ addr[3] = (mac_val >> 16) & 0xff; ++ addr[4] = (mac_val >> 8) & 0xff; ++ addr[5] = (mac_val >> 0) & 0xff; ++ } + +- return of_get_mac_addr_nvmem(np, addr); ++ return ret; + } + EXPORT_SYMBOL(of_get_mac_address); diff --git a/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch new file mode 100644 index 0000000000..03cd763d9d --- /dev/null +++ b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch @@ -0,0 +1,38 @@ +--- a/drivers/of/of_net.c ++++ b/drivers/of/of_net.c +@@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct + return 0; + } + ++static int of_add_mac_address(struct device_node *np, u8* addr) ++{ ++ struct property *prop; ++ ++ prop = kzalloc(sizeof(*prop), GFP_KERNEL); ++ if (!prop) ++ return -ENOMEM; ++ ++ prop->name = "mac-address"; ++ prop->length = ETH_ALEN; ++ prop->value = kmemdup(addr, ETH_ALEN, GFP_KERNEL); ++ if (!prop->value || of_update_property(np, prop)) ++ goto free; ++ ++ return 0; ++free: ++ kfree(prop->value); ++ kfree(prop); ++ return -ENOMEM; ++} ++ + /** + * Search the device tree for the best MAC address to use. 'mac-address' is + * checked first, because that is supposed to contain to "most recent" MAC +@@ -171,6 +192,7 @@ found: + addr[5] = (mac_val >> 0) & 0xff; + } + ++ of_add_mac_address(np, addr); + return ret; + } + EXPORT_SYMBOL(of_get_mac_address); diff --git a/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch b/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch new file mode 100644 index 0000000000..ff090f07f1 --- /dev/null +++ b/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch @@ -0,0 +1,26 @@ +From: Felix Fietkau +Date: Thu, 8 Jul 2021 07:08:29 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: avoid creating duplicate offload + entries + +Sometimes multiple CLS_REPLACE calls are issued for the same connection. +rhashtable_insert_fast does not check for these duplicates, so multiple +hardware flow entries can be created. +Fix this by checking for an existing entry early + +Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -187,6 +187,9 @@ mtk_flow_offload_replace(struct mtk_eth + int hash; + int i; + ++ if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) ++ return -EEXIST; ++ + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { + struct flow_match_meta match; + diff --git a/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch b/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch new file mode 100644 index 0000000000..7140c6877e --- /dev/null +++ b/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch @@ -0,0 +1,65 @@ +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -20,6 +21,11 @@ struct mtk_flow_data { + __be32 src_addr; + __be32 dst_addr; + } v4; ++ ++ struct { ++ struct in6_addr src_addr; ++ struct in6_addr dst_addr; ++ } v6; + }; + + __be16 src_port; +@@ -64,6 +70,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en + data->v4.dst_addr, data->dst_port); + } + ++static int ++mtk_flow_set_ipv6_addr(struct mtk_foe_entry *foe, struct mtk_flow_data *data) ++{ ++ return mtk_foe_entry_set_ipv6_tuple(foe, ++ data->v6.src_addr.s6_addr32, data->src_port, ++ data->v6.dst_addr.s6_addr32, data->dst_port); ++} ++ + static void + mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth) + { +@@ -254,6 +268,9 @@ mtk_flow_offload_replace(struct mtk_eth + case FLOW_DISSECTOR_KEY_IPV4_ADDRS: + offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; + break; ++ case FLOW_DISSECTOR_KEY_IPV6_ADDRS: ++ offload_type = MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T; ++ break; + default: + return -EOPNOTSUPP; + } +@@ -289,6 +306,17 @@ mtk_flow_offload_replace(struct mtk_eth + mtk_flow_set_ipv4_addr(&foe, &data, false); + } + ++ if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { ++ struct flow_match_ipv6_addrs addrs; ++ ++ flow_rule_match_ipv6_addrs(rule, &addrs); ++ ++ data.v6.src_addr = addrs.key->src; ++ data.v6.dst_addr = addrs.key->dst; ++ ++ mtk_flow_set_ipv6_addr(&foe, &data); ++ } ++ + flow_action_for_each(i, act, &rule->action) { + if (act->id != FLOW_ACTION_MANGLE) + continue; diff --git a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch new file mode 100644 index 0000000000..da9c040322 --- /dev/null +++ b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +Date: Mon, 21 Mar 2022 20:39:59 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: enable threaded NAPI + +This can improve performance under load by ensuring that NAPI processing is +not pinned on CPU 0. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2171,8 +2171,8 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- __napi_schedule(ð->rx_napi); + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); ++ __napi_schedule(ð->rx_napi); + } + + return IRQ_HANDLED; +@@ -2184,8 +2184,8 @@ static irqreturn_t mtk_handle_irq_tx(int + + eth->tx_events++; + if (likely(napi_schedule_prep(ð->tx_napi))) { +- __napi_schedule(ð->tx_napi); + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); ++ __napi_schedule(ð->tx_napi); + } + + return IRQ_HANDLED; +@@ -3229,6 +3229,8 @@ static int mtk_probe(struct platform_dev + * for NAPI to work + */ + init_dummy_netdev(ð->dummy_dev); ++ eth->dummy_dev.threaded = 1; ++ strcpy(eth->dummy_dev.name, "mtk_eth"); + netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx, + MTK_NAPI_WEIGHT); + netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx, diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch new file mode 100644 index 0000000000..52350ecccc --- /dev/null +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -0,0 +1,38 @@ +From: Gabor Juhos +Subject: generic: add detach callback to struct phy_driver + +lede-commit: fe61fc2d7d0b3fb348b502f68f98243b3ddf5867 + +Signed-off-by: Gabor Juhos +--- + drivers/net/phy/phy_device.c | 3 +++ + include/linux/phy.h | 6 ++++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1651,6 +1651,9 @@ void phy_detach(struct phy_device *phyde + struct module *ndev_owner = NULL; + struct mii_bus *bus; + ++ if (phydev->drv && phydev->drv->detach) ++ phydev->drv->detach(phydev); ++ + if (phydev->sysfs_links) { + if (dev) + sysfs_remove_link(&dev->dev.kobj, "phydev"); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -765,6 +765,12 @@ struct phy_driver { + /** @handle_interrupt: Override default interrupt handling */ + irqreturn_t (*handle_interrupt)(struct phy_device *phydev); + ++ /* ++ * Called before an ethernet device is detached ++ * from the PHY. ++ */ ++ void (*detach)(struct phy_device *phydev); ++ + /** @remove: Clears up any memory if needed */ + void (*remove)(struct phy_device *phydev); + diff --git a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch new file mode 100644 index 0000000000..ecd6e9e7a2 --- /dev/null +++ b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -0,0 +1,177 @@ +From: Felix Fietkau +Date: Fri, 27 Aug 2021 12:22:32 +0200 +Subject: [PATCH] bridge: add knob for filtering rx/tx BPDU packets on a port + +Some devices (e.g. wireless APs) can't have devices behind them be part of +a bridge topology with redundant links, due to address limitations. +Additionally, broadcast traffic on these devices is somewhat expensive, due to +the low data rate and wakeups of clients in powersave mode. +This knob can be used to ensure that BPDU packets are never sent or forwarded +to/from these devices + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -56,6 +56,7 @@ struct br_ip_list { + #define BR_MRP_AWARE BIT(17) + #define BR_MRP_LOST_CONT BIT(18) + #define BR_MRP_LOST_IN_CONT BIT(19) ++#define BR_BPDU_FILTER BIT(20) + + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -191,6 +191,7 @@ out: + void br_flood(struct net_bridge *br, struct sk_buff *skb, + enum br_pkt_type pkt_type, bool local_rcv, bool local_orig) + { ++ const unsigned char *dest = eth_hdr(skb)->h_dest; + struct net_bridge_port *prev = NULL; + struct net_bridge_port *p; + +@@ -206,6 +207,10 @@ void br_flood(struct net_bridge *br, str + case BR_PKT_MULTICAST: + if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) + continue; ++ if ((p->flags & BR_BPDU_FILTER) && ++ unlikely(is_link_local_ether_addr(dest) && ++ dest[5] == 0)) ++ continue; + break; + case BR_PKT_BROADCAST: + if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -305,6 +305,8 @@ static rx_handler_result_t br_handle_fra + fwd_mask |= p->group_fwd_mask; + switch (dest[5]) { + case 0x00: /* Bridge Group Address */ ++ if (p->flags & BR_BPDU_FILTER) ++ goto drop; + /* If STP is turned off, + then must forward to keep loop detection */ + if (p->br->stp_enabled == BR_NO_STP || +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -233,6 +233,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA + BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); + BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); + BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); ++BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER); + + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +@@ -285,6 +286,7 @@ static const struct brport_attribute *br + &brport_attr_group_fwd_mask, + &brport_attr_neigh_suppress, + &brport_attr_isolated, ++ &brport_attr_bpdu_filter, + &brport_attr_backup_port, + NULL + }; +--- a/net/bridge/br_stp_bpdu.c ++++ b/net/bridge/br_stp_bpdu.c +@@ -80,7 +80,8 @@ void br_send_config_bpdu(struct net_brid + { + unsigned char buf[35]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -127,7 +128,8 @@ void br_send_tcn_bpdu(struct net_bridge_ + { + unsigned char buf[4]; + +- if (p->br->stp_enabled != BR_KERNEL_STP) ++ if (p->br->stp_enabled != BR_KERNEL_STP || ++ (p->flags & BR_BPDU_FILTER)) + return; + + buf[0] = 0; +@@ -172,6 +174,9 @@ void br_stp_rcv(const struct stp_proto * + if (!(br->dev->flags & IFF_UP)) + goto out; + ++ if (p->flags & BR_BPDU_FILTER) ++ goto out; ++ + if (p->state == BR_STATE_DISABLED) + goto out; + +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -524,6 +524,7 @@ enum { + IFLA_BRPORT_BACKUP_PORT, + IFLA_BRPORT_MRP_RING_OPEN, + IFLA_BRPORT_MRP_IN_OPEN, ++ IFLA_BRPORT_BPDU_FILTER, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -137,6 +137,7 @@ static inline size_t br_port_info_size(v + + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ + + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */ + + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ ++ + nla_total_size(1) /* IFLA_BRPORT_BPDU_FILTER */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ +@@ -220,7 +221,8 @@ static int br_port_fill_attrs(struct sk_ + BR_MRP_LOST_CONT)) || + nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN, + !!(p->flags & BR_MRP_LOST_IN_CONT)) || +- nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) ++ nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) || ++ nla_put_u8(skb, IFLA_BRPORT_BPDU_FILTER, !!(p->flags & BR_BPDU_FILTER))) + return -EMSGSIZE; + + timerval = br_timer_value(&p->message_age_timer); +@@ -728,6 +730,7 @@ static const struct nla_policy br_port_p + [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 }, + [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, + [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, ++ [IFLA_BRPORT_BPDU_FILTER] = { .type = NLA_U8 }, + }; + + /* Change the state of the port and notify spanning tree */ +@@ -826,6 +829,10 @@ static int br_setport(struct net_bridge_ + if (err) + return err; + ++ err = br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); ++ if (err) ++ return err; ++ + br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false; + err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); + if (err) +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -55,7 +55,7 @@ + #include + + #define RTNL_MAX_TYPE 50 +-#define RTNL_SLAVE_MAX_TYPE 36 ++#define RTNL_SLAVE_MAX_TYPE 37 + + struct rtnl_link { + rtnl_doit_func doit; +@@ -4684,7 +4684,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu + brport_nla_put_flag(skb, flags, mask, + IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) || + brport_nla_put_flag(skb, flags, mask, +- IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD)) { ++ IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD) || ++ brport_nla_put_flag(skb, flags, mask, ++ IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER)) { + nla_nest_cancel(skb, protinfo); + goto nla_put_failure; + } diff --git a/target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch b/target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch new file mode 100644 index 0000000000..c49bb19601 --- /dev/null +++ b/target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch @@ -0,0 +1,66 @@ +From 97ca310aa18a93329ef5cd68c20de89761962f45 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 13 Jun 2021 12:19:36 +0200 +Subject: [PATCH] net: phy: at803x: fix feature detection + +AR8031/AR8033 have different status registers for copper +and fiber operation. However, the extended status register +is the same for both operation modes. + +As a result of that, ESTATUS_1000_XFULL is set to 1 even when +operating in copper TP mode. + +Remove this mode from the supported link modes, as this driver +currently only supports copper operation. + +Signed-off-by: David Bauer +--- + drivers/net/phy/at803x.c | 30 +++++++++++++++++++++++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1032,6 +1032,34 @@ static int at803x_set_tunable(struct phy + } + } + ++static int at803x_get_features(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = genphy_read_abilities(phydev); ++ if (err) ++ return err; ++ ++ if (!at803x_match_phy_id(phydev, ATH8031_PHY_ID)) ++ return 0; ++ ++ /* AR8031/AR8033 have different status registers ++ * for copper and fiber operation. However, the ++ * extended status register is the same for both ++ * operation modes. ++ * ++ * As a result of that, ESTATUS_1000_XFULL is set ++ * to 1 even when operating in copper TP mode. ++ * ++ * Remove this mode from the supported link modes, ++ * as this driver currently only supports copper ++ * operation. ++ */ ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, ++ phydev->supported); ++ return 0; ++} ++ + static int at803x_cable_test_result_trans(u16 status) + { + switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +@@ -1364,7 +1392,7 @@ static struct phy_driver at803x_driver[] + .resume = at803x_resume, + .read_page = at803x_read_page, + .write_page = at803x_write_page, +- /* PHY_GBIT_FEATURES */ ++ .get_features = at803x_get_features, + .read_status = at803x_read_status, + .aneg_done = at803x_aneg_done, + .ack_interrupt = &at803x_ack_interrupt, diff --git a/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch b/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch new file mode 100644 index 0000000000..16be95ea38 --- /dev/null +++ b/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch @@ -0,0 +1,27 @@ +From a1b291f3f6c80a6c5ccad7283fc472d77a2a4763 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sun, 22 Dec 2019 12:40:11 +0000 +Subject: [PATCH] net: dsa: mv88e6xxx: fix vlan setup + +Provide an option that drivers can set to indicate they want to receive +vlan configuration even when vlan filtering is disabled. This is safe +for Marvell DSA bridges, which do not look up ingress traffic in the +VTU if the port is in 8021Q disabled state. Whether this change is +suitable for all DSA bridges is not known. + +Signed-off-by: Russell King +Signed-off-by: DENG Qingfang +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -2869,6 +2869,7 @@ static int mv88e6xxx_setup(struct dsa_sw + + chip->ds = ds; + ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); ++ ds->configure_vlan_while_not_filtering = true; + + mv88e6xxx_reg_lock(chip); + diff --git a/target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch b/target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch new file mode 100644 index 0000000000..fbc8342b0e --- /dev/null +++ b/target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch @@ -0,0 +1,77 @@ +From 46fe6cecb296d850c1ee2b333e57093ac4b733f3 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Sat, 16 Jan 2021 02:25:09 +0100 +Subject: [PATCH] net: bridge: switchdev: Refactor br_switchdev_fdb_notify + +Instead of having to add more and more arguments to +br_switchdev_fdb_call_notifiers, get rid of it and build the info +struct directly in br_switchdev_fdb_notify. + +Signed-off-by: Tobias Waldekranz +Reviewed-by: Vladimir Oltean +--- + net/bridge/br_switchdev.c | 41 +++++++++++---------------------------- + 1 file changed, 11 insertions(+), 30 deletions(-) + +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -102,25 +102,16 @@ int br_switchdev_set_port_flag(struct ne + return 0; + } + +-static void +-br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, +- u16 vid, struct net_device *dev, +- bool added_by_user, bool offloaded) +-{ +- struct switchdev_notifier_fdb_info info; +- unsigned long notifier_type; +- +- info.addr = mac; +- info.vid = vid; +- info.added_by_user = added_by_user; +- info.offloaded = offloaded; +- notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; +- call_switchdev_notifiers(notifier_type, dev, &info.info, NULL); +-} +- + void + br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) + { ++ struct switchdev_notifier_fdb_info info = { ++ .addr = fdb->key.addr.addr, ++ .vid = fdb->key.vlan_id, ++ .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), ++ .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), ++ }; ++ + if (!fdb->dst) + return; + if (test_bit(BR_FDB_LOCAL, &fdb->flags)) +@@ -128,22 +119,12 @@ br_switchdev_fdb_notify(const struct net + + switch (type) { + case RTM_DELNEIGH: +- br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr, +- fdb->key.vlan_id, +- fdb->dst->dev, +- test_bit(BR_FDB_ADDED_BY_USER, +- &fdb->flags), +- test_bit(BR_FDB_OFFLOADED, +- &fdb->flags)); ++ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, ++ fdb->dst->dev, &info.info, NULL); + break; + case RTM_NEWNEIGH: +- br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr, +- fdb->key.vlan_id, +- fdb->dst->dev, +- test_bit(BR_FDB_ADDED_BY_USER, +- &fdb->flags), +- test_bit(BR_FDB_OFFLOADED, +- &fdb->flags)); ++ call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, ++ fdb->dst->dev, &info.info, NULL); + break; + } + } diff --git a/target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch b/target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch new file mode 100644 index 0000000000..41374c88df --- /dev/null +++ b/target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch @@ -0,0 +1,42 @@ +From ec5be4f79026282925ae383caa431a8d41e3456a Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Sat, 16 Jan 2021 02:25:10 +0100 +Subject: [PATCH] net: bridge: switchdev: Include local flag in FDB + notifications + +Some switchdev drivers, notably DSA, ignore all dynamically learned +address notifications (!added_by_user) as these are autonomously added +by the switch. Previously, such a notification was indistinguishable +from a local address notification. Include a local bit in the +notification so that the two classes can be discriminated. + +This allows DSA-like devices to add local addresses to the hardware +FDB (with the CPU as the destination), thereby avoiding flows towards +the CPU being flooded by the switch as unknown unicast. + +Signed-off-by: Tobias Waldekranz +--- + include/net/switchdev.h | 1 + + net/bridge/br_switchdev.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/include/net/switchdev.h ++++ b/include/net/switchdev.h +@@ -224,6 +224,7 @@ struct switchdev_notifier_fdb_info { + const unsigned char *addr; + u16 vid; + u8 added_by_user:1, ++ local:1, + offloaded:1; + }; + +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -109,6 +109,7 @@ br_switchdev_fdb_notify(const struct net + .addr = fdb->key.addr.addr, + .vid = fdb->key.vlan_id, + .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), ++ .local = test_bit(BR_FDB_LOCAL, &fdb->flags), + .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), + }; + diff --git a/target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch b/target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch new file mode 100644 index 0000000000..630e03bbfd --- /dev/null +++ b/target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch @@ -0,0 +1,96 @@ +From 2e50fd9322047253c327550b4485cf8761035a8c Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Sat, 16 Jan 2021 02:25:11 +0100 +Subject: [PATCH] net: bridge: switchdev: Send FDB notifications for host + addresses + +Treat addresses added to the bridge itself in the same way as regular +ports and send out a notification so that drivers may sync it down to +the hardware FDB. + +Signed-off-by: Tobias Waldekranz +--- + net/bridge/br_fdb.c | 4 ++-- + net/bridge/br_private.h | 7 ++++--- + net/bridge/br_switchdev.c | 11 +++++------ + 3 files changed, 11 insertions(+), 11 deletions(-) + +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -602,7 +602,7 @@ void br_fdb_update(struct net_bridge *br + /* fastpath: update of existing entry */ + if (unlikely(source != fdb->dst && + !test_bit(BR_FDB_STICKY, &fdb->flags))) { +- br_switchdev_fdb_notify(fdb, RTM_DELNEIGH); ++ br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH); + fdb->dst = source; + fdb_modified = true; + /* Take over HW learned entry */ +@@ -735,7 +735,7 @@ static void fdb_notify(struct net_bridge + int err = -ENOBUFS; + + if (swdev_notify) +- br_switchdev_fdb_notify(fdb, type); ++ br_switchdev_fdb_notify(br, fdb, type); + + skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); + if (skb == NULL) +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1525,8 +1525,8 @@ bool nbp_switchdev_allowed_egress(const + int br_switchdev_set_port_flag(struct net_bridge_port *p, + unsigned long flags, + unsigned long mask); +-void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, +- int type); ++void br_switchdev_fdb_notify(struct net_bridge *br, ++ const struct net_bridge_fdb_entry *fdb, int type); + int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, + struct netlink_ext_ack *extack); + int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid); +@@ -1572,7 +1572,8 @@ static inline int br_switchdev_port_vlan + } + + static inline void +-br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) ++br_switchdev_fdb_notify(struct net_bridge *br, ++ const struct net_bridge_fdb_entry *fdb, int type) + { + } + +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -103,7 +103,8 @@ int br_switchdev_set_port_flag(struct ne + } + + void +-br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) ++br_switchdev_fdb_notify(struct net_bridge *br, ++ const struct net_bridge_fdb_entry *fdb, int type) + { + struct switchdev_notifier_fdb_info info = { + .addr = fdb->key.addr.addr, +@@ -112,20 +113,19 @@ br_switchdev_fdb_notify(const struct net + .local = test_bit(BR_FDB_LOCAL, &fdb->flags), + .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), + }; ++ struct net_device *dev = fdb->dst ? fdb->dst->dev : br->dev; + +- if (!fdb->dst) +- return; + if (test_bit(BR_FDB_LOCAL, &fdb->flags)) + return; + + switch (type) { + case RTM_DELNEIGH: + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, +- fdb->dst->dev, &info.info, NULL); ++ dev, &info.info, NULL); + break; + case RTM_NEWNEIGH: + call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, +- fdb->dst->dev, &info.info, NULL); ++ dev, &info.info, NULL); + break; + } + } diff --git a/target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch b/target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch new file mode 100644 index 0000000000..c0b4fd1d14 --- /dev/null +++ b/target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch @@ -0,0 +1,36 @@ +From dd082716b43a3684b2f473ae5d1e76d1c076d86d Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Sat, 16 Jan 2021 02:25:12 +0100 +Subject: [PATCH] net: dsa: Include local addresses in assisted CPU port + learning + +Add local addresses (i.e. the ports' MAC addresses) to the hardware +FDB when assisted CPU port learning is enabled. + +NOTE: The bridge's own MAC address is also "local". If that address is +not shared with any port, the bridge's MAC is not be added by this +functionality - but the following commit takes care of that case. + +Signed-off-by: Tobias Waldekranz +--- + net/dsa/slave.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2192,10 +2192,12 @@ static int dsa_slave_switchdev_event(str + fdb_info = ptr; + + if (dsa_slave_dev_check(dev)) { +- if (!fdb_info->added_by_user) +- return NOTIFY_OK; +- + dp = dsa_slave_to_port(dev); ++ ++ if (fdb_info->local && dp->ds->assisted_learning_on_cpu_port) ++ dp = dp->cpu_dp; ++ else if (!fdb_info->added_by_user) ++ return NOTIFY_OK; + } else { + /* Snoop addresses learnt on foreign interfaces + * bridged with us, for switches that don't diff --git a/target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch b/target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch new file mode 100644 index 0000000000..0b644d8300 --- /dev/null +++ b/target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch @@ -0,0 +1,30 @@ +From 0663ebde114a6fb2c28c622ba5212b302d4d2581 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Sat, 16 Jan 2021 02:25:13 +0100 +Subject: [PATCH] net: dsa: Include bridge addresses in assisted CPU port + learning + +Now that notifications are sent out for addresses added to the bridge +itself, extend DSA to include those addresses in the hardware FDB when +assisted CPU port learning is enabled. + +Signed-off-by: Tobias Waldekranz +--- + net/dsa/slave.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2206,7 +2206,11 @@ static int dsa_slave_switchdev_event(str + struct net_device *br_dev; + struct dsa_slave_priv *p; + +- br_dev = netdev_master_upper_dev_get_rcu(dev); ++ if (netif_is_bridge_master(dev)) ++ br_dev = dev; ++ else ++ br_dev = netdev_master_upper_dev_get_rcu(dev); ++ + if (!br_dev) + return NOTIFY_DONE; + diff --git a/target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch b/target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch new file mode 100644 index 0000000000..f71ea16b97 --- /dev/null +++ b/target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch @@ -0,0 +1,56 @@ +From 81e39fd78db82fb51b05fff309b9c521f1a0bc5a Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Sat, 16 Jan 2021 02:25:14 +0100 +Subject: [PATCH] net: dsa: Sync static FDB entries on foreign interfaces to + hardware + +Reuse the "assisted_learning_on_cpu_port" functionality to always add +entries for user-configured entries on foreign interfaces, even if +assisted_learning_on_cpu_port is not enabled. E.g. in this situation: + + br0 + / \ +swp0 dummy0 + +$ bridge fdb add 02:00:de:ad:00:01 dev dummy0 vlan 1 master + +Results in DSA adding an entry in the hardware FDB, pointing this +address towards the CPU port. + +The same is true for entries added to the bridge itself, e.g: + +$ bridge fdb add 02:00:de:ad:00:01 dev br0 vlan 1 self + +Signed-off-by: Tobias Waldekranz +--- + net/dsa/slave.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2199,9 +2199,12 @@ static int dsa_slave_switchdev_event(str + else if (!fdb_info->added_by_user) + return NOTIFY_OK; + } else { +- /* Snoop addresses learnt on foreign interfaces +- * bridged with us, for switches that don't +- * automatically learn SA from CPU-injected traffic ++ /* Snoop addresses added to foreign interfaces ++ * bridged with us, or the bridge ++ * itself. Dynamically learned addresses can ++ * also be added for switches that don't ++ * automatically learn SA from CPU-injected ++ * traffic. + */ + struct net_device *br_dev; + struct dsa_slave_priv *p; +@@ -2223,7 +2226,8 @@ static int dsa_slave_switchdev_event(str + + dp = p->dp->cpu_dp; + +- if (!dp->ds->assisted_learning_on_cpu_port) ++ if (!fdb_info->added_by_user && ++ !dp->ds->assisted_learning_on_cpu_port) + return NOTIFY_DONE; + } + diff --git a/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch new file mode 100644 index 0000000000..9247401140 --- /dev/null +++ b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -0,0 +1,27 @@ +From: Tobias Waldekranz +Subject: [RFC net-next 7/7] net: dsa: mv88e6xxx: Request assisted learning on CPU port +Date: Sat, 16 Jan 2021 02:25:15 +0100 +Archived-At: + +While the hardware is capable of performing learning on the CPU port, +it requires alot of additions to the bridge's forwarding path in order +to handle multi-destination traffic correctly. + +Until that is in place, opt for the next best thing and let DSA sync +the relevant addresses down to the hardware FDB. + +Signed-off-by: Tobias Waldekranz +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5436,6 +5436,7 @@ static int mv88e6xxx_register_switch(str + ds->ops = &mv88e6xxx_switch_ops; + ds->ageing_time_min = chip->info->age_time_coeff; + ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; ++ ds->assisted_learning_on_cpu_port = true; + + dev_set_drvdata(dev, ds); + diff --git a/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch b/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch new file mode 100644 index 0000000000..fcf7892c04 --- /dev/null +++ b/target/linux/generic/pending-5.15/780-ARM-kirkwood-add-missing-linux-if_ether.h-for-ETH_AL.patch @@ -0,0 +1,61 @@ +From patchwork Thu Aug 5 22:23:30 2021 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 12422209 +Date: Thu, 5 Aug 2021 23:23:30 +0100 +From: Daniel Golle +To: linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org, + linux-kernel@vger.kernel.org +Cc: "David S. Miller" , Andrew Lunn , + Michael Walle +Subject: [PATCH] ARM: kirkwood: add missing for ETH_ALEN +Message-ID: +MIME-Version: 1.0 +Content-Disposition: inline +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.34 +Precedence: list +List-Id: +List-Archive: +Sender: "linux-arm-kernel" + +After commit 83216e3988cd1 ("of: net: pass the dst buffer to +of_get_mac_address()") build fails for kirkwood as ETH_ALEN is not +defined. + +arch/arm/mach-mvebu/kirkwood.c: In function 'kirkwood_dt_eth_fixup': +arch/arm/mach-mvebu/kirkwood.c:87:13: error: 'ETH_ALEN' undeclared (first use in this function); did you mean 'ESTALE'? + u8 tmpmac[ETH_ALEN]; + ^~~~~~~~ + ESTALE +arch/arm/mach-mvebu/kirkwood.c:87:13: note: each undeclared identifier is reported only once for each function it appears in +arch/arm/mach-mvebu/kirkwood.c:87:6: warning: unused variable 'tmpmac' [-Wunused-variable] + u8 tmpmac[ETH_ALEN]; + ^~~~~~ +make[5]: *** [scripts/Makefile.build:262: arch/arm/mach-mvebu/kirkwood.o] Error 1 +make[5]: *** Waiting for unfinished jobs.... + +Add missing #include to fix this. + +Cc: David S. Miller +Cc: Andrew Lunn +Cc: Michael Walle +Reported-by: https://buildbot.openwrt.org/master/images/#/builders/56/builds/220/steps/44/logs/stdio +Fixes: 83216e3988cd1 ("of: net: pass the dst buffer to of_get_mac_address()") +Signed-off-by: Daniel Golle +--- + arch/arm/mach-mvebu/kirkwood.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/mach-mvebu/kirkwood.c ++++ b/arch/arm/mach-mvebu/kirkwood.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch new file mode 100644 index 0000000000..511a9f7555 --- /dev/null +++ b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch @@ -0,0 +1,64 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] bcma: get SoC device struct & copy its DMA params to the + subdevices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For bus devices to be fully usable it's required to set their DMA +parameters. + +For years it has been missing and remained unnoticed because of +mips_dma_alloc_coherent() silently handling the empty coherent_dma_mask. +Kernel 4.19 came with a lot of DMA changes and caused a regression on +the bcm47xx. Starting with the commit f8c55dc6e828 ("MIPS: use generic +dma noncoherent ops for simple noncoherent platforms") DMA coherent +allocations just fail. Example: +[ 1.114914] bgmac_bcma bcma0:2: Allocation of TX ring 0x200 failed +[ 1.121215] bgmac_bcma bcma0:2: Unable to alloc memory for DMA +[ 1.127626] bgmac_bcma: probe of bcma0:2 failed with error -12 +[ 1.133838] bgmac_bcma: Broadcom 47xx GBit MAC driver loaded + +This change fixes above regression in addition to the MIPS bcm47xx +commit 321c46b91550 ("MIPS: BCM47XX: Setup struct device for the SoC"). + +It also fixes another *old* GPIO regression caused by a parent pointing +to the NULL: +[ 0.157054] missing gpiochip .dev parent pointer +[ 0.157287] bcma: bus0: Error registering GPIO driver: -22 +introduced by the commit 74f4e0cc6108 ("bcma: switch GPIO portions to +use GPIOLIB_IRQCHIP"). + +Fixes: f8c55dc6e828 ("MIPS: use generic dma noncoherent ops for simple noncoherent platforms") +Fixes: 74f4e0cc6108 ("bcma: switch GPIO portions to use GPIOLIB_IRQCHIP") +Cc: linux-mips@linux-mips.org +Cc: Christoph Hellwig +Cc: Linus Walleij +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/bcma/host_soc.c ++++ b/drivers/bcma/host_soc.c +@@ -191,6 +191,8 @@ int __init bcma_host_soc_init(struct bcm + struct bcma_bus *bus = &soc->bus; + int err; + ++ bus->dev = soc->dev; ++ + /* Scan bus and initialize it */ + err = bcma_bus_early_register(bus); + if (err) +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -241,8 +241,10 @@ void bcma_prepare_core(struct bcma_bus * + core->dev.bus = &bcma_bus_type; + dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); + core->dev.parent = bus->dev; +- if (bus->dev) ++ if (bus->dev) { + bcma_of_fill_device(bus->dev, core); ++ dma_coerce_mask_and_coherent(&core->dev, bus->dev->coherent_dma_mask); ++ } + + switch (bus->hosttype) { + case BCMA_HOSTTYPE_PCI: diff --git a/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch new file mode 100644 index 0000000000..af44ff24ac --- /dev/null +++ b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch @@ -0,0 +1,222 @@ +From fc23ea48ba52c24f201fe5ca0132ee1a3de5a70a Mon Sep 17 00:00:00 2001 +From: Mauri Sandberg +Date: Thu, 25 Mar 2021 11:48:05 +0200 +Subject: [PATCH 2/2] gpio: gpio-cascade: add generic GPIO cascade + +Adds support for building cascades of GPIO lines. That is, it allows +setups when there is one upstream line and multiple cascaded lines, out +of which one can be chosen at a time. The status of the upstream line +can be conveyed to the selected cascaded line or, vice versa, the status +of the cascaded line can be conveyed to the upstream line. + +A multiplexer is being used to select, which cascaded GPIO line is being +used at any given time. + +At the moment only input direction is supported. In future it should be +possible to add support for output direction, too. + +Signed-off-by: Mauri Sandberg +Reviewed-by: Linus Walleij +Reviewed-by: Andy Shevchenko +--- +v7 -> v8: + - rearrange members in struct gpio_cascade + - cosmetic changes in file header and in one function declaration + - added Reviewed-by tags by Linus and Andy +v6 -> v7: + - In Kconfig add info about module name + - adhere to new convention that allows lines longer than 80 chars + - use dev_probe_err with upstream gpio line too + - refactor for cleaner exit of probe function. +v5 -> v6: + - In Kconfig, remove dependency to OF_GPIO and select only MULTIPLEXER + - refactor code preferring one-liners + - clean up prints, removing them from success-path. + - don't explicitly set gpio_chip.of_node as it's done in the GPIO library + - use devm_gpiochip_add_data instead of gpiochip_add +v4 -> v5: + - renamed gpio-mux-input -> gpio-cascade. refactored code accordingly + here and there and changed to use new bindings and compatible string + - ambigious and vague 'pin' was rename to 'upstream_line' + - dropped Tested-by and Reviewed-by due to changes in bindings + - dropped Reported-by suggested by an automatic bot as it was not really + appropriate to begin with + - functionally it's the same as v4 +v3 -> v4: + - Changed author email + - Included Tested-by and Reviewed-by from Drew +v2 -> v3: + - use managed device resources + - update Kconfig description +v1 -> v2: + - removed .owner from platform_driver as per test bot's instruction + - added MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE + - added gpio_mux_input_get_direction as it's recommended for all chips + - removed because this is input only chip: gpio_mux_input_set_value + - removed because they are not needed for input/output only chips: + gpio_mux_input_direction_input + gpio_mux_input_direction_output + - fixed typo in an error message + - added info message about successful registration + - removed can_sleep flag as this does not sleep while getting GPIO value + like I2C or SPI do + - Updated description in Kconfig +--- + drivers/gpio/Kconfig | 15 +++++ + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-cascade.c | 117 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 133 insertions(+) + create mode 100644 drivers/gpio/gpio-cascade.c + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1617,4 +1617,19 @@ config GPIO_MOCKUP + tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in + it. + ++comment "Other GPIO expanders" ++ ++config GPIO_CASCADE ++ tristate "General GPIO cascade" ++ select MULTIPLEXER ++ help ++ Say yes here to enable support for generic GPIO cascade. ++ ++ This allows building one-to-many cascades of GPIO lines using ++ different types of multiplexers readily available. At the ++ moment only input lines are supported. ++ ++ To build the driver as a module choose 'm' and the resulting module ++ will be called 'gpio-cascade'. ++ + endif +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -44,6 +44,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o ++obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o + obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o + obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o +--- /dev/null ++++ b/drivers/gpio/gpio-cascade.c +@@ -0,0 +1,117 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * A generic GPIO cascade driver ++ * ++ * Copyright (C) 2021 Mauri Sandberg ++ * ++ * This allows building cascades of GPIO lines in a manner illustrated ++ * below: ++ * ++ * /|---- Cascaded GPIO line 0 ++ * Upstream | |---- Cascaded GPIO line 1 ++ * GPIO line ----+ | . ++ * | | . ++ * \|---- Cascaded GPIO line n ++ * ++ * A multiplexer is being used to select, which cascaded line is being ++ * addressed at any given time. ++ * ++ * At the moment only input mode is supported due to lack of means for ++ * testing output functionality. At least theoretically output should be ++ * possible with open drain constructions. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct gpio_cascade { ++ struct gpio_chip gpio_chip; ++ struct device *parent; ++ struct mux_control *mux_control; ++ struct gpio_desc *upstream_line; ++}; ++ ++static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc) ++{ ++ return container_of(gc, struct gpio_cascade, gpio_chip); ++} ++ ++static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ return GPIO_LINE_DIRECTION_IN; ++} ++ ++static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct gpio_cascade *cas = chip_to_cascade(gc); ++ int ret; ++ ++ ret = mux_control_select(cas->mux_control, offset); ++ if (ret) ++ return ret; ++ ++ ret = gpiod_get_value(cas->upstream_line); ++ mux_control_deselect(cas->mux_control); ++ return ret; ++} ++ ++static int gpio_cascade_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct gpio_cascade *cas; ++ struct mux_control *mc; ++ struct gpio_desc *upstream; ++ struct gpio_chip *gc; ++ ++ cas = devm_kzalloc(dev, sizeof(*cas), GFP_KERNEL); ++ if (!cas) ++ return -ENOMEM; ++ ++ mc = devm_mux_control_get(dev, NULL); ++ if (IS_ERR(mc)) ++ return dev_err_probe(dev, PTR_ERR(mc), "unable to get mux-control\n"); ++ ++ cas->mux_control = mc; ++ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN); ++ if (IS_ERR(upstream)) ++ return dev_err_probe(dev, PTR_ERR(upstream), "unable to claim upstream GPIO line\n"); ++ ++ cas->upstream_line = upstream; ++ cas->parent = dev; ++ ++ gc = &cas->gpio_chip; ++ gc->get = gpio_cascade_get_value; ++ gc->get_direction = gpio_cascade_get_direction; ++ gc->base = -1; ++ gc->ngpio = mux_control_states(mc); ++ gc->label = dev_name(cas->parent); ++ gc->parent = cas->parent; ++ gc->owner = THIS_MODULE; ++ ++ platform_set_drvdata(pdev, cas); ++ return devm_gpiochip_add_data(dev, &cas->gpio_chip, NULL); ++} ++ ++static const struct of_device_id gpio_cascade_id[] = { ++ { .compatible = "gpio-cascade" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, gpio_cascade_id); ++ ++static struct platform_driver gpio_cascade_driver = { ++ .driver = { ++ .name = "gpio-cascade", ++ .of_match_table = gpio_cascade_id, ++ }, ++ .probe = gpio_cascade_probe, ++}; ++module_platform_driver(gpio_cascade_driver); ++ ++MODULE_AUTHOR("Mauri Sandberg "); ++MODULE_DESCRIPTION("Generic GPIO cascade"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch new file mode 100644 index 0000000000..62f6fed126 --- /dev/null +++ b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch @@ -0,0 +1,62 @@ +From: Gabor Juhos +Subject: debloat: add kernel config option to disabling common PCI quirks + +Signed-off-by: Gabor Juhos +--- + drivers/pci/Kconfig | 6 ++++++ + drivers/pci/quirks.c | 6 ++++++ + 2 files changed, 12 insertions(+) + +--- a/drivers/pci/Kconfig ++++ b/drivers/pci/Kconfig +@@ -118,6 +118,13 @@ config XEN_PCIDEV_FRONTEND + The PCI device frontend driver allows the kernel to import arbitrary + PCI devices from a PCI backend to support PCI driver domains. + ++config PCI_DISABLE_COMMON_QUIRKS ++ bool "PCI disable common quirks" ++ depends on PCI ++ help ++ If you don't know what to do here, say N. ++ ++ + config PCI_ATS + bool + +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -206,6 +206,7 @@ static void quirk_mmio_always_on(struct + DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS + /* + * The Mellanox Tavor device gives false positive parity errors. Mark this + * device with a broken_parity_status to allow PCI scanning code to "skip" +@@ -3323,6 +3324,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); + ++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ + /* + * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. + * To work around this, query the size it should be configured to by the +@@ -3348,6 +3351,8 @@ static void quirk_intel_ntb(struct pci_d + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ + /* + * Some BIOS implementations leave the Intel GPU interrupts enabled, even + * though no one is handling them (e.g., if the i915 driver is never +@@ -3386,6 +3391,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); + ++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ + /* + * PCI devices which are on Intel chips can skip the 10ms delay + * before entering D3 mode. diff --git a/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch new file mode 100644 index 0000000000..42a8397839 --- /dev/null +++ b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch @@ -0,0 +1,115 @@ +From: Felix Fietkau +Subject: debloat: disable common USB quirks + +Signed-off-by: Felix Fietkau +--- + drivers/usb/host/pci-quirks.c | 16 ++++++++++++++++ + drivers/usb/host/pci-quirks.h | 18 +++++++++++++++++- + include/linux/usb/hcd.h | 7 +++++++ + 3 files changed, 40 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -128,6 +128,8 @@ struct amd_chipset_type { + u8 rev; + }; + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ + static struct amd_chipset_info { + struct pci_dev *nb_dev; + struct pci_dev *smbus_dev; +@@ -633,6 +635,10 @@ bool usb_amd_pt_check_port(struct device + } + EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); + ++#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */ ++ ++#if IS_ENABLED(CONFIG_USB_UHCI_HCD) ++ + /* + * Make sure the controller is completely inactive, unable to + * generate interrupts or do DMA. +@@ -712,8 +718,17 @@ reset_needed: + uhci_reset_hc(pdev, base); + return 1; + } ++#else ++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) ++{ ++ return 0; ++} ++ ++#endif + EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS ++ + static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) + { + u16 cmd; +@@ -1285,3 +1300,4 @@ static void quirk_usb_early_handoff(stru + } + DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); ++#endif +--- a/drivers/usb/host/pci-quirks.h ++++ b/drivers/usb/host/pci-quirks.h +@@ -5,6 +5,9 @@ + #ifdef CONFIG_USB_PCI + void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); + int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); ++#endif /* CONFIG_USB_PCI */ ++ ++#if defined(CONFIG_USB_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS) + int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); + bool usb_amd_hang_symptom_quirk(void); + bool usb_amd_prefetch_quirk(void); +@@ -19,6 +22,18 @@ void sb800_prefetch(struct device *dev, + bool usb_amd_pt_check_port(struct device *device, int port); + #else + struct pci_dev; ++static inline int usb_amd_quirk_pll_check(void) ++{ ++ return 0; ++} ++static inline bool usb_amd_hang_symptom_quirk(void) ++{ ++ return false; ++} ++static inline bool usb_amd_prefetch_quirk(void) ++{ ++ return false; ++} + static inline void usb_amd_quirk_pll_disable(void) {} + static inline void usb_amd_quirk_pll_enable(void) {} + static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {} +@@ -29,6 +44,11 @@ static inline bool usb_amd_pt_check_port + { + return false; + } ++static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {} ++static inline bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) ++{ ++ return false; ++} + #endif /* CONFIG_USB_PCI */ + + #endif /* __LINUX_USB_PCI_QUIRKS_H */ +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -484,7 +484,14 @@ extern int usb_hcd_pci_probe(struct pci_ + extern void usb_hcd_pci_remove(struct pci_dev *dev); + extern void usb_hcd_pci_shutdown(struct pci_dev *dev); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS + extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); ++#else ++static inline int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev) ++{ ++ return 0; ++} ++#endif + + #ifdef CONFIG_PM + extern const struct dev_pm_ops usb_hcd_pci_pm_ops; diff --git a/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch new file mode 100644 index 0000000000..33eb34c913 --- /dev/null +++ b/target/linux/generic/pending-5.15/820-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch @@ -0,0 +1,26 @@ +From d9c8bc8c1408f3e8529db6e4e04017b4c579c342 Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Sun, 18 Feb 2018 17:08:04 +0100 +Subject: [PATCH] w1: gpio: fix problem with platfom data in w1-gpio + +In devices, where fdt is used, is impossible to apply platform data +without proper fdt node. + +This patch allow to use platform data in devices with fdt. + +Signed-off-by: Pawel Dembicki +--- + drivers/w1/masters/w1-gpio.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/w1/masters/w1-gpio.c ++++ b/drivers/w1/masters/w1-gpio.c +@@ -76,7 +76,7 @@ static int w1_gpio_probe(struct platform + enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN; + int err; + +- if (of_have_populated_dt()) { ++ if (of_have_populated_dt() && !dev_get_platdata(&pdev->dev)) { + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; diff --git a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch new file mode 100644 index 0000000000..25cffb1444 --- /dev/null +++ b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch @@ -0,0 +1,149 @@ +From: Daniel Golle +Subject: libata: add ledtrig support + +This adds a LED trigger for each ATA port indicating disk activity. + +As this is needed only on specific platforms (NAS SoCs and such), +these platforms should define ARCH_WANTS_LIBATA_LEDS if there +are boards with LED(s) intended to indicate ATA disk activity and +need the OS to take care of that. +In that way, if not selected, LED trigger support not will be +included in libata-core and both, codepaths and structures remain +untouched. + +Signed-off-by: Daniel Golle +--- + drivers/ata/Kconfig | 16 ++++++++++++++++ + drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++ + include/linux/libata.h | 9 +++++++++ + 3 files changed, 66 insertions(+) + +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -67,6 +67,22 @@ config ATA_FORCE + + If unsure, say Y. + ++config ARCH_WANT_LIBATA_LEDS ++ bool ++ ++config ATA_LEDS ++ bool "support ATA port LED triggers" ++ depends on ARCH_WANT_LIBATA_LEDS ++ select NEW_LEDS ++ select LEDS_CLASS ++ select LEDS_TRIGGERS ++ default y ++ help ++ This option adds a LED trigger for each registered ATA port. ++ It is used to drive disk activity leds connected via GPIO. ++ ++ If unsure, say N. ++ + config ATA_ACPI + bool "ATA ACPI Support" + depends on ACPI +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -650,6 +650,19 @@ u64 ata_tf_read_block(const struct ata_t + return block; + } + ++#ifdef CONFIG_ATA_LEDS ++#define LIBATA_BLINK_DELAY 20 /* ms */ ++static inline void ata_led_act(struct ata_port *ap) ++{ ++ unsigned long led_delay = LIBATA_BLINK_DELAY; ++ ++ if (unlikely(!ap->ledtrig)) ++ return; ++ ++ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); ++} ++#endif ++ + /** + * ata_build_rw_tf - Build ATA taskfile for given read/write request + * @tf: Target ATA taskfile +@@ -4548,6 +4561,9 @@ struct ata_queued_cmd *ata_qc_new_init(s + if (tag < 0) + return NULL; + } ++#ifdef CONFIG_ATA_LEDS ++ ata_led_act(ap); ++#endif + + qc = __ata_qc_from_tag(ap, tag); + qc->tag = qc->hw_tag = tag; +@@ -5326,6 +5342,9 @@ struct ata_port *ata_port_alloc(struct a + ap->stats.unhandled_irq = 1; + ap->stats.idle_irq = 1; + #endif ++#ifdef CONFIG_ATA_LEDS ++ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); ++#endif + ata_sff_port_init(ap); + + return ap; +@@ -5361,6 +5380,12 @@ static void ata_host_release(struct kref + + kfree(ap->pmp_link); + kfree(ap->slave_link); ++#ifdef CONFIG_ATA_LEDS ++ if (ap->ledtrig) { ++ led_trigger_unregister(ap->ledtrig); ++ kfree(ap->ledtrig); ++ }; ++#endif + kfree(ap); + host->ports[i] = NULL; + } +@@ -5767,7 +5792,23 @@ int ata_host_register(struct ata_host *h + host->ports[i]->print_id = atomic_inc_return(&ata_print_id); + host->ports[i]->local_port_no = i + 1; + } ++#ifdef CONFIG_ATA_LEDS ++ for (i = 0; i < host->n_ports; i++) { ++ if (unlikely(!host->ports[i]->ledtrig)) ++ continue; + ++ snprintf(host->ports[i]->ledtrig_name, ++ sizeof(host->ports[i]->ledtrig_name), "ata%u", ++ host->ports[i]->print_id); ++ ++ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; ++ ++ if (led_trigger_register(host->ports[i]->ledtrig)) { ++ kfree(host->ports[i]->ledtrig); ++ host->ports[i]->ledtrig = NULL; ++ } ++ } ++#endif + /* Create associated sysfs transport objects */ + for (i = 0; i < host->n_ports; i++) { + rc = ata_tport_add(host->dev,host->ports[i]); +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -23,6 +23,9 @@ + #include + #include + #include ++#ifdef CONFIG_ATA_LEDS ++#include ++#endif + + /* + * Define if arch has non-standard setup. This is a _PCI_ standard +@@ -883,6 +886,12 @@ struct ata_port { + #ifdef CONFIG_ATA_ACPI + struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ + #endif ++ ++#ifdef CONFIG_ATA_LEDS ++ struct led_trigger *ledtrig; ++ char ledtrig_name[8]; ++#endif ++ + /* owned by EH */ + u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; + }; diff --git a/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch new file mode 100644 index 0000000000..580f0b1bfa --- /dev/null +++ b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch @@ -0,0 +1,26 @@ +From d6988cf1d16faac56899918bb2b1be8d85155e3f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 20 Feb 2021 18:36:38 +0100 +Subject: [PATCH] hwrng: bcm2835: set quality to 1000 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows devices without a high precission timer to reduce boot from >100s +to <30s. + +Signed-off-by: Álvaro Fernández Rojas +--- + drivers/char/hw_random/bcm2835-rng.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/char/hw_random/bcm2835-rng.c ++++ b/drivers/char/hw_random/bcm2835-rng.c +@@ -163,6 +163,7 @@ static int bcm2835_rng_probe(struct plat + priv->rng.init = bcm2835_rng_init; + priv->rng.read = bcm2835_rng_read; + priv->rng.cleanup = bcm2835_rng_cleanup; ++ priv->rng.quality = 1000; + + if (dev_of_node(dev)) { + rng_id = of_match_node(bcm2835_rng_of_match, dev->of_node); diff --git a/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch b/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch new file mode 100644 index 0000000000..f2f0e61089 --- /dev/null +++ b/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch @@ -0,0 +1,59 @@ +From 078c6a1cbd4cd7496048786beec2e312577bebbf Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Tue, 11 Jan 2022 23:11:32 +0100 +Subject: [PATCH] net: qmi_wwan: add ZTE MF286D modem 19d2:1485 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Modem from ZTE MF286D is an Qualcomm MDM9250 based 3G/4G modem. + +T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=5000 MxCh= 0 +D: Ver= 3.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 +P: Vendor=19d2 ProdID=1485 Rev=52.87 +S: Manufacturer=ZTE,Incorporated +S: Product=ZTE Technologies MSM +S: SerialNumber=MF286DZTED000000 +C:* #Ifs= 7 Cfg#= 1 Atr=80 MxPwr=896mA +A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00 +I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=ff Driver=rndis_host +E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host +E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option +E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option +E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms +E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option +E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms +E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan +E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms +E: Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +I:* If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs +E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms +E: Ad=89(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms + +Signed-off-by: Pawel Dembicki +Acked-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1252,6 +1252,7 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ + {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ + {QMI_FIXED_INTF(0x19d2, 0x1432, 3)}, /* ZTE ME3620 */ ++ {QMI_FIXED_INTF(0x19d2, 0x1485, 5)}, /* ZTE MF286D */ + {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x2001, 0x7e16, 3)}, /* D-Link DWM-221 */ + {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ diff --git a/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch b/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch new file mode 100644 index 0000000000..fecd19166c --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch @@ -0,0 +1,40 @@ +From 43f3f187e6f62ca40802afe39495c8a3e20b4bfa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Mon, 10 Jan 2022 01:50:50 +0100 +Subject: [PATCH] PCI: aardvark: Replace custom PCIE_CORE_INT_* macros with + PCI_INTERRUPT_* +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Header file linux/pci.h defines enum pci_interrupt_pin with corresponding +PCI_INTERRUPT_* values. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -37,10 +37,6 @@ + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6) + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK BIT(7) + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV BIT(8) +-#define PCIE_CORE_INT_A_ASSERT_ENABLE 1 +-#define PCIE_CORE_INT_B_ASSERT_ENABLE 2 +-#define PCIE_CORE_INT_C_ASSERT_ENABLE 3 +-#define PCIE_CORE_INT_D_ASSERT_ENABLE 4 + /* PIO registers base address and register offsets */ + #define PIO_BASE_ADDR 0x4000 + #define PIO_CTRL (PIO_BASE_ADDR + 0x0) +@@ -966,7 +962,7 @@ static int advk_sw_pci_bridge_init(struc + bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64); + + /* Support interrupt A for MSI feature */ +- bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE; ++ bridge->conf.intpin = PCI_INTERRUPT_INTA; + + /* Aardvark HW provides PCIe Capability structure in version 2 */ + bridge->pcie_conf.cap = cpu_to_le16(2); diff --git a/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch b/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch new file mode 100644 index 0000000000..72a432fc06 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch @@ -0,0 +1,57 @@ +From a29a7d01cd778854e08108461cba321a63d98871 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 2 Jul 2021 16:39:47 +0200 +Subject: [PATCH] PCI: aardvark: Fix reading MSI interrupt number +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In advk_pcie_handle_msi() the authors expect that when bit i in the W1C +register PCIE_MSI_STATUS_REG is cleared, the PCIE_MSI_PAYLOAD_REG is +updated to contain the MSI number corresponding to index i. + +Experiments show that this is not so, and instead PCIE_MSI_PAYLOAD_REG +always contains the number of the last received MSI, overall. + +Do not read PCIE_MSI_PAYLOAD_REG register for determining MSI interrupt +number. Since Aardvark already forbids more than 32 interrupts and uses +own allocated hwirq numbers, the msi_idx already corresponds to the +received MSI number. + +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1393,7 +1393,7 @@ static void advk_pcie_remove_irq_domain( + static void advk_pcie_handle_msi(struct advk_pcie *pcie) + { + u32 msi_val, msi_mask, msi_status, msi_idx; +- u16 msi_data; ++ int virq; + + msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG); + msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG); +@@ -1403,13 +1403,12 @@ static void advk_pcie_handle_msi(struct + if (!(BIT(msi_idx) & msi_status)) + continue; + +- /* +- * msi_idx contains bits [4:0] of the msi_data and msi_data +- * contains 16bit MSI interrupt number +- */ + advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG); +- msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK; +- generic_handle_irq(msi_data); ++ virq = irq_find_mapping(pcie->msi_inner_domain, msi_idx); ++ if (virq) ++ generic_handle_irq(virq); ++ else ++ dev_err_ratelimited(&pcie->pdev->dev, "unexpected MSI 0x%02x\n", msi_idx); + } + + advk_writel(pcie, PCIE_ISR0_MSI_INT_PENDING, diff --git a/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch b/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch new file mode 100644 index 0000000000..8b2d07089a --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch @@ -0,0 +1,72 @@ +From bb03b126ea6c9e57177b537dd022246fa5dbef16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 12 Feb 2021 16:24:07 +0100 +Subject: [PATCH] PCI: aardvark: Fix support for MSI interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Aardvark hardware supports Multi-MSI and MSI_FLAG_MULTI_PCI_MSI is already +set for the MSI chip. But when allocating MSI interrupt numbers for +Multi-MSI, the numbers need to be properly aligned, otherwise endpoint +devices send MSI interrupt with incorrect numbers. + +Fix this issue by using function bitmap_find_free_region() instead of +bitmap_find_next_zero_area(). + +To ensure that aligned MSI interrupt numbers are used by endpoint devices, +we cannot use Linux virtual irq numbers (as they are random and not +properly aligned). Instead we need to use the aligned hwirq numbers. + +This change fixes receiving MSI interrupts on Armada 3720 boards and +allows using NVMe disks which use Multi-MSI feature with 3 interrupts. + +Without this NVMe disks freeze booting as linux nvme-core.c is waiting +60s for an interrupt. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1189,7 +1189,7 @@ static void advk_msi_irq_compose_msi_msg + + msg->address_lo = lower_32_bits(msi_msg); + msg->address_hi = upper_32_bits(msi_msg); +- msg->data = data->irq; ++ msg->data = data->hwirq; + } + + static int advk_msi_set_affinity(struct irq_data *irq_data, +@@ -1206,15 +1206,11 @@ static int advk_msi_irq_domain_alloc(str + int hwirq, i; + + mutex_lock(&pcie->msi_used_lock); +- hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM, +- 0, nr_irqs, 0); +- if (hwirq >= MSI_IRQ_NUM) { +- mutex_unlock(&pcie->msi_used_lock); +- return -ENOSPC; +- } +- +- bitmap_set(pcie->msi_used, hwirq, nr_irqs); ++ hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM, ++ order_base_2(nr_irqs)); + mutex_unlock(&pcie->msi_used_lock); ++ if (hwirq < 0) ++ return -ENOSPC; + + for (i = 0; i < nr_irqs; i++) + irq_domain_set_info(domain, virq + i, hwirq + i, +@@ -1232,7 +1228,7 @@ static void advk_msi_irq_domain_free(str + struct advk_pcie *pcie = domain->host_data; + + mutex_lock(&pcie->msi_used_lock); +- bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs); ++ bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs)); + mutex_unlock(&pcie->msi_used_lock); + } + diff --git a/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch b/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch new file mode 100644 index 0000000000..47a26ceeb8 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch @@ -0,0 +1,125 @@ +From 0cd5141d1866afb23286fe90cd846441fe7aeb39 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Sat, 27 Mar 2021 14:44:11 +0100 +Subject: [PATCH] PCI: aardvark: Rewrite IRQ code to chained IRQ handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rewrite the code to use irq_set_chained_handler_and_data() handler with +chained_irq_enter() and chained_irq_exit() processing instead of using +devm_request_irq(). + +advk_pcie_irq_handler() reads IRQ status bits and calls other functions +based on which bits are set. These functions then read its own IRQ status +bits and calls other aardvark functions based on these bits. Finally +generic_handle_domain_irq() with translated linux IRQ numbers are called. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 48 +++++++++++++++------------ + 1 file changed, 26 insertions(+), 22 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -275,6 +275,7 @@ struct advk_pcie { + u32 actions; + } wins[OB_WIN_COUNT]; + u8 wins_count; ++ int irq; + struct irq_domain *irq_domain; + struct irq_chip irq_chip; + raw_spinlock_t irq_lock; +@@ -1442,21 +1443,26 @@ static void advk_pcie_handle_int(struct + } + } + +-static irqreturn_t advk_pcie_irq_handler(int irq, void *arg) ++static void advk_pcie_irq_handler(struct irq_desc *desc) + { +- struct advk_pcie *pcie = arg; +- u32 status; ++ struct advk_pcie *pcie = irq_desc_get_handler_data(desc); ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ u32 val, mask, status; + +- status = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG); +- if (!(status & PCIE_IRQ_CORE_INT)) +- return IRQ_NONE; ++ chained_irq_enter(chip, desc); + +- advk_pcie_handle_int(pcie); ++ val = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG); ++ mask = advk_readl(pcie, HOST_CTRL_INT_MASK_REG); ++ status = val & ((~mask) & PCIE_IRQ_ALL_MASK); + +- /* Clear interrupt */ +- advk_writel(pcie, PCIE_IRQ_CORE_INT, HOST_CTRL_INT_STATUS_REG); ++ if (status & PCIE_IRQ_CORE_INT) { ++ advk_pcie_handle_int(pcie); + +- return IRQ_HANDLED; ++ /* Clear interrupt */ ++ advk_writel(pcie, PCIE_IRQ_CORE_INT, HOST_CTRL_INT_STATUS_REG); ++ } ++ ++ chained_irq_exit(chip, desc); + } + + static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) +@@ -1523,7 +1529,7 @@ static int advk_pcie_probe(struct platfo + struct advk_pcie *pcie; + struct pci_host_bridge *bridge; + struct resource_entry *entry; +- int ret, irq; ++ int ret; + + bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie)); + if (!bridge) +@@ -1611,17 +1617,9 @@ static int advk_pcie_probe(struct platfo + if (IS_ERR(pcie->base)) + return PTR_ERR(pcie->base); + +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) +- return irq; +- +- ret = devm_request_irq(dev, irq, advk_pcie_irq_handler, +- IRQF_SHARED | IRQF_NO_THREAD, "advk-pcie", +- pcie); +- if (ret) { +- dev_err(dev, "Failed to register interrupt\n"); +- return ret; +- } ++ pcie->irq = platform_get_irq(pdev, 0); ++ if (pcie->irq < 0) ++ return pcie->irq; + + pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node, + "reset-gpios", 0, +@@ -1670,11 +1668,14 @@ static int advk_pcie_probe(struct platfo + return ret; + } + ++ irq_set_chained_handler_and_data(pcie->irq, advk_pcie_irq_handler, pcie); ++ + bridge->sysdata = pcie; + bridge->ops = &advk_pcie_ops; + + ret = pci_host_probe(bridge); + if (ret < 0) { ++ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + return ret; +@@ -1722,6 +1723,9 @@ static int advk_pcie_remove(struct platf + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); + ++ /* Remove IRQ handler */ ++ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); ++ + /* Remove IRQ domains */ + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); diff --git a/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch b/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch new file mode 100644 index 0000000000..9cc37f727e --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch @@ -0,0 +1,31 @@ +From 69c1f2c6f45a556361fd8e8d2d4eb20e2c8d3d95 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 18 Mar 2021 17:04:32 +0100 +Subject: [PATCH] PCI: aardvark: Check return value of + generic_handle_domain_irq() when processing INTx IRQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It is possible that we receive spurious INTx interrupt. Check for the +return value of generic_handle_domain_irq() when processing INTx IRQ. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1439,7 +1439,9 @@ static void advk_pcie_handle_int(struct + PCIE_ISR1_REG); + + virq = irq_find_mapping(pcie->irq_domain, i); +- generic_handle_irq(virq); ++ if (generic_handle_irq(virq) == -EINVAL) ++ dev_err_ratelimited(&pcie->pdev->dev, "unexpected INT%c IRQ\n", ++ (char)i + 'A'); + } + } + diff --git a/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch b/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch new file mode 100644 index 0000000000..154b11290a --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch @@ -0,0 +1,93 @@ +From 5eb36a6b9508da442aac80f4df23e3951bbfa7aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 10 Jan 2022 00:03:41 +0100 +Subject: [PATCH] PCI: aardvark: Make MSI irq_chip structures static driver + structures +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Marc Zyngier says [1] that we should use struct irq_chip as a global +static struct in the driver. Even though the structure currently +contains a dynamic member (parent_device), Marc says [2] that he plans +to kill it and make the structure completely static. + +Convert Aardvark's priv->msi_bottom_irq_chip and priv->msi_irq_chip to +static driver structure. + +[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/ +[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/ + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -281,8 +281,6 @@ struct advk_pcie { + raw_spinlock_t irq_lock; + struct irq_domain *msi_domain; + struct irq_domain *msi_inner_domain; +- struct irq_chip msi_bottom_irq_chip; +- struct irq_chip msi_irq_chip; + struct msi_domain_info msi_domain_info; + DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); + struct mutex msi_used_lock; +@@ -1199,6 +1197,12 @@ static int advk_msi_set_affinity(struct + return -EINVAL; + } + ++static struct irq_chip advk_msi_bottom_irq_chip = { ++ .name = "MSI", ++ .irq_compose_msi_msg = advk_msi_irq_compose_msi_msg, ++ .irq_set_affinity = advk_msi_set_affinity, ++}; ++ + static int advk_msi_irq_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs, void *args) +@@ -1215,7 +1219,7 @@ static int advk_msi_irq_domain_alloc(str + + for (i = 0; i < nr_irqs; i++) + irq_domain_set_info(domain, virq + i, hwirq + i, +- &pcie->msi_bottom_irq_chip, ++ &advk_msi_bottom_irq_chip, + domain->host_data, handle_simple_irq, + NULL, NULL); + +@@ -1285,29 +1289,23 @@ static const struct irq_domain_ops advk_ + .xlate = irq_domain_xlate_onecell, + }; + ++static struct irq_chip advk_msi_irq_chip = { ++ .name = "advk-MSI", ++}; ++ + static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; + struct device_node *node = dev->of_node; +- struct irq_chip *bottom_ic, *msi_ic; + struct msi_domain_info *msi_di; + phys_addr_t msi_msg_phys; + + mutex_init(&pcie->msi_used_lock); + +- bottom_ic = &pcie->msi_bottom_irq_chip; +- +- bottom_ic->name = "MSI"; +- bottom_ic->irq_compose_msi_msg = advk_msi_irq_compose_msi_msg; +- bottom_ic->irq_set_affinity = advk_msi_set_affinity; +- +- msi_ic = &pcie->msi_irq_chip; +- msi_ic->name = "advk-MSI"; +- + msi_di = &pcie->msi_domain_info; + msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_MULTI_PCI_MSI; +- msi_di->chip = msi_ic; ++ msi_di->chip = &advk_msi_irq_chip; + + msi_msg_phys = virt_to_phys(&pcie->msi_msg); + diff --git a/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch b/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch new file mode 100644 index 0000000000..2f15b5b8d6 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch @@ -0,0 +1,64 @@ +From c092ab8994f1f777054c0179a9deb40b87ee606f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 10 Jan 2022 00:10:46 +0100 +Subject: [PATCH] PCI: aardvark: Make msi_domain_info structure a static driver + structure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make Aardvark's msi_domain_info structure into a private driver structure. +Domain info is same for every potential instatination of a controller. + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -281,7 +281,6 @@ struct advk_pcie { + raw_spinlock_t irq_lock; + struct irq_domain *msi_domain; + struct irq_domain *msi_inner_domain; +- struct msi_domain_info msi_domain_info; + DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); + struct mutex msi_used_lock; + u16 msi_msg; +@@ -1293,20 +1292,20 @@ static struct irq_chip advk_msi_irq_chip + .name = "advk-MSI", + }; + ++static struct msi_domain_info advk_msi_domain_info = { ++ .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | ++ MSI_FLAG_MULTI_PCI_MSI, ++ .chip = &advk_msi_irq_chip, ++}; ++ + static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; + struct device_node *node = dev->of_node; +- struct msi_domain_info *msi_di; + phys_addr_t msi_msg_phys; + + mutex_init(&pcie->msi_used_lock); + +- msi_di = &pcie->msi_domain_info; +- msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | +- MSI_FLAG_MULTI_PCI_MSI; +- msi_di->chip = &advk_msi_irq_chip; +- + msi_msg_phys = virt_to_phys(&pcie->msi_msg); + + advk_writel(pcie, lower_32_bits(msi_msg_phys), +@@ -1322,7 +1321,8 @@ static int advk_pcie_init_msi_irq_domain + + pcie->msi_domain = + pci_msi_create_irq_domain(of_node_to_fwnode(node), +- msi_di, pcie->msi_inner_domain); ++ &advk_msi_domain_info, ++ pcie->msi_inner_domain); + if (!pcie->msi_domain) { + irq_domain_remove(pcie->msi_inner_domain); + return -ENOMEM; diff --git a/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch b/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch new file mode 100644 index 0000000000..73f7cb9476 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch @@ -0,0 +1,40 @@ +From 59029739d42b439628e2f64f3d8f2db9be97deff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 10 Jan 2022 00:15:17 +0100 +Subject: [PATCH] PCI: aardvark: Use dev_fwnode() instead of + of_node_to_fwnode(dev->of_node) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use simple + dev_fwnode(dev) +instead of + struct device_node *node = dev->of_node; + of_node_to_fwnode(node) +especially since the node variable is not used elsewhere in the function. + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1301,7 +1301,6 @@ static struct msi_domain_info advk_msi_d + static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; +- struct device_node *node = dev->of_node; + phys_addr_t msi_msg_phys; + + mutex_init(&pcie->msi_used_lock); +@@ -1320,7 +1319,7 @@ static int advk_pcie_init_msi_irq_domain + return -ENOMEM; + + pcie->msi_domain = +- pci_msi_create_irq_domain(of_node_to_fwnode(node), ++ pci_msi_create_irq_domain(dev_fwnode(dev), + &advk_msi_domain_info, + pcie->msi_inner_domain); + if (!pcie->msi_domain) { diff --git a/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch b/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch new file mode 100644 index 0000000000..6cdaddc51c --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch @@ -0,0 +1,44 @@ +From 98feaf97bc64fc640a6c5b1394cd18fc7cd7dac8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Sun, 28 Mar 2021 14:34:49 +0200 +Subject: [PATCH] PCI: aardvark: Refactor unmasking summary MSI interrupt +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Refactor the masking of ISR0/1 Sources and unmasking of summary MSI interrupt +so that it corresponds to the comments: +- first mask all ISR0/1 +- then unmask all MSIs +- then unmask summary MSI interrupt + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -578,15 +578,17 @@ static void advk_pcie_setup_hw(struct ad + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); + + /* Disable All ISR0/1 Sources */ +- reg = PCIE_ISR0_ALL_MASK; +- reg &= ~PCIE_ISR0_MSI_INT_PENDING; +- advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); +- ++ advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG); + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); + + /* Unmask all MSIs */ + advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); + ++ /* Unmask summary MSI interrupt */ ++ reg = advk_readl(pcie, PCIE_ISR0_MASK_REG); ++ reg &= ~PCIE_ISR0_MSI_INT_PENDING; ++ advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); ++ + /* Enable summary interrupt for GIC SPI source */ + reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); + advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG); diff --git a/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch b/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch new file mode 100644 index 0000000000..808094ebd8 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch @@ -0,0 +1,117 @@ +From 7f353accca6e4a3222991c65b1a6801503973bd3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 2 Jul 2021 16:44:10 +0200 +Subject: [PATCH] PCI: aardvark: Add support for masking MSI interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We should not unmask MSIs at setup, but only when kernel asks for them +to be unmasked. + +At setup, mask all MSIs, and implement IRQ chip callbacks for masking +and unmasking particular MSIs. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 54 ++++++++++++++++++++++++--- + 1 file changed, 49 insertions(+), 5 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -281,6 +281,7 @@ struct advk_pcie { + raw_spinlock_t irq_lock; + struct irq_domain *msi_domain; + struct irq_domain *msi_inner_domain; ++ raw_spinlock_t msi_irq_lock; + DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); + struct mutex msi_used_lock; + u16 msi_msg; +@@ -577,12 +578,10 @@ static void advk_pcie_setup_hw(struct ad + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); + +- /* Disable All ISR0/1 Sources */ ++ /* Disable All ISR0/1 and MSI Sources */ + advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG); + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); +- +- /* Unmask all MSIs */ +- advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); ++ advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); + + /* Unmask summary MSI interrupt */ + reg = advk_readl(pcie, PCIE_ISR0_MASK_REG); +@@ -1198,10 +1197,52 @@ static int advk_msi_set_affinity(struct + return -EINVAL; + } + ++static void advk_msi_irq_mask(struct irq_data *d) ++{ ++ struct advk_pcie *pcie = d->domain->host_data; ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ unsigned long flags; ++ u32 mask; ++ ++ raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags); ++ mask = advk_readl(pcie, PCIE_MSI_MASK_REG); ++ mask |= BIT(hwirq); ++ advk_writel(pcie, mask, PCIE_MSI_MASK_REG); ++ raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags); ++} ++ ++static void advk_msi_irq_unmask(struct irq_data *d) ++{ ++ struct advk_pcie *pcie = d->domain->host_data; ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ unsigned long flags; ++ u32 mask; ++ ++ raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags); ++ mask = advk_readl(pcie, PCIE_MSI_MASK_REG); ++ mask &= ~BIT(hwirq); ++ advk_writel(pcie, mask, PCIE_MSI_MASK_REG); ++ raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags); ++} ++ ++static void advk_msi_top_irq_mask(struct irq_data *d) ++{ ++ pci_msi_mask_irq(d); ++ irq_chip_mask_parent(d); ++} ++ ++static void advk_msi_top_irq_unmask(struct irq_data *d) ++{ ++ pci_msi_unmask_irq(d); ++ irq_chip_unmask_parent(d); ++} ++ + static struct irq_chip advk_msi_bottom_irq_chip = { + .name = "MSI", + .irq_compose_msi_msg = advk_msi_irq_compose_msi_msg, + .irq_set_affinity = advk_msi_set_affinity, ++ .irq_mask = advk_msi_irq_mask, ++ .irq_unmask = advk_msi_irq_unmask, + }; + + static int advk_msi_irq_domain_alloc(struct irq_domain *domain, +@@ -1291,7 +1332,9 @@ static const struct irq_domain_ops advk_ + }; + + static struct irq_chip advk_msi_irq_chip = { +- .name = "advk-MSI", ++ .name = "advk-MSI", ++ .irq_mask = advk_msi_top_irq_mask, ++ .irq_unmask = advk_msi_top_irq_unmask, + }; + + static struct msi_domain_info advk_msi_domain_info = { +@@ -1305,6 +1348,7 @@ static int advk_pcie_init_msi_irq_domain + struct device *dev = &pcie->pdev->dev; + phys_addr_t msi_msg_phys; + ++ raw_spin_lock_init(&pcie->msi_irq_lock); + mutex_init(&pcie->msi_used_lock); + + msi_msg_phys = virt_to_phys(&pcie->msi_msg); diff --git a/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch b/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch new file mode 100644 index 0000000000..4807f24a12 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch @@ -0,0 +1,91 @@ +From fa73c200f181436eab859374657c53a73778d8ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 26 Mar 2021 17:35:44 +0100 +Subject: [PATCH] PCI: aardvark: Fix setting MSI address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +MSI address for receiving MSI interrupts needs to be correctly set before +enabling processing of MSI interrupts. + +Move code for setting PCIE_MSI_ADDR_LOW_REG and PCIE_MSI_ADDR_HIGH_REG +from advk_pcie_init_msi_irq_domain() to advk_pcie_setup_hw(), before +enabling PCIE_CORE_CTRL2_MSI_ENABLE. + +After this we can remove the now unused member msi_msg, which was used +only for MSI doorbell address. MSI address can be any address which cannot +be used to DMA to. So change it to the address of the main struct advk_pcie. + +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Acked-by: Marc Zyngier +Signed-off-by: Marek Behún +Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling using generic MSI support") +--- + drivers/pci/controller/pci-aardvark.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -284,7 +284,6 @@ struct advk_pcie { + raw_spinlock_t msi_irq_lock; + DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); + struct mutex msi_used_lock; +- u16 msi_msg; + int link_gen; + struct pci_bridge_emul bridge; + struct gpio_desc *reset_gpio; +@@ -479,6 +478,7 @@ static void advk_pcie_disable_ob_win(str + + static void advk_pcie_setup_hw(struct advk_pcie *pcie) + { ++ phys_addr_t msi_addr; + u32 reg; + int i; + +@@ -567,6 +567,11 @@ static void advk_pcie_setup_hw(struct ad + reg |= LANE_COUNT_1; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + ++ /* Set MSI address */ ++ msi_addr = virt_to_phys(pcie); ++ advk_writel(pcie, lower_32_bits(msi_addr), PCIE_MSI_ADDR_LOW_REG); ++ advk_writel(pcie, upper_32_bits(msi_addr), PCIE_MSI_ADDR_HIGH_REG); ++ + /* Enable MSI */ + reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG); + reg |= PCIE_CORE_CTRL2_MSI_ENABLE; +@@ -1184,10 +1189,10 @@ static void advk_msi_irq_compose_msi_msg + struct msi_msg *msg) + { + struct advk_pcie *pcie = irq_data_get_irq_chip_data(data); +- phys_addr_t msi_msg = virt_to_phys(&pcie->msi_msg); ++ phys_addr_t msi_addr = virt_to_phys(pcie); + +- msg->address_lo = lower_32_bits(msi_msg); +- msg->address_hi = upper_32_bits(msi_msg); ++ msg->address_lo = lower_32_bits(msi_addr); ++ msg->address_hi = upper_32_bits(msi_addr); + msg->data = data->hwirq; + } + +@@ -1346,18 +1351,10 @@ static struct msi_domain_info advk_msi_d + static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; +- phys_addr_t msi_msg_phys; + + raw_spin_lock_init(&pcie->msi_irq_lock); + mutex_init(&pcie->msi_used_lock); + +- msi_msg_phys = virt_to_phys(&pcie->msi_msg); +- +- advk_writel(pcie, lower_32_bits(msi_msg_phys), +- PCIE_MSI_ADDR_LOW_REG); +- advk_writel(pcie, upper_32_bits(msi_msg_phys), +- PCIE_MSI_ADDR_HIGH_REG); +- + pcie->msi_inner_domain = + irq_domain_add_linear(NULL, MSI_IRQ_NUM, + &advk_msi_domain_ops, pcie); diff --git a/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch b/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch new file mode 100644 index 0000000000..20757c7a80 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch @@ -0,0 +1,38 @@ +From 735a4ac9782b96fbe1543c578aa8334364f21abd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 2 Apr 2021 14:05:24 +0200 +Subject: [PATCH] PCI: aardvark: Enable MSI-X support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to PCI 3.0 specification, sending both MSI and MSI-X interrupts +is done by DWORD memory write operation to doorbell message address. The +write operation for MSI has zero upper 16 bits and the MSI interrupt number +in the lower 16 bits, while the write operation for MSI-X contains a 32-bit +value from MSI-X table. + +Since the driver only uses interrupt numbers from range 0..31, the upper +16 bits of the DWORD memory write operation to doorbell message address +are zero even for MSI-X interrupts. Thus we can enable MSI-X interrupts. + +Testing proves that kernel can correctly receive MSI-X interrupts from PCIe +cards which supports both MSI and MSI-X interrupts. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1344,7 +1344,7 @@ static struct irq_chip advk_msi_irq_chip + + static struct msi_domain_info advk_msi_domain_info = { + .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | +- MSI_FLAG_MULTI_PCI_MSI, ++ MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, + .chip = &advk_msi_irq_chip, + }; + diff --git a/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch b/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch new file mode 100644 index 0000000000..eb27610aa3 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch @@ -0,0 +1,100 @@ +From 7f3e55a3890fa26d15e2e4e90213962d1a7f6df9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 12 Feb 2021 20:32:55 +0100 +Subject: [PATCH] PCI: aardvark: Add support for ERR interrupt on emulated + bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +ERR interrupt is triggered when corresponding bit is unmasked in both ISR0 +and PCI_EXP_DEVCTL registers. Unmasking ERR bits in PCI_EXP_DEVCTL register +is not enough. This means that currently the ERR interrupt is never +triggered. + +Unmask ERR bits in ISR0 register at driver probe time. ERR interrupt is not +triggered until ERR bits are unmasked also in PCI_EXP_DEVCTL register, +which is done by AER driver. So it is safe to unconditionally unmask all +ERR bits in aardvark probe. + +Aardvark HW sets PCI_ERR_ROOT_AER_IRQ to zero and when corresponding bits +in ISR0 and PCI_EXP_DEVCTL are enabled, the HW triggers a generic interrupt +on GIC. Chain this interrupt to PCIe interrupt 0 with +generic_handle_domain_irq() to allow processing of ERR interrupts. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 36 ++++++++++++++++++++++++++- + 1 file changed, 35 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -97,6 +97,10 @@ + #define PCIE_MSG_PM_PME_MASK BIT(7) + #define PCIE_ISR0_MASK_REG (CONTROL_BASE_ADDR + 0x44) + #define PCIE_ISR0_MSI_INT_PENDING BIT(24) ++#define PCIE_ISR0_CORR_ERR BIT(11) ++#define PCIE_ISR0_NFAT_ERR BIT(12) ++#define PCIE_ISR0_FAT_ERR BIT(13) ++#define PCIE_ISR0_ERR_MASK GENMASK(13, 11) + #define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val)) + #define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val)) + #define PCIE_ISR0_ALL_MASK GENMASK(31, 0) +@@ -785,11 +789,15 @@ advk_pci_bridge_emul_base_conf_read(stru + case PCI_INTERRUPT_LINE: { + /* + * From the whole 32bit register we support reading from HW only +- * one bit: PCI_BRIDGE_CTL_BUS_RESET. ++ * two bits: PCI_BRIDGE_CTL_BUS_RESET and PCI_BRIDGE_CTL_SERR. + * Other bits are retrieved only from emulated config buffer. + */ + __le32 *cfgspace = (__le32 *)&bridge->conf; + u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]); ++ if (advk_readl(pcie, PCIE_ISR0_MASK_REG) & PCIE_ISR0_ERR_MASK) ++ val &= ~(PCI_BRIDGE_CTL_SERR << 16); ++ else ++ val |= PCI_BRIDGE_CTL_SERR << 16; + if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN) + val |= PCI_BRIDGE_CTL_BUS_RESET << 16; + else +@@ -815,6 +823,19 @@ advk_pci_bridge_emul_base_conf_write(str + break; + + case PCI_INTERRUPT_LINE: ++ /* ++ * According to Figure 6-3: Pseudo Logic Diagram for Error ++ * Message Controls in PCIe base specification, SERR# Enable bit ++ * in Bridge Control register enable receiving of ERR_* messages ++ */ ++ if (mask & (PCI_BRIDGE_CTL_SERR << 16)) { ++ u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); ++ if (new & (PCI_BRIDGE_CTL_SERR << 16)) ++ val &= ~PCIE_ISR0_ERR_MASK; ++ else ++ val |= PCIE_ISR0_ERR_MASK; ++ advk_writel(pcie, val, PCIE_ISR0_MASK_REG); ++ } + if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { + u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); + if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) +@@ -1466,6 +1487,19 @@ static void advk_pcie_handle_int(struct + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); + ++ /* Process ERR interrupt */ ++ if (isr0_status & PCIE_ISR0_ERR_MASK) { ++ advk_writel(pcie, PCIE_ISR0_ERR_MASK, PCIE_ISR0_REG); ++ ++ /* ++ * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use ++ * PCIe interrupt 0 ++ */ ++ virq = irq_find_mapping(pcie->irq_domain, 0); ++ if (generic_handle_irq(virq) == -EINVAL) ++ dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n"); ++ } ++ + /* Process MSI interrupts */ + if (isr0_status & PCIE_ISR0_MSI_INT_PENDING) + advk_pcie_handle_msi(pcie); diff --git a/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch b/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch new file mode 100644 index 0000000000..4a2cd77144 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch @@ -0,0 +1,44 @@ +From 5f354992eeef9a51c67796dc9f7f578d3584baa2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Wed, 8 Dec 2021 05:57:54 +0100 +Subject: [PATCH] PCI: aardvark: Fix reading PCI_EXP_RTSTA_PME bit on emulated + bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The emulated bridge returns incorrect value for PCI_EXP_RTSTA register +during readout in advk_pci_bridge_emul_pcie_conf_read() function: the +correct bit is BIT(16), but we are setting BIT(23), because the code +does + *value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 +where + PCIE_MSG_PM_PME_MASK +is + BIT(7). + +The code should probably have been something like + *value = (!!(isr0 & PCIE_MSG_PM_PME_MASK)) << 16, +but we are better of using an if() and using the proper macro for this +bit. + +Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -874,7 +874,9 @@ advk_pci_bridge_emul_pcie_conf_read(stru + case PCI_EXP_RTSTA: { + u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG); + u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG); +- *value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 | (msglog >> 16); ++ *value = msglog >> 16; ++ if (isr0 & PCIE_MSG_PM_PME_MASK) ++ *value |= PCI_EXP_RTSTA_PME; + return PCI_BRIDGE_EMUL_HANDLED; + } + diff --git a/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch b/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch new file mode 100644 index 0000000000..5ed809def2 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch @@ -0,0 +1,52 @@ +From 3fe0073d116d9902df08761c1cf0d733dd4c38fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Wed, 8 Dec 2021 06:03:50 +0100 +Subject: [PATCH] PCI: aardvark: Optimize writing PCI_EXP_RTCTL_PMEIE and + PCI_EXP_RTSTA_PME on emulated bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To optimize advk_pci_bridge_emul_pcie_conf_write() code, touch +PCIE_ISR0_REG and PCIE_ISR0_MASK_REG registers only when it is really +needed, when processing PCI_EXP_RTCTL_PMEIE and PCI_EXP_RTSTA_PME bits. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -932,19 +932,21 @@ advk_pci_bridge_emul_pcie_conf_write(str + advk_pcie_wait_for_retrain(pcie); + break; + +- case PCI_EXP_RTCTL: { ++ case PCI_EXP_RTCTL: + /* Only mask/unmask PME interrupt */ +- u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG) & +- ~PCIE_MSG_PM_PME_MASK; +- if ((new & PCI_EXP_RTCTL_PMEIE) == 0) +- val |= PCIE_MSG_PM_PME_MASK; +- advk_writel(pcie, val, PCIE_ISR0_MASK_REG); ++ if (mask & PCI_EXP_RTCTL_PMEIE) { ++ u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); ++ if (new & PCI_EXP_RTCTL_PMEIE) ++ val &= ~PCIE_MSG_PM_PME_MASK; ++ else ++ val |= PCIE_MSG_PM_PME_MASK; ++ advk_writel(pcie, val, PCIE_ISR0_MASK_REG); ++ } + break; +- } + + case PCI_EXP_RTSTA: +- new = (new & PCI_EXP_RTSTA_PME) >> 9; +- advk_writel(pcie, new, PCIE_ISR0_REG); ++ if (new & PCI_EXP_RTSTA_PME) ++ advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG); + break; + + case PCI_EXP_DEVCTL: diff --git a/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch b/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch new file mode 100644 index 0000000000..4272b6dd6e --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch @@ -0,0 +1,47 @@ +From 7acd8ef92e8789e10b5d736d73cea3b625087f26 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Wed, 8 Dec 2021 06:07:44 +0100 +Subject: [PATCH] PCI: aardvark: Add support for PME interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently enabling PCI_EXP_RTSTA_PME bit in PCI_EXP_RTCTL register does +nothing. This is because PCIe PME driver expects to receive PCIe interrupt +defined in PCI_EXP_FLAGS_IRQ register, but aardvark hardware does not +trigger PCIe INTx/MSI interrupt for PME event, rather it triggers custom +aardvark interrupt which this driver is not processing yet. + +Fix this issue by handling PME interrupt in advk_pcie_handle_int() and +chaining it to PCIe interrupt 0 with generic_handle_domain_irq() (since +aardvark sets PCI_EXP_FLAGS_IRQ to zero). With this change PCIe PME driver +finally starts receiving PME interrupt. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1491,6 +1491,19 @@ static void advk_pcie_handle_int(struct + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); + ++ /* Process PME interrupt */ ++ if (isr0_status & PCIE_MSG_PM_PME_MASK) { ++ /* ++ * Do not clear PME interrupt bit in ISR0, it is cleared by IRQ ++ * receiver by writing to the PCI_EXP_RTSTA register of emulated ++ * root bridge. Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, ++ * so use PCIe interrupt 0. ++ */ ++ virq = irq_find_mapping(pcie->irq_domain, 0); ++ if (generic_handle_irq(virq) == -EINVAL) ++ dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n"); ++ } ++ + /* Process ERR interrupt */ + if (isr0_status & PCIE_ISR0_ERR_MASK) { + advk_writel(pcie, PCIE_ISR0_ERR_MASK, PCIE_ISR0_REG); diff --git a/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch b/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch new file mode 100644 index 0000000000..6aa7dcbd76 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch @@ -0,0 +1,173 @@ +From 68727b545332327b4c2f9c0f8d006be8970e7832 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 19 Feb 2021 14:22:22 +0100 +Subject: [PATCH] PCI: aardvark: Fix support for PME requester on emulated + bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Enable aardvark PME interrupt unconditionally by unmasking it and read PME +requester ID to emulated bridge config space immediately after receiving +interrupt. + +PME requester ID is stored in the PCIE_MSG_LOG_REG register, which contains +the last inbound message. So when new inbound message is received by HW +(including non-PM), the content in PCIE_MSG_LOG_REG register is replaced by +a new value. + +PCIe specification mandates that subsequent PMEs are kept pending until the +PME Status Register bit is cleared by software by writing a 1b. + +Support for masking/unmasking PME interrupt on emulated bridge via +PCI_EXP_RTCTL_PMEIE bit is now implemented only in emulated bridge config +space, to ensure that we do not miss any aardvark PME interrupt. + +Reading of PCI_EXP_RTCAP and PCI_EXP_RTSTA registers is simplified as final +value is now always stored into emulated bridge config space by the +interrupt handler, so there is no need to implement support for these +registers in read_pcie callback. + +Clearing of W1C bit PCI_EXP_RTSTA_PME is now also simplified as it is done +by pci-bridge-emul.c code for emulated bridge config space. So there is no +need to implement support for clearing this bit in write_pcie callback. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 94 +++++++++++++++------------ + 1 file changed, 52 insertions(+), 42 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -597,6 +597,11 @@ static void advk_pcie_setup_hw(struct ad + reg &= ~PCIE_ISR0_MSI_INT_PENDING; + advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); + ++ /* Unmask PME interrupt for processing of PME requester */ ++ reg = advk_readl(pcie, PCIE_ISR0_MASK_REG); ++ reg &= ~PCIE_MSG_PM_PME_MASK; ++ advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); ++ + /* Enable summary interrupt for GIC SPI source */ + reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); + advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG); +@@ -863,22 +868,11 @@ advk_pci_bridge_emul_pcie_conf_read(stru + *value = PCI_EXP_SLTSTA_PDS << 16; + return PCI_BRIDGE_EMUL_HANDLED; + +- case PCI_EXP_RTCTL: { +- u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); +- *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; +- *value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE; +- *value |= PCI_EXP_RTCAP_CRSVIS << 16; +- return PCI_BRIDGE_EMUL_HANDLED; +- } +- +- case PCI_EXP_RTSTA: { +- u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG); +- u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG); +- *value = msglog >> 16; +- if (isr0 & PCIE_MSG_PM_PME_MASK) +- *value |= PCI_EXP_RTSTA_PME; +- return PCI_BRIDGE_EMUL_HANDLED; +- } ++ /* ++ * PCI_EXP_RTCTL and PCI_EXP_RTSTA are also supported, but do not need ++ * to be handled here, because their values are stored in emulated ++ * config space buffer, and we read them from there when needed. ++ */ + + case PCI_EXP_LNKCAP: { + u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); +@@ -932,22 +926,19 @@ advk_pci_bridge_emul_pcie_conf_write(str + advk_pcie_wait_for_retrain(pcie); + break; + +- case PCI_EXP_RTCTL: +- /* Only mask/unmask PME interrupt */ +- if (mask & PCI_EXP_RTCTL_PMEIE) { +- u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); +- if (new & PCI_EXP_RTCTL_PMEIE) +- val &= ~PCIE_MSG_PM_PME_MASK; +- else +- val |= PCIE_MSG_PM_PME_MASK; +- advk_writel(pcie, val, PCIE_ISR0_MASK_REG); +- } ++ case PCI_EXP_RTCTL: { ++ u16 rootctl = le16_to_cpu(bridge->pcie_conf.rootctl); ++ /* Only emulation of PMEIE and CRSSVE bits is provided */ ++ rootctl &= PCI_EXP_RTCTL_PMEIE | PCI_EXP_RTCTL_CRSSVE; ++ bridge->pcie_conf.rootctl = cpu_to_le16(rootctl); + break; ++ } + +- case PCI_EXP_RTSTA: +- if (new & PCI_EXP_RTSTA_PME) +- advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG); +- break; ++ /* ++ * PCI_EXP_RTSTA is also supported, but does not need to be handled ++ * here, because its value is stored in emulated config space buffer, ++ * and we write it there when needed. ++ */ + + case PCI_EXP_DEVCTL: + case PCI_EXP_DEVCTL2: +@@ -1452,6 +1443,34 @@ static void advk_pcie_remove_irq_domain( + irq_domain_remove(pcie->irq_domain); + } + ++static void advk_pcie_handle_pme(struct advk_pcie *pcie) ++{ ++ u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16; ++ int virq; ++ ++ advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG); ++ ++ /* ++ * PCIE_MSG_LOG_REG contains the last inbound message, so store ++ * the requester ID only when PME was not asserted yet. ++ * Also do not trigger PME interrupt when PME is still asserted. ++ */ ++ if (!(le32_to_cpu(pcie->bridge.pcie_conf.rootsta) & PCI_EXP_RTSTA_PME)) { ++ pcie->bridge.pcie_conf.rootsta = cpu_to_le32(requester | PCI_EXP_RTSTA_PME); ++ ++ /* ++ * Trigger PME interrupt only if PMEIE bit in Root Control is set. ++ * Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, so use PCIe interrupt 0. ++ */ ++ if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE)) ++ return; ++ ++ virq = irq_find_mapping(pcie->irq_domain, 0); ++ if (generic_handle_irq(virq) == -EINVAL) ++ dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n"); ++ } ++} ++ + static void advk_pcie_handle_msi(struct advk_pcie *pcie) + { + u32 msi_val, msi_mask, msi_status, msi_idx; +@@ -1491,18 +1510,9 @@ static void advk_pcie_handle_int(struct + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); + +- /* Process PME interrupt */ +- if (isr0_status & PCIE_MSG_PM_PME_MASK) { +- /* +- * Do not clear PME interrupt bit in ISR0, it is cleared by IRQ +- * receiver by writing to the PCI_EXP_RTSTA register of emulated +- * root bridge. Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, +- * so use PCIe interrupt 0. +- */ +- virq = irq_find_mapping(pcie->irq_domain, 0); +- if (generic_handle_irq(virq) == -EINVAL) +- dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n"); +- } ++ /* Process PME interrupt as the first one to do not miss PME requester id */ ++ if (isr0_status & PCIE_MSG_PM_PME_MASK) ++ advk_pcie_handle_pme(pcie); + + /* Process ERR interrupt */ + if (isr0_status & PCIE_ISR0_ERR_MASK) { diff --git a/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch b/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch new file mode 100644 index 0000000000..e9f65aca23 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch @@ -0,0 +1,161 @@ +From db305233136f5aa2444a8287a279384e8458c458 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 1 Apr 2021 20:12:48 +0200 +Subject: [PATCH] PCI: aardvark: Use separate INTA interrupt for emulated root + bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Emulated root bridge currently provides only one Legacy INTA interrupt +which is used for reporting PCIe PME and ERR events and handled by kernel +PCIe PME and AER drivers. + +Aardvark HW reports these PME and ERR events separately, so there is no +need to mix real INTA interrupt and emulated INTA interrupt for PCIe PME +and AER drivers. + +Register a new advk-RP (as in Root Port) irq chip and a new irq domain +for emulated root bridge and use this new separate irq domain for +providing INTA interrupt from emulated root bridge for PME and ERR events. + +The real INTA interrupt from real devices is now separate. + +A custom map_irq callback function on PCI host bridge structure is used to +allocate IRQ mapping for emulated root bridge from new irq domain. Original +callback of_irq_parse_and_map_pci() is used for all other devices as before. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 69 ++++++++++++++++++++++++++- + 1 file changed, 67 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -280,6 +280,7 @@ struct advk_pcie { + } wins[OB_WIN_COUNT]; + u8 wins_count; + int irq; ++ struct irq_domain *rp_irq_domain; + struct irq_domain *irq_domain; + struct irq_chip irq_chip; + raw_spinlock_t irq_lock; +@@ -1443,6 +1444,44 @@ static void advk_pcie_remove_irq_domain( + irq_domain_remove(pcie->irq_domain); + } + ++static struct irq_chip advk_rp_irq_chip = { ++ .name = "advk-RP", ++}; ++ ++static int advk_pcie_rp_irq_map(struct irq_domain *h, ++ unsigned int virq, irq_hw_number_t hwirq) ++{ ++ struct advk_pcie *pcie = h->host_data; ++ ++ irq_set_chip_and_handler(virq, &advk_rp_irq_chip, handle_simple_irq); ++ irq_set_chip_data(virq, pcie); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops advk_pcie_rp_irq_domain_ops = { ++ .map = advk_pcie_rp_irq_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++static int advk_pcie_init_rp_irq_domain(struct advk_pcie *pcie) ++{ ++ pcie->rp_irq_domain = irq_domain_add_linear(NULL, 1, ++ &advk_pcie_rp_irq_domain_ops, ++ pcie); ++ if (!pcie->rp_irq_domain) { ++ dev_err(&pcie->pdev->dev, "Failed to add Root Port IRQ domain\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static void advk_pcie_remove_rp_irq_domain(struct advk_pcie *pcie) ++{ ++ irq_domain_remove(pcie->rp_irq_domain); ++} ++ + static void advk_pcie_handle_pme(struct advk_pcie *pcie) + { + u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16; +@@ -1465,7 +1504,7 @@ static void advk_pcie_handle_pme(struct + if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE)) + return; + +- virq = irq_find_mapping(pcie->irq_domain, 0); ++ virq = irq_find_mapping(pcie->rp_irq_domain, 0); + if (generic_handle_irq(virq) == -EINVAL) + dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n"); + } +@@ -1522,7 +1561,7 @@ static void advk_pcie_handle_int(struct + * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use + * PCIe interrupt 0 + */ +- virq = irq_find_mapping(pcie->irq_domain, 0); ++ virq = irq_find_mapping(pcie->rp_irq_domain, 0); + if (generic_handle_irq(virq) == -EINVAL) + dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n"); + } +@@ -1568,6 +1607,21 @@ static void advk_pcie_irq_handler(struct + chained_irq_exit(chip, desc); + } + ++static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ struct advk_pcie *pcie = dev->bus->sysdata; ++ ++ /* ++ * Emulated root bridge has its own emulated irq chip and irq domain. ++ * Argument pin is the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD) and ++ * hwirq for irq_create_mapping() is indexed from zero. ++ */ ++ if (pci_is_root_bus(dev->bus)) ++ return irq_create_mapping(pcie->rp_irq_domain, pin - 1); ++ else ++ return of_irq_parse_and_map_pci(dev, slot, pin); ++} ++ + static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) + { + phy_power_off(pcie->phy); +@@ -1771,14 +1825,24 @@ static int advk_pcie_probe(struct platfo + return ret; + } + ++ ret = advk_pcie_init_rp_irq_domain(pcie); ++ if (ret) { ++ dev_err(dev, "Failed to initialize irq\n"); ++ advk_pcie_remove_msi_irq_domain(pcie); ++ advk_pcie_remove_irq_domain(pcie); ++ return ret; ++ } ++ + irq_set_chained_handler_and_data(pcie->irq, advk_pcie_irq_handler, pcie); + + bridge->sysdata = pcie; + bridge->ops = &advk_pcie_ops; ++ bridge->map_irq = advk_pcie_map_irq; + + ret = pci_host_probe(bridge); + if (ret < 0) { + irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); ++ advk_pcie_remove_rp_irq_domain(pcie); + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + return ret; +@@ -1830,6 +1894,7 @@ static int advk_pcie_remove(struct platf + irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); + + /* Remove IRQ domains */ ++ advk_pcie_remove_rp_irq_domain(pcie); + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + diff --git a/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch b/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch new file mode 100644 index 0000000000..75f31ba19e --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch @@ -0,0 +1,29 @@ +From 8c9eef96e24f34ff8b62b230700416b822691a37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 1 Apr 2021 14:24:12 +0200 +Subject: [PATCH] PCI: aardvark: Remove irq_mask_ack callback for INTx + interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Callback for irq_mask_ack is the same as for irq_mask. As there is no +special handling for irq_ack, there is no need to define irq_mask_ack too. + +Signed-off-by: Pali Rohár +Acked-by: Marc Zyngier +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1422,7 +1422,6 @@ static int advk_pcie_init_irq_domain(str + } + + irq_chip->irq_mask = advk_pcie_irq_mask; +- irq_chip->irq_mask_ack = advk_pcie_irq_mask; + irq_chip->irq_unmask = advk_pcie_irq_unmask; + + pcie->irq_domain = diff --git a/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch b/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch new file mode 100644 index 0000000000..5583dc1b6f --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch @@ -0,0 +1,27 @@ +From dc01fca5a9d9c09ce9a3fb2bc2e7715c37ff3bd9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 1 Apr 2021 14:30:06 +0200 +Subject: [PATCH] PCI: aardvark: Don't mask irq when mapping +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +By default, all Legacy INTx interrupts are masked, so there is no need to +mask this interrupt during irq_map callback. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1339,7 +1339,6 @@ static int advk_pcie_irq_map(struct irq_ + { + struct advk_pcie *pcie = h->host_data; + +- advk_pcie_irq_mask(irq_get_irq_data(virq)); + irq_set_status_flags(virq, IRQ_LEVEL); + irq_set_chip_and_handler(virq, &pcie->irq_chip, + handle_level_irq); diff --git a/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch b/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch new file mode 100644 index 0000000000..f359663ca4 --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch @@ -0,0 +1,28 @@ +From a511c99262ce19ee06908d27212b39ec4c5aeb17 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Wed, 8 Dec 2021 04:40:29 +0100 +Subject: [PATCH] PCI: aardvark: Drop __maybe_unused from + advk_pcie_disable_phy() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This function is now always used in driver remove method, drop the +__maybe_unused attribute. + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1620,7 +1620,7 @@ static int advk_pcie_map_irq(const struc + return of_irq_parse_and_map_pci(dev, slot, pin); + } + +-static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) ++static void advk_pcie_disable_phy(struct advk_pcie *pcie) + { + phy_power_off(pcie->phy); + phy_exit(pcie->phy); diff --git a/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch b/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch new file mode 100644 index 0000000000..cc489ebc8a --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch @@ -0,0 +1,35 @@ +From bafda858364003a70b9cda84282f9761587f8033 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 10 Jan 2022 00:47:38 +0100 +Subject: [PATCH] PCI: aardvark: Update comment about link going down after + link-up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Update the comment about what happens when link goes down after we have +checked for link-up. If a PIO request is done while link-down, we have +a serious problem. + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1005,8 +1005,12 @@ static bool advk_pcie_valid_device(struc + return false; + + /* +- * If the link goes down after we check for link-up, nothing bad +- * happens but the config access times out. ++ * If the link goes down after we check for link-up, we have a problem: ++ * if a PIO request is executed while link-down, the whole controller ++ * gets stuck in a non-functional state, and even after link comes up ++ * again, PIO requests won't work anymore, and a reset of the whole PCIe ++ * controller is needed. Therefore we need to prevent sending PIO ++ * requests while the link is down. + */ + if (!pci_is_root_bus(bus) && !advk_pcie_link_up(pcie)) + return false; diff --git a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch new file mode 100644 index 0000000000..a5e2d8a3dd --- /dev/null +++ b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch @@ -0,0 +1,102 @@ +From 663b9f99bb35dbc0c7b685f71ee3668a60d31320 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 10 Jan 2022 02:02:00 +0100 +Subject: [PATCH] PCI: aardvark: Make main irq_chip structure a static driver + structure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Marc Zyngier says [1] that we should use struct irq_chip as a global +static struct in the driver. Even though the structure currently +contains a dynamic member (parent_device), Marc says [2] that he plans +to kill it and make the structure completely static. + +We have already converted others irq_chip structures in this driver in +this way, but we omitted this one because the .name member is +dynamically created from device's name, and the name is displayed in +sysfs, so changing it would break sysfs ABI. + +The rationale for changing the name (to "advk-INT") in spite of sysfs +ABI, and thus allowing to convert to a static structure, is that after +the other changes we made in this series, the IRQ chip is basically +something different: it no logner generates ERR and PME interrupts (they +are generated by emulated bridge's rp_irq_chip). + +[1] https://lore.kernel.org/linux-pci/877dbcvngf.wl-maz@kernel.org/ +[2] https://lore.kernel.org/linux-pci/874k6gvkhz.wl-maz@kernel.org/ + +Signed-off-by: Marek Behún +--- + drivers/pci/controller/pci-aardvark.c | 25 +++++++------------------ + 1 file changed, 7 insertions(+), 18 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -282,7 +282,6 @@ struct advk_pcie { + int irq; + struct irq_domain *rp_irq_domain; + struct irq_domain *irq_domain; +- struct irq_chip irq_chip; + raw_spinlock_t irq_lock; + struct irq_domain *msi_domain; + struct irq_domain *msi_inner_domain; +@@ -1338,14 +1337,19 @@ static void advk_pcie_irq_unmask(struct + raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); + } + ++static struct irq_chip advk_irq_chip = { ++ .name = "advk-INT", ++ .irq_mask = advk_pcie_irq_mask, ++ .irq_unmask = advk_pcie_irq_unmask, ++}; ++ + static int advk_pcie_irq_map(struct irq_domain *h, + unsigned int virq, irq_hw_number_t hwirq) + { + struct advk_pcie *pcie = h->host_data; + + irq_set_status_flags(virq, IRQ_LEVEL); +- irq_set_chip_and_handler(virq, &pcie->irq_chip, +- handle_level_irq); ++ irq_set_chip_and_handler(virq, &advk_irq_chip, handle_level_irq); + irq_set_chip_data(virq, pcie); + + return 0; +@@ -1404,7 +1408,6 @@ static int advk_pcie_init_irq_domain(str + struct device *dev = &pcie->pdev->dev; + struct device_node *node = dev->of_node; + struct device_node *pcie_intc_node; +- struct irq_chip *irq_chip; + int ret = 0; + + raw_spin_lock_init(&pcie->irq_lock); +@@ -1415,28 +1418,14 @@ static int advk_pcie_init_irq_domain(str + return -ENODEV; + } + +- irq_chip = &pcie->irq_chip; +- +- irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq", +- dev_name(dev)); +- if (!irq_chip->name) { +- ret = -ENOMEM; +- goto out_put_node; +- } +- +- irq_chip->irq_mask = advk_pcie_irq_mask; +- irq_chip->irq_unmask = advk_pcie_irq_unmask; +- + pcie->irq_domain = + irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, + &advk_pcie_irq_domain_ops, pcie); + if (!pcie->irq_domain) { + dev_err(dev, "Failed to get a INTx IRQ domain\n"); + ret = -ENOMEM; +- goto out_put_node; + } + +-out_put_node: + of_node_put(pcie_intc_node); + return ret; + } diff --git a/target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch b/target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch new file mode 100644 index 0000000000..4a963be952 --- /dev/null +++ b/target/linux/generic/pending-5.15/851-0001-phy-marvell-phy-mvebu-a3700-comphy-Remove-port-from-.patch @@ -0,0 +1,217 @@ +From a719f7ba7fcba05d85801c6f0267f389a21627c1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 24 Sep 2021 13:03:02 +0200 +Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Remove port from driver + configuration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Port number is encoded into argument for SMC call. It is zero for SATA, +PCIe and also both USB 3.0 PHYs. It is non-zero only for Ethernet PHY +(incorrectly called SGMII) on lane 0. Ethernet PHY on lane 1 also uses zero +port number. + +So construct "port" bits for SMC call argument can be constructed directly +from PHY type and lane number. + +Change driver code to always pass zero port number for non-ethernet PHYs +and for ethernet PHYs determinate port number from lane number. This +simplifies the driver. + +As port number from DT PHY configuration is not used anymore, remove whole +driver code which parses it. This also simplifies the driver. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Reviewed-by: Miquel Raynal +--- + drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 62 +++++++++----------- + 1 file changed, 29 insertions(+), 33 deletions(-) + +--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -20,7 +20,6 @@ + #include + + #define MVEBU_A3700_COMPHY_LANES 3 +-#define MVEBU_A3700_COMPHY_PORTS 2 + + /* COMPHY Fast SMC function identifiers */ + #define COMPHY_SIP_POWER_ON 0x82000001 +@@ -45,51 +44,47 @@ + #define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \ + ((idx) << 8) | \ + ((speed) << 2)) +-#define COMPHY_FW_PCIE(mode, idx, speed, width) (COMPHY_FW_NET(mode, idx, speed) | \ ++#define COMPHY_FW_PCIE(mode, speed, width) (COMPHY_FW_NET(mode, 0, speed) | \ + ((width) << 18)) + + struct mvebu_a3700_comphy_conf { + unsigned int lane; + enum phy_mode mode; + int submode; +- unsigned int port; + u32 fw_mode; + }; + +-#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _port, _fw) \ ++#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _fw) \ + { \ + .lane = _lane, \ + .mode = _mode, \ + .submode = _smode, \ +- .port = _port, \ + .fw_mode = _fw, \ + } + +-#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _port, _fw) \ +- MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _port, _fw) ++#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _fw) \ ++ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _fw) + +-#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _port, _fw) \ +- MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _port, _fw) ++#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _fw) \ ++ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _fw) + + static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = { + /* lane 0 */ +- MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0, ++ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, + COMPHY_FW_MODE_USB3H), +- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1, ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, + COMPHY_FW_MODE_SGMII), +- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1, ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, + COMPHY_FW_MODE_2500BASEX), + /* lane 1 */ +- MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0, +- COMPHY_FW_MODE_PCIE), +- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0, ++ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE), ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, + COMPHY_FW_MODE_SGMII), +- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0, ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, + COMPHY_FW_MODE_2500BASEX), + /* lane 2 */ +- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0, +- COMPHY_FW_MODE_SATA), +- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, 0, ++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, COMPHY_FW_MODE_SATA), ++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, + COMPHY_FW_MODE_USB3H), + }; + +@@ -98,7 +93,6 @@ struct mvebu_a3700_comphy_lane { + unsigned int id; + enum phy_mode mode; + int submode; +- int port; + }; + + static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane, +@@ -120,7 +114,7 @@ static int mvebu_a3700_comphy_smc(unsign + } + } + +-static int mvebu_a3700_comphy_get_fw_mode(int lane, int port, ++static int mvebu_a3700_comphy_get_fw_mode(int lane, + enum phy_mode mode, + int submode) + { +@@ -132,7 +126,6 @@ static int mvebu_a3700_comphy_get_fw_mod + + for (i = 0; i < n; i++) { + if (mvebu_a3700_comphy_modes[i].lane == lane && +- mvebu_a3700_comphy_modes[i].port == port && + mvebu_a3700_comphy_modes[i].mode == mode && + mvebu_a3700_comphy_modes[i].submode == submode) + break; +@@ -153,7 +146,7 @@ static int mvebu_a3700_comphy_set_mode(s + if (submode == PHY_INTERFACE_MODE_1000BASEX) + submode = PHY_INTERFACE_MODE_SGMII; + +- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, mode, ++ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, mode, + submode); + if (fw_mode < 0) { + dev_err(lane->dev, "invalid COMPHY mode\n"); +@@ -172,9 +165,10 @@ static int mvebu_a3700_comphy_power_on(s + struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); + u32 fw_param; + int fw_mode; ++ int fw_port; + int ret; + +- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, ++ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, + lane->mode, lane->submode); + if (fw_mode < 0) { + dev_err(lane->dev, "invalid COMPHY mode\n"); +@@ -191,17 +185,18 @@ static int mvebu_a3700_comphy_power_on(s + fw_param = COMPHY_FW_MODE(fw_mode); + break; + case PHY_MODE_ETHERNET: ++ fw_port = (lane->id == 0) ? 1 : 0; + switch (lane->submode) { + case PHY_INTERFACE_MODE_SGMII: + dev_dbg(lane->dev, "set lane %d to SGMII mode\n", + lane->id); +- fw_param = COMPHY_FW_NET(fw_mode, lane->port, ++ fw_param = COMPHY_FW_NET(fw_mode, fw_port, + COMPHY_FW_SPEED_1_25G); + break; + case PHY_INTERFACE_MODE_2500BASEX: + dev_dbg(lane->dev, "set lane %d to 2500BASEX mode\n", + lane->id); +- fw_param = COMPHY_FW_NET(fw_mode, lane->port, ++ fw_param = COMPHY_FW_NET(fw_mode, fw_port, + COMPHY_FW_SPEED_3_125G); + break; + default: +@@ -212,8 +207,7 @@ static int mvebu_a3700_comphy_power_on(s + break; + case PHY_MODE_PCIE: + dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); +- fw_param = COMPHY_FW_PCIE(fw_mode, lane->port, +- COMPHY_FW_SPEED_5G, ++ fw_param = COMPHY_FW_PCIE(fw_mode, COMPHY_FW_SPEED_5G, + phy->attrs.bus_width); + break; + default: +@@ -247,17 +241,20 @@ static struct phy *mvebu_a3700_comphy_xl + struct of_phandle_args *args) + { + struct mvebu_a3700_comphy_lane *lane; ++ unsigned int port; + struct phy *phy; + +- if (WARN_ON(args->args[0] >= MVEBU_A3700_COMPHY_PORTS)) +- return ERR_PTR(-EINVAL); +- + phy = of_phy_simple_xlate(dev, args); + if (IS_ERR(phy)) + return phy; + + lane = phy_get_drvdata(phy); +- lane->port = args->args[0]; ++ ++ port = args->args[0]; ++ if (port != 0 && (port != 1 || lane->id != 0)) { ++ dev_err(lane->dev, "invalid port number %u\n", port); ++ return ERR_PTR(-EINVAL); ++ } + + return phy; + } +@@ -302,7 +299,6 @@ static int mvebu_a3700_comphy_probe(stru + lane->mode = PHY_MODE_INVALID; + lane->submode = PHY_INTERFACE_MODE_NA; + lane->id = lane_id; +- lane->port = -1; + phy_set_drvdata(phy, lane); + } + diff --git a/target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch b/target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch new file mode 100644 index 0000000000..73ead1e16c --- /dev/null +++ b/target/linux/generic/pending-5.15/851-0002-phy-marvell-phy-mvebu-a3700-comphy-Add-native-kernel.patch @@ -0,0 +1,1564 @@ +From 9d276da259cce20b2ed7a868b6e6a6a205f7bb04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 23 Sep 2021 19:20:13 +0200 +Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Add native kernel + implementation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove old RPC implementation and add a new native kernel implementation. + +The old implementation uses ARM SMC API to issue RPC calls to ARM Trusted +Firmware which provides real implementation of PHY configuration. + +But older versions of ARM Trusted Firmware do not provide this PHY +configuration functionality, simply returning: operation not supported; or +worse, some versions provide the configuration functionality incorrectly. + +For example the firmware shipped in ESPRESSObin board has this older +version of ARM Trusted Firmware and therefore SATA, USB 3.0 and PCIe +functionality do not work with newer versions of Linux kernel. + +Due to the above reasons, the following commits were introduced into Linux, +to workaround these issues by ignoring -EOPNOTSUPP error code from +phy-mvebu-a3700-comphy driver function phy_power_on(): + +commit 45aefe3d2251 ("ata: ahci: mvebu: Make SATA PHY optional for Armada +3720") +commit 3241929b67d2 ("usb: host: xhci: mvebu: make USB 3.0 PHY optional for +Armada 3720") +commit b0c6ae0f8948 ("PCI: aardvark: Fix initialization with old Marvell's +Arm Trusted Firmware") + +Replace this RPC implementation with proper native kernel implementation, +which is independent on the firmware. Never return -EOPNOTSUPP for proper +arguments. + +This should solve multiple issues with real-world boards, where it is not +possible or really inconvenient to change the firmware. Let's eliminate +these issues. + +This implementation is ported directly from Armada 3720 comphy driver found +in newest version of ARM Trusted Firmware source code, but with various +fixes of register names, some added comments, some refactoring due to the +original code not conforming to kernel standards. Also PCIe mode poweroff +support was added here, and PHY reset support. These changes are also going +to be sent to ARM Trusted Firmware. + +Signed-off-by: Pali Rohár +Acked-by: Miquel Raynal +[ Pali did the porting from ATF. + I (Marek) then fixed some register names, some various other things, + added some comments and refactored the code to kernel standards. Also + fixed PHY poweroff and added PHY reset. ] +Signed-off-by: Marek Behún +--- + drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 1351 ++++++++++++++++-- + 1 file changed, 1234 insertions(+), 117 deletions(-) + +--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -5,12 +5,16 @@ + * Authors: + * Evan Wang + * Miquèl Raynal ++ * Pali Rohár ++ * Marek Behún + * + * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart. +- * SMC call initial support done by Grzegorz Jaszczyk. ++ * Comphy code from ARM Trusted Firmware ported by Pali Rohár ++ * and Marek Behún . + */ + +-#include ++#include ++#include + #include + #include + #include +@@ -18,103 +22,1147 @@ + #include + #include + #include ++#include + +-#define MVEBU_A3700_COMPHY_LANES 3 ++#define PLL_SET_DELAY_US 600 ++#define COMPHY_PLL_SLEEP 1000 ++#define COMPHY_PLL_TIMEOUT 150000 ++ ++/* Comphy lane2 indirect access register offset */ ++#define COMPHY_LANE2_INDIR_ADDR 0x0 ++#define COMPHY_LANE2_INDIR_DATA 0x4 ++ ++/* SATA and USB3 PHY offset compared to SATA PHY */ ++#define COMPHY_LANE2_REGS_BASE 0x200 ++ ++/* ++ * When accessing common PHY lane registers directly, we need to shift by 1, ++ * since the registers are 16-bit. ++ */ ++#define COMPHY_LANE_REG_DIRECT(reg) (((reg) & 0x7FF) << 1) ++ ++/* COMPHY registers */ ++#define COMPHY_POWER_PLL_CTRL 0x01 ++#define PU_IVREF_BIT BIT(15) ++#define PU_PLL_BIT BIT(14) ++#define PU_RX_BIT BIT(13) ++#define PU_TX_BIT BIT(12) ++#define PU_TX_INTP_BIT BIT(11) ++#define PU_DFE_BIT BIT(10) ++#define RESET_DTL_RX_BIT BIT(9) ++#define PLL_LOCK_BIT BIT(8) ++#define REF_FREF_SEL_MASK GENMASK(4, 0) ++#define REF_FREF_SEL_SERDES_25MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x1) ++#define REF_FREF_SEL_SERDES_40MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x3) ++#define REF_FREF_SEL_SERDES_50MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x4) ++#define REF_FREF_SEL_PCIE_USB3_25MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x2) ++#define REF_FREF_SEL_PCIE_USB3_40MHZ FIELD_PREP(REF_FREF_SEL_MASK, 0x3) ++#define COMPHY_MODE_MASK GENMASK(7, 5) ++#define COMPHY_MODE_SATA FIELD_PREP(COMPHY_MODE_MASK, 0x0) ++#define COMPHY_MODE_PCIE FIELD_PREP(COMPHY_MODE_MASK, 0x3) ++#define COMPHY_MODE_SERDES FIELD_PREP(COMPHY_MODE_MASK, 0x4) ++#define COMPHY_MODE_USB3 FIELD_PREP(COMPHY_MODE_MASK, 0x5) ++ ++#define COMPHY_KVCO_CAL_CTRL 0x02 ++#define USE_MAX_PLL_RATE_BIT BIT(12) ++#define SPEED_PLL_MASK GENMASK(7, 2) ++#define SPEED_PLL_VALUE_16 FIELD_PREP(SPEED_PLL_MASK, 0x10) ++ ++#define COMPHY_DIG_LOOPBACK_EN 0x23 ++#define SEL_DATA_WIDTH_MASK GENMASK(11, 10) ++#define DATA_WIDTH_10BIT FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x0) ++#define DATA_WIDTH_20BIT FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x1) ++#define DATA_WIDTH_40BIT FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x2) ++#define PLL_READY_TX_BIT BIT(4) ++ ++#define COMPHY_SYNC_PATTERN 0x24 ++#define TXD_INVERT_BIT BIT(10) ++#define RXD_INVERT_BIT BIT(11) ++ ++#define COMPHY_SYNC_MASK_GEN 0x25 ++#define PHY_GEN_MAX_MASK GENMASK(11, 10) ++#define PHY_GEN_MAX_USB3_5G FIELD_PREP(PHY_GEN_MAX_MASK, 0x1) ++ ++#define COMPHY_ISOLATION_CTRL 0x26 ++#define PHY_ISOLATE_MODE BIT(15) ++ ++#define COMPHY_GEN2_SET2 0x3e ++#define GS2_TX_SSC_AMP_MASK GENMASK(15, 9) ++#define GS2_TX_SSC_AMP_4128 FIELD_PREP(GS2_TX_SSC_AMP_MASK, 0x20) ++#define GS2_VREG_RXTX_MAS_ISET_MASK GENMASK(8, 7) ++#define GS2_VREG_RXTX_MAS_ISET_60U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ ++ 0x0) ++#define GS2_VREG_RXTX_MAS_ISET_80U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ ++ 0x1) ++#define GS2_VREG_RXTX_MAS_ISET_100U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ ++ 0x2) ++#define GS2_VREG_RXTX_MAS_ISET_120U FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\ ++ 0x3) ++#define GS2_RSVD_6_0_MASK GENMASK(6, 0) ++ ++#define COMPHY_GEN3_SET2 0x3f ++ ++#define COMPHY_IDLE_SYNC_EN 0x48 ++#define IDLE_SYNC_EN BIT(12) ++ ++#define COMPHY_MISC_CTRL0 0x4F ++#define CLK100M_125M_EN BIT(4) ++#define TXDCLK_2X_SEL BIT(6) ++#define CLK500M_EN BIT(7) ++#define PHY_REF_CLK_SEL BIT(10) ++ ++#define COMPHY_SFT_RESET 0x52 ++#define SFT_RST BIT(9) ++#define SFT_RST_NO_REG BIT(10) ++ ++#define COMPHY_MISC_CTRL1 0x73 ++#define SEL_BITS_PCIE_FORCE BIT(15) ++ ++#define COMPHY_GEN2_SET3 0x112 ++#define GS3_FFE_CAP_SEL_MASK GENMASK(3, 0) ++#define GS3_FFE_CAP_SEL_VALUE FIELD_PREP(GS3_FFE_CAP_SEL_MASK, 0xF) ++ ++/* PIPE registers */ ++#define COMPHY_PIPE_LANE_CFG0 0x180 ++#define PRD_TXDEEMPH0_MASK BIT(0) ++#define PRD_TXMARGIN_MASK GENMASK(3, 1) ++#define PRD_TXSWING_MASK BIT(4) ++#define CFG_TX_ALIGN_POS_MASK GENMASK(8, 5) ++ ++#define COMPHY_PIPE_LANE_CFG1 0x181 ++#define PRD_TXDEEMPH1_MASK BIT(15) ++#define USE_MAX_PLL_RATE_EN BIT(9) ++#define TX_DET_RX_MODE BIT(6) ++#define GEN2_TX_DATA_DLY_MASK GENMASK(4, 3) ++#define GEN2_TX_DATA_DLY_DEFT FIELD_PREP(GEN2_TX_DATA_DLY_MASK, 2) ++#define TX_ELEC_IDLE_MODE_EN BIT(0) ++ ++#define COMPHY_PIPE_LANE_STAT1 0x183 ++#define TXDCLK_PCLK_EN BIT(0) ++ ++#define COMPHY_PIPE_LANE_CFG4 0x188 ++#define SPREAD_SPECTRUM_CLK_EN BIT(7) ++ ++#define COMPHY_PIPE_RST_CLK_CTRL 0x1C1 ++#define PIPE_SOFT_RESET BIT(0) ++#define PIPE_REG_RESET BIT(1) ++#define MODE_CORE_CLK_FREQ_SEL BIT(9) ++#define MODE_PIPE_WIDTH_32 BIT(3) ++#define MODE_REFDIV_MASK GENMASK(5, 4) ++#define MODE_REFDIV_BY_4 FIELD_PREP(MODE_REFDIV_MASK, 0x2) ++ ++#define COMPHY_PIPE_TEST_MODE_CTRL 0x1C2 ++#define MODE_MARGIN_OVERRIDE BIT(2) ++ ++#define COMPHY_PIPE_CLK_SRC_LO 0x1C3 ++#define MODE_CLK_SRC BIT(0) ++#define BUNDLE_PERIOD_SEL BIT(1) ++#define BUNDLE_PERIOD_SCALE_MASK GENMASK(3, 2) ++#define BUNDLE_SAMPLE_CTRL BIT(4) ++#define PLL_READY_DLY_MASK GENMASK(7, 5) ++#define CFG_SEL_20B BIT(15) ++ ++#define COMPHY_PIPE_PWR_MGM_TIM1 0x1D0 ++#define CFG_PM_OSCCLK_WAIT_MASK GENMASK(15, 12) ++#define CFG_PM_RXDEN_WAIT_MASK GENMASK(11, 8) ++#define CFG_PM_RXDEN_WAIT_1_UNIT FIELD_PREP(CFG_PM_RXDEN_WAIT_MASK, 0x1) ++#define CFG_PM_RXDLOZ_WAIT_MASK GENMASK(7, 0) ++#define CFG_PM_RXDLOZ_WAIT_7_UNIT FIELD_PREP(CFG_PM_RXDLOZ_WAIT_MASK, 0x7) ++#define CFG_PM_RXDLOZ_WAIT_12_UNIT FIELD_PREP(CFG_PM_RXDLOZ_WAIT_MASK, 0xC) ++ ++/* ++ * This register is not from PHY lane register space. It only exists in the ++ * indirect register space, before the actual PHY lane 2 registers. So the ++ * offset is absolute, not relative to COMPHY_LANE2_REGS_BASE. ++ * It is used only for SATA PHY initialization. ++ */ ++#define COMPHY_RESERVED_REG 0x0E ++#define PHYCTRL_FRM_PIN_BIT BIT(13) + +-/* COMPHY Fast SMC function identifiers */ +-#define COMPHY_SIP_POWER_ON 0x82000001 +-#define COMPHY_SIP_POWER_OFF 0x82000002 +-#define COMPHY_SIP_PLL_LOCK 0x82000003 +- +-#define COMPHY_FW_MODE_SATA 0x1 +-#define COMPHY_FW_MODE_SGMII 0x2 +-#define COMPHY_FW_MODE_2500BASEX 0x3 +-#define COMPHY_FW_MODE_USB3H 0x4 +-#define COMPHY_FW_MODE_USB3D 0x5 +-#define COMPHY_FW_MODE_PCIE 0x6 +-#define COMPHY_FW_MODE_USB3 0xa +- +-#define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ +-#define COMPHY_FW_SPEED_2_5G 1 +-#define COMPHY_FW_SPEED_3_125G 2 /* 2500BASE-X */ +-#define COMPHY_FW_SPEED_5G 3 +-#define COMPHY_FW_SPEED_MAX 0x3F +- +-#define COMPHY_FW_MODE(mode) ((mode) << 12) +-#define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \ +- ((idx) << 8) | \ +- ((speed) << 2)) +-#define COMPHY_FW_PCIE(mode, speed, width) (COMPHY_FW_NET(mode, 0, speed) | \ +- ((width) << 18)) ++/* South Bridge PHY Configuration Registers */ ++#define COMPHY_PHY_REG(lane, reg) (((1 - (lane)) * 0x28) + ((reg) & 0x3f)) ++ ++/* ++ * lane0: USB3/GbE1 PHY Configuration 1 ++ * lane1: PCIe/GbE0 PHY Configuration 1 ++ * (used only by SGMII code) ++ */ ++#define COMPHY_PHY_CFG1 0x0 ++#define PIN_PU_IVREF_BIT BIT(1) ++#define PIN_RESET_CORE_BIT BIT(11) ++#define PIN_RESET_COMPHY_BIT BIT(12) ++#define PIN_PU_PLL_BIT BIT(16) ++#define PIN_PU_RX_BIT BIT(17) ++#define PIN_PU_TX_BIT BIT(18) ++#define PIN_TX_IDLE_BIT BIT(19) ++#define GEN_RX_SEL_MASK GENMASK(25, 22) ++#define GEN_RX_SEL_VALUE(val) FIELD_PREP(GEN_RX_SEL_MASK, (val)) ++#define GEN_TX_SEL_MASK GENMASK(29, 26) ++#define GEN_TX_SEL_VALUE(val) FIELD_PREP(GEN_TX_SEL_MASK, (val)) ++#define SERDES_SPEED_1_25_G 0x6 ++#define SERDES_SPEED_3_125_G 0x8 ++#define PHY_RX_INIT_BIT BIT(30) ++ ++/* ++ * lane0: USB3/GbE1 PHY Status 1 ++ * lane1: PCIe/GbE0 PHY Status 1 ++ * (used only by SGMII code) ++ */ ++#define COMPHY_PHY_STAT1 0x18 ++#define PHY_RX_INIT_DONE_BIT BIT(0) ++#define PHY_PLL_READY_RX_BIT BIT(2) ++#define PHY_PLL_READY_TX_BIT BIT(3) ++ ++/* PHY Selector */ ++#define COMPHY_SELECTOR_PHY_REG 0xFC ++/* bit0: 0: Lane1 is GbE0; 1: Lane1 is PCIe */ ++#define COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT BIT(0) ++/* bit4: 0: Lane0 is GbE1; 1: Lane0 is USB3 */ ++#define COMPHY_SELECTOR_USB3_GBE1_SEL_BIT BIT(4) ++/* bit8: 0: Lane0 is USB3 instead of GbE1, Lane2 is SATA; 1: Lane2 is USB3 */ ++#define COMPHY_SELECTOR_USB3_PHY_SEL_BIT BIT(8) + + struct mvebu_a3700_comphy_conf { + unsigned int lane; + enum phy_mode mode; + int submode; +- u32 fw_mode; + }; + +-#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _fw) \ ++#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode) \ + { \ + .lane = _lane, \ + .mode = _mode, \ + .submode = _smode, \ +- .fw_mode = _fw, \ + } + +-#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _fw) \ +- MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _fw) ++#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode) \ ++ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA) + +-#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _fw) \ +- MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _fw) ++#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode) \ ++ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode) + + static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = { + /* lane 0 */ +- MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, +- COMPHY_FW_MODE_USB3H), +- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, +- COMPHY_FW_MODE_SGMII), +- MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, +- COMPHY_FW_MODE_2500BASEX), ++ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS), ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII), ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_1000BASEX), ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX), + /* lane 1 */ +- MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE), +- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, +- COMPHY_FW_MODE_SGMII), +- MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, +- COMPHY_FW_MODE_2500BASEX), ++ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE), ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII), ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_1000BASEX), ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX), + /* lane 2 */ +- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, COMPHY_FW_MODE_SATA), +- MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, +- COMPHY_FW_MODE_USB3H), ++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA), ++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS), ++}; ++ ++struct mvebu_a3700_comphy_priv { ++ void __iomem *comphy_regs; ++ void __iomem *lane0_phy_regs; /* USB3 and GbE1 */ ++ void __iomem *lane1_phy_regs; /* PCIe and GbE0 */ ++ void __iomem *lane2_phy_indirect; /* SATA and USB3 */ ++ spinlock_t lock; /* for PHY selector access */ ++ bool xtal_is_40m; + }; + + struct mvebu_a3700_comphy_lane { ++ struct mvebu_a3700_comphy_priv *priv; + struct device *dev; + unsigned int id; + enum phy_mode mode; + int submode; ++ bool invert_tx; ++ bool invert_rx; ++ bool needs_reset; ++}; ++ ++struct gbe_phy_init_data_fix { ++ u16 addr; ++ u16 value; ++}; ++ ++/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */ ++static struct gbe_phy_init_data_fix gbe_phy_init_fix[] = { ++ { 0x005, 0x07CC }, { 0x015, 0x0000 }, { 0x01B, 0x0000 }, ++ { 0x01D, 0x0000 }, { 0x01E, 0x0000 }, { 0x01F, 0x0000 }, ++ { 0x020, 0x0000 }, { 0x021, 0x0030 }, { 0x026, 0x0888 }, ++ { 0x04D, 0x0152 }, { 0x04F, 0xA020 }, { 0x050, 0x07CC }, ++ { 0x053, 0xE9CA }, { 0x055, 0xBD97 }, { 0x071, 0x3015 }, ++ { 0x076, 0x03AA }, { 0x07C, 0x0FDF }, { 0x0C2, 0x3030 }, ++ { 0x0C3, 0x8000 }, { 0x0E2, 0x5550 }, { 0x0E3, 0x12A4 }, ++ { 0x0E4, 0x7D00 }, { 0x0E6, 0x0C83 }, { 0x101, 0xFCC0 }, ++ { 0x104, 0x0C10 } + }; + +-static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane, +- unsigned long mode) ++/* 40M1G25 mode init data */ ++static u16 gbe_phy_init[512] = { ++ /* 0 1 2 3 4 5 6 7 */ ++ /*-----------------------------------------------------------*/ ++ /* 8 9 A B C D E F */ ++ 0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26, /* 00 */ ++ 0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52, /* 08 */ ++ 0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000, /* 10 */ ++ 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF, /* 18 */ ++ 0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000, /* 20 */ ++ 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 28 */ ++ 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ ++ 0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100, /* 38 */ ++ 0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00, /* 40 */ ++ 0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A, /* 48 */ ++ 0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001, /* 50 */ ++ 0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF, /* 58 */ ++ 0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000, /* 60 */ ++ 0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002, /* 68 */ ++ 0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780, /* 70 */ ++ 0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000, /* 78 */ ++ 0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000, /* 80 */ ++ 0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210, /* 88 */ ++ 0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F, /* 90 */ ++ 0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651, /* 98 */ ++ 0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000, /* A0 */ ++ 0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A8 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B0 */ ++ 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, /* B8 */ ++ 0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003, /* C0 */ ++ 0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000, /* C8 */ ++ 0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00, /* D0 */ ++ 0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000, /* D8 */ ++ 0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541, /* E0 */ ++ 0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200, /* E8 */ ++ 0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000, /* F0 */ ++ 0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000, /* F8 */ ++ 0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000, /*100 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*108 */ ++ 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000, /*110 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*118 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*120 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*128 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*130 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*138 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*140 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*148 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*150 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*158 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*160 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*168 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*170 */ ++ 0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000, /*178 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*180 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*188 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*190 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*198 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A0 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A8 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B0 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B8 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C0 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C8 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D0 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D8 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E0 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E8 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1F0 */ ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /*1F8 */ ++}; ++ ++static inline void comphy_reg_set(void __iomem *addr, u32 data, u32 mask) + { +- struct arm_smccc_res res; +- s32 ret; ++ u32 val; + +- arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res); +- ret = res.a0; ++ val = readl(addr); ++ val = (val & ~mask) | (data & mask); ++ writel(val, addr); ++} + +- switch (ret) { +- case SMCCC_RET_SUCCESS: +- return 0; +- case SMCCC_RET_NOT_SUPPORTED: +- return -EOPNOTSUPP; ++static inline void comphy_reg_set16(void __iomem *addr, u16 data, u16 mask) ++{ ++ u16 val; ++ ++ val = readw(addr); ++ val = (val & ~mask) | (data & mask); ++ writew(val, addr); ++} ++ ++/* Used for accessing lane 2 registers (SATA/USB3 PHY) */ ++static void comphy_set_indirect(struct mvebu_a3700_comphy_priv *priv, ++ u32 offset, u16 data, u16 mask) ++{ ++ writel(offset, ++ priv->lane2_phy_indirect + COMPHY_LANE2_INDIR_ADDR); ++ comphy_reg_set(priv->lane2_phy_indirect + COMPHY_LANE2_INDIR_DATA, ++ data, mask); ++} ++ ++static void comphy_lane_reg_set(struct mvebu_a3700_comphy_lane *lane, ++ u16 reg, u16 data, u16 mask) ++{ ++ if (lane->id == 2) { ++ /* lane 2 PHY registers are accessed indirectly */ ++ comphy_set_indirect(lane->priv, ++ reg + COMPHY_LANE2_REGS_BASE, ++ data, mask); ++ } else { ++ void __iomem *base = lane->id == 1 ? ++ lane->priv->lane1_phy_regs : ++ lane->priv->lane0_phy_regs; ++ ++ comphy_reg_set16(base + COMPHY_LANE_REG_DIRECT(reg), ++ data, mask); ++ } ++} ++ ++static int comphy_lane_reg_poll(struct mvebu_a3700_comphy_lane *lane, ++ u16 reg, u16 bits, ++ ulong sleep_us, ulong timeout_us) ++{ ++ int ret; ++ ++ if (lane->id == 2) { ++ u32 data; ++ ++ /* lane 2 PHY registers are accessed indirectly */ ++ writel(reg + COMPHY_LANE2_REGS_BASE, ++ lane->priv->lane2_phy_indirect + ++ COMPHY_LANE2_INDIR_ADDR); ++ ++ ret = readl_poll_timeout(lane->priv->lane2_phy_indirect + ++ COMPHY_LANE2_INDIR_DATA, ++ data, (data & bits) == bits, ++ sleep_us, timeout_us); ++ } else { ++ void __iomem *base = lane->id == 1 ? ++ lane->priv->lane1_phy_regs : ++ lane->priv->lane0_phy_regs; ++ u16 data; ++ ++ ret = readw_poll_timeout(base + COMPHY_LANE_REG_DIRECT(reg), ++ data, (data & bits) == bits, ++ sleep_us, timeout_us); ++ } ++ ++ return ret; ++} ++ ++static void comphy_periph_reg_set(struct mvebu_a3700_comphy_lane *lane, ++ u8 reg, u32 data, u32 mask) ++{ ++ comphy_reg_set(lane->priv->comphy_regs + COMPHY_PHY_REG(lane->id, reg), ++ data, mask); ++} ++ ++static int comphy_periph_reg_poll(struct mvebu_a3700_comphy_lane *lane, ++ u8 reg, u32 bits, ++ ulong sleep_us, ulong timeout_us) ++{ ++ u32 data; ++ ++ return readl_poll_timeout(lane->priv->comphy_regs + ++ COMPHY_PHY_REG(lane->id, reg), ++ data, (data & bits) == bits, ++ sleep_us, timeout_us); ++} ++ ++/* PHY selector configures with corresponding modes */ ++static int ++mvebu_a3700_comphy_set_phy_selector(struct mvebu_a3700_comphy_lane *lane) ++{ ++ u32 old, new, clr = 0, set = 0; ++ unsigned long flags; ++ ++ switch (lane->mode) { ++ case PHY_MODE_SATA: ++ /* SATA must be in Lane2 */ ++ if (lane->id == 2) ++ clr = COMPHY_SELECTOR_USB3_PHY_SEL_BIT; ++ else ++ goto error; ++ break; ++ ++ case PHY_MODE_ETHERNET: ++ if (lane->id == 0) ++ clr = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; ++ else if (lane->id == 1) ++ clr = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; ++ else ++ goto error; ++ break; ++ ++ case PHY_MODE_USB_HOST_SS: ++ if (lane->id == 2) ++ set = COMPHY_SELECTOR_USB3_PHY_SEL_BIT; ++ else if (lane->id == 0) ++ set = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; ++ else ++ goto error; ++ break; ++ ++ case PHY_MODE_PCIE: ++ /* PCIE must be in Lane1 */ ++ if (lane->id == 1) ++ set = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; ++ else ++ goto error; ++ break; ++ ++ default: ++ goto error; ++ } ++ ++ spin_lock_irqsave(&lane->priv->lock, flags); ++ ++ old = readl(lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG); ++ new = (old & ~clr) | set; ++ writel(new, lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG); ++ ++ spin_unlock_irqrestore(&lane->priv->lock, flags); ++ ++ dev_dbg(lane->dev, ++ "COMPHY[%d] mode[%d] changed PHY selector 0x%08x -> 0x%08x\n", ++ lane->id, lane->mode, old, new); ++ ++ return 0; ++error: ++ dev_err(lane->dev, "COMPHY[%d] mode[%d] is invalid\n", lane->id, ++ lane->mode); ++ return -EINVAL; ++} ++ ++static int ++mvebu_a3700_comphy_sata_power_on(struct mvebu_a3700_comphy_lane *lane) ++{ ++ u32 mask, data, ref_clk; ++ int ret; ++ ++ /* Configure phy selector for SATA */ ++ ret = mvebu_a3700_comphy_set_phy_selector(lane); ++ if (ret) ++ return ret; ++ ++ /* Clear phy isolation mode to make it work in normal mode */ ++ comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL, ++ 0x0, PHY_ISOLATE_MODE); ++ ++ /* 0. Check the Polarity invert bits */ ++ data = 0x0; ++ if (lane->invert_tx) ++ data |= TXD_INVERT_BIT; ++ if (lane->invert_rx) ++ data |= RXD_INVERT_BIT; ++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; ++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); ++ ++ /* 1. Select 40-bit data width */ ++ comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, ++ DATA_WIDTH_40BIT, SEL_DATA_WIDTH_MASK); ++ ++ /* 2. Select reference clock(25M) and PHY mode (SATA) */ ++ if (lane->priv->xtal_is_40m) ++ ref_clk = REF_FREF_SEL_SERDES_40MHZ; ++ else ++ ref_clk = REF_FREF_SEL_SERDES_25MHZ; ++ ++ data = ref_clk | COMPHY_MODE_SATA; ++ mask = REF_FREF_SEL_MASK | COMPHY_MODE_MASK; ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); ++ ++ /* 3. Use maximum PLL rate (no power save) */ ++ comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, ++ USE_MAX_PLL_RATE_BIT, USE_MAX_PLL_RATE_BIT); ++ ++ /* 4. Reset reserved bit */ ++ comphy_set_indirect(lane->priv, COMPHY_RESERVED_REG, ++ 0x0, PHYCTRL_FRM_PIN_BIT); ++ ++ /* 5. Set vendor-specific configuration (It is done in sata driver) */ ++ /* XXX: in U-Boot below sequence was executed in this place, in Linux ++ * not. Now it is done only in U-Boot before this comphy ++ * initialization - tests shows that it works ok, but in case of any ++ * future problem it is left for reference. ++ * reg_set(MVEBU_REGS_BASE + 0xe00a0, 0, 0xffffffff); ++ * reg_set(MVEBU_REGS_BASE + 0xe00a4, BIT(6), BIT(6)); ++ */ ++ ++ /* Wait for > 55 us to allow PLL be enabled */ ++ udelay(PLL_SET_DELAY_US); ++ ++ /* Polling status */ ++ ret = comphy_lane_reg_poll(lane, COMPHY_DIG_LOOPBACK_EN, ++ PLL_READY_TX_BIT, COMPHY_PLL_SLEEP, ++ COMPHY_PLL_TIMEOUT); ++ if (ret) { ++ dev_err(lane->dev, "Failed to lock SATA PLL\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane, ++ bool is_1gbps) ++{ ++ int addr, fix_idx; ++ u16 val; ++ ++ fix_idx = 0; ++ for (addr = 0; addr < 512; addr++) { ++ /* ++ * All PHY register values are defined in full for 3.125Gbps ++ * SERDES speed. The values required for 1.25 Gbps are almost ++ * the same and only few registers should be "fixed" in ++ * comparison to 3.125 Gbps values. These register values are ++ * stored in "gbe_phy_init_fix" array. ++ */ ++ if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) { ++ /* Use new value */ ++ val = gbe_phy_init_fix[fix_idx].value; ++ if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix)) ++ fix_idx++; ++ } else { ++ val = gbe_phy_init[addr]; ++ } ++ ++ comphy_lane_reg_set(lane, addr, val, 0xFFFF); ++ } ++} ++ ++static int ++mvebu_a3700_comphy_ethernet_power_on(struct mvebu_a3700_comphy_lane *lane) ++{ ++ u32 mask, data, speed_sel; ++ int ret; ++ ++ /* Set selector */ ++ ret = mvebu_a3700_comphy_set_phy_selector(lane); ++ if (ret) ++ return ret; ++ ++ /* ++ * 1. Reset PHY by setting PHY input port PIN_RESET=1. ++ * 2. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep ++ * PHY TXP/TXN output to idle state during PHY initialization ++ * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0. ++ */ ++ data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT; ++ mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT | ++ PIN_PU_TX_BIT | PHY_RX_INIT_BIT; ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); ++ ++ /* 4. Release reset to the PHY by setting PIN_RESET=0. */ ++ data = 0x0; ++ mask = PIN_RESET_COMPHY_BIT; ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); ++ ++ /* ++ * 5. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide COMPHY ++ * bit rate ++ */ ++ switch (lane->submode) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ /* SGMII 1G, SerDes speed 1.25G */ ++ speed_sel = SERDES_SPEED_1_25_G; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ /* 2500Base-X, SerDes speed 3.125G */ ++ speed_sel = SERDES_SPEED_3_125_G; ++ break; + default: ++ /* Other rates are not supported */ ++ dev_err(lane->dev, ++ "unsupported phy speed %d on comphy lane%d\n", ++ lane->submode, lane->id); + return -EINVAL; + } ++ data = GEN_RX_SEL_VALUE(speed_sel) | GEN_TX_SEL_VALUE(speed_sel); ++ mask = GEN_RX_SEL_MASK | GEN_TX_SEL_MASK; ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); ++ ++ /* ++ * 6. Wait 10mS for bandgap and reference clocks to stabilize; then ++ * start SW programming. ++ */ ++ mdelay(10); ++ ++ /* 7. Program COMPHY register PHY_MODE */ ++ data = COMPHY_MODE_SERDES; ++ mask = COMPHY_MODE_MASK; ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); ++ ++ /* ++ * 8. Set COMPHY register REFCLK_SEL to select the correct REFCLK ++ * source ++ */ ++ data = 0x0; ++ mask = PHY_REF_CLK_SEL; ++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask); ++ ++ /* ++ * 9. Set correct reference clock frequency in COMPHY register ++ * REF_FREF_SEL. ++ */ ++ if (lane->priv->xtal_is_40m) ++ data = REF_FREF_SEL_SERDES_50MHZ; ++ else ++ data = REF_FREF_SEL_SERDES_25MHZ; ++ ++ mask = REF_FREF_SEL_MASK; ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); ++ ++ /* 10. Program COMPHY register PHY_GEN_MAX[1:0] ++ * This step is mentioned in the flow received from verification team. ++ * However the PHY_GEN_MAX value is only meaningful for other interfaces ++ * (not SERDES). For instance, it selects SATA speed 1.5/3/6 Gbps or ++ * PCIe speed 2.5/5 Gbps ++ */ ++ ++ /* ++ * 11. Program COMPHY register SEL_BITS to set correct parallel data ++ * bus width ++ */ ++ data = DATA_WIDTH_10BIT; ++ mask = SEL_DATA_WIDTH_MASK; ++ comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, data, mask); ++ ++ /* ++ * 12. As long as DFE function needs to be enabled in any mode, ++ * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F ++ * for real chip during COMPHY power on. ++ * The step 14 exists (and empty) in the original initialization flow ++ * obtained from the verification team. According to the functional ++ * specification DFE_UPDATE_EN already has the default value 0x3F ++ */ ++ ++ /* ++ * 13. Program COMPHY GEN registers. ++ * These registers should be programmed based on the lab testing result ++ * to achieve optimal performance. Please contact the CEA group to get ++ * the related GEN table during real chip bring-up. We only required to ++ * run though the entire registers programming flow defined by ++ * "comphy_gbe_phy_init" when the REF clock is 40 MHz. For REF clock ++ * 25 MHz the default values stored in PHY registers are OK. ++ */ ++ dev_dbg(lane->dev, "Running C-DPI phy init %s mode\n", ++ lane->submode == PHY_INTERFACE_MODE_2500BASEX ? "2G5" : "1G"); ++ if (lane->priv->xtal_is_40m) ++ comphy_gbe_phy_init(lane, ++ lane->submode != PHY_INTERFACE_MODE_2500BASEX); ++ ++ /* ++ * 14. [Simulation Only] should not be used for real chip. ++ * By pass power up calibration by programming EXT_FORCE_CAL_DONE ++ * (R02h[9]) to 1 to shorten COMPHY simulation time. ++ */ ++ ++ /* ++ * 15. [Simulation Only: should not be used for real chip] ++ * Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX training ++ * simulation time. ++ */ ++ ++ /* ++ * 16. Check the PHY Polarity invert bit ++ */ ++ data = 0x0; ++ if (lane->invert_tx) ++ data |= TXD_INVERT_BIT; ++ if (lane->invert_rx) ++ data |= RXD_INVERT_BIT; ++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; ++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); ++ ++ /* ++ * 17. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to ++ * start PHY power up sequence. All the PHY register programming should ++ * be done before PIN_PU_PLL=1. There should be no register programming ++ * for normal PHY operation from this point. ++ */ ++ data = PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT; ++ mask = data; ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); ++ ++ /* ++ * 18. Wait for PHY power up sequence to finish by checking output ports ++ * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1. ++ */ ++ ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1, ++ PHY_PLL_READY_TX_BIT | ++ PHY_PLL_READY_RX_BIT, ++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); ++ if (ret) { ++ dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n", ++ lane->id); ++ return ret; ++ } ++ ++ /* ++ * 19. Set COMPHY input port PIN_TX_IDLE=0 ++ */ ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, 0x0, PIN_TX_IDLE_BIT); ++ ++ /* ++ * 20. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. To ++ * start RX initialization. PIN_RX_INIT_DONE will be cleared to 0 by the ++ * PHY After RX initialization is done, PIN_RX_INIT_DONE will be set to ++ * 1 by COMPHY Set PIN_RX_INIT=0 after PIN_RX_INIT_DONE= 1. Please ++ * refer to RX initialization part for details. ++ */ ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, ++ PHY_RX_INIT_BIT, PHY_RX_INIT_BIT); ++ ++ ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1, ++ PHY_PLL_READY_TX_BIT | ++ PHY_PLL_READY_RX_BIT, ++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); ++ if (ret) { ++ dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n", ++ lane->id); ++ return ret; ++ } ++ ++ ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1, ++ PHY_RX_INIT_DONE_BIT, ++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); ++ if (ret) { ++ dev_err(lane->dev, "Failed to init RX of SERDES PHY %d\n", ++ lane->id); ++ return ret; ++ } ++ ++ return 0; + } + +-static int mvebu_a3700_comphy_get_fw_mode(int lane, ++static int ++mvebu_a3700_comphy_usb3_power_on(struct mvebu_a3700_comphy_lane *lane) ++{ ++ u32 mask, data, cfg, ref_clk; ++ int ret; ++ ++ /* Set phy seclector */ ++ ret = mvebu_a3700_comphy_set_phy_selector(lane); ++ if (ret) ++ return ret; ++ ++ /* ++ * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The ++ * register belong to UTMI module, so it is set in UTMI phy driver. ++ */ ++ ++ /* ++ * 1. Set PRD_TXDEEMPH (3.5db de-emph) ++ */ ++ data = PRD_TXDEEMPH0_MASK; ++ mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK | ++ CFG_TX_ALIGN_POS_MASK; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG0, data, mask); ++ ++ /* ++ * 2. Set BIT0: enable transmitter in high impedance mode ++ * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency ++ * Set BIT6: Tx detect Rx at HiZ mode ++ * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db ++ * together with bit 0 of COMPHY_PIPE_LANE_CFG0 register ++ */ ++ data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN; ++ mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK | ++ TX_ELEC_IDLE_MODE_EN; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1, data, mask); ++ ++ /* ++ * 3. Set Spread Spectrum Clock Enabled ++ */ ++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG4, ++ SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN); ++ ++ /* ++ * 4. Set Override Margining Controls From the MAC: ++ * Use margining signals from lane configuration ++ */ ++ comphy_lane_reg_set(lane, COMPHY_PIPE_TEST_MODE_CTRL, ++ MODE_MARGIN_OVERRIDE, 0xFFFF); ++ ++ /* ++ * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles ++ * set Mode Clock Source = PCLK is generated from REFCLK ++ */ ++ data = 0x0; ++ mask = MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE_MASK | ++ BUNDLE_SAMPLE_CTRL | PLL_READY_DLY_MASK; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO, data, mask); ++ ++ /* ++ * 6. Set G2 Spread Spectrum Clock Amplitude at 4K ++ */ ++ comphy_lane_reg_set(lane, COMPHY_GEN2_SET2, ++ GS2_TX_SSC_AMP_4128, GS2_TX_SSC_AMP_MASK); ++ ++ /* ++ * 7. Unset G3 Spread Spectrum Clock Amplitude ++ * set G3 TX and RX Register Master Current Select ++ */ ++ data = GS2_VREG_RXTX_MAS_ISET_60U; ++ mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK | ++ GS2_RSVD_6_0_MASK; ++ comphy_lane_reg_set(lane, COMPHY_GEN3_SET2, data, mask); ++ ++ /* ++ * 8. Check crystal jumper setting and program the Power and PLL Control ++ * accordingly Change RX wait ++ */ ++ if (lane->priv->xtal_is_40m) { ++ ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; ++ cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT; ++ } else { ++ ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; ++ cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT; ++ } ++ ++ data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | ++ PU_TX_INTP_BIT | PU_DFE_BIT | COMPHY_MODE_USB3 | ref_clk; ++ mask = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | ++ PU_TX_INTP_BIT | PU_DFE_BIT | PLL_LOCK_BIT | COMPHY_MODE_MASK | ++ REF_FREF_SEL_MASK; ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); ++ ++ data = CFG_PM_RXDEN_WAIT_1_UNIT | cfg; ++ mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | ++ CFG_PM_RXDLOZ_WAIT_MASK; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_PWR_MGM_TIM1, data, mask); ++ ++ /* ++ * 9. Enable idle sync ++ */ ++ comphy_lane_reg_set(lane, COMPHY_IDLE_SYNC_EN, ++ IDLE_SYNC_EN, IDLE_SYNC_EN); ++ ++ /* ++ * 10. Enable the output of 500M clock ++ */ ++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, CLK500M_EN, CLK500M_EN); ++ ++ /* ++ * 11. Set 20-bit data width ++ */ ++ comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, ++ DATA_WIDTH_20BIT, 0xFFFF); ++ ++ /* ++ * 12. Override Speed_PLL value and use MAC PLL ++ */ ++ data = SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT; ++ mask = 0xFFFF; ++ comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, data, mask); ++ ++ /* ++ * 13. Check the Polarity invert bit ++ */ ++ data = 0x0; ++ if (lane->invert_tx) ++ data |= TXD_INVERT_BIT; ++ if (lane->invert_rx) ++ data |= RXD_INVERT_BIT; ++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; ++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); ++ ++ /* ++ * 14. Set max speed generation to USB3.0 5Gbps ++ */ ++ comphy_lane_reg_set(lane, COMPHY_SYNC_MASK_GEN, ++ PHY_GEN_MAX_USB3_5G, PHY_GEN_MAX_MASK); ++ ++ /* ++ * 15. Set capacitor value for FFE gain peaking to 0xF ++ */ ++ comphy_lane_reg_set(lane, COMPHY_GEN2_SET3, ++ GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK); ++ ++ /* ++ * 16. Release SW reset ++ */ ++ data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4; ++ mask = 0xFFFF; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask); ++ ++ /* Wait for > 55 us to allow PCLK be enabled */ ++ udelay(PLL_SET_DELAY_US); ++ ++ ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN, ++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); ++ if (ret) { ++ dev_err(lane->dev, "Failed to lock USB3 PLL\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++mvebu_a3700_comphy_pcie_power_on(struct mvebu_a3700_comphy_lane *lane) ++{ ++ u32 mask, data, ref_clk; ++ int ret; ++ ++ /* Configure phy selector for PCIe */ ++ ret = mvebu_a3700_comphy_set_phy_selector(lane); ++ if (ret) ++ return ret; ++ ++ /* 1. Enable max PLL. */ ++ comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1, ++ USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN); ++ ++ /* 2. Select 20 bit SERDES interface. */ ++ comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO, ++ CFG_SEL_20B, CFG_SEL_20B); ++ ++ /* 3. Force to use reg setting for PCIe mode */ ++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL1, ++ SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE); ++ ++ /* 4. Change RX wait */ ++ data = CFG_PM_RXDEN_WAIT_1_UNIT | CFG_PM_RXDLOZ_WAIT_12_UNIT; ++ mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | ++ CFG_PM_RXDLOZ_WAIT_MASK; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_PWR_MGM_TIM1, data, mask); ++ ++ /* 5. Enable idle sync */ ++ comphy_lane_reg_set(lane, COMPHY_IDLE_SYNC_EN, ++ IDLE_SYNC_EN, IDLE_SYNC_EN); ++ ++ /* 6. Enable the output of 100M/125M/500M clock */ ++ data = CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN; ++ mask = data; ++ comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask); ++ ++ /* ++ * 7. Enable TX, PCIE global register, 0xd0074814, it is done in ++ * PCI-E driver ++ */ ++ ++ /* ++ * 8. Check crystal jumper setting and program the Power and PLL ++ * Control accordingly ++ */ ++ ++ if (lane->priv->xtal_is_40m) ++ ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; ++ else ++ ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; ++ ++ data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | ++ PU_TX_INTP_BIT | PU_DFE_BIT | COMPHY_MODE_PCIE | ref_clk; ++ mask = 0xFFFF; ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask); ++ ++ /* 9. Override Speed_PLL value and use MAC PLL */ ++ comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, ++ SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT, ++ 0xFFFF); ++ ++ /* 10. Check the Polarity invert bit */ ++ data = 0x0; ++ if (lane->invert_tx) ++ data |= TXD_INVERT_BIT; ++ if (lane->invert_rx) ++ data |= RXD_INVERT_BIT; ++ mask = TXD_INVERT_BIT | RXD_INVERT_BIT; ++ comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask); ++ ++ /* 11. Release SW reset */ ++ data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32; ++ mask = data | PIPE_SOFT_RESET | MODE_REFDIV_MASK; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask); ++ ++ /* Wait for > 55 us to allow PCLK be enabled */ ++ udelay(PLL_SET_DELAY_US); ++ ++ ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN, ++ COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT); ++ if (ret) { ++ dev_err(lane->dev, "Failed to lock PCIE PLL\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ++mvebu_a3700_comphy_usb3_power_off(struct mvebu_a3700_comphy_lane *lane) ++{ ++ /* ++ * Currently the USB3 MAC sets the USB3 PHY to low state, so we do not ++ * need to power off USB3 PHY again. ++ */ ++} ++ ++static void ++mvebu_a3700_comphy_sata_power_off(struct mvebu_a3700_comphy_lane *lane) ++{ ++ /* Set phy isolation mode */ ++ comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL, ++ PHY_ISOLATE_MODE, PHY_ISOLATE_MODE); ++ ++ /* Power off PLL, Tx, Rx */ ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, ++ 0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); ++} ++ ++static void ++mvebu_a3700_comphy_ethernet_power_off(struct mvebu_a3700_comphy_lane *lane) ++{ ++ u32 mask, data; ++ ++ data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT | PIN_PU_IVREF_BIT | ++ PHY_RX_INIT_BIT; ++ mask = data; ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); ++} ++ ++static void ++mvebu_a3700_comphy_pcie_power_off(struct mvebu_a3700_comphy_lane *lane) ++{ ++ /* Power off PLL, Tx, Rx */ ++ comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, ++ 0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); ++} ++ ++static int mvebu_a3700_comphy_reset(struct phy *phy) ++{ ++ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); ++ u16 mask, data; ++ ++ dev_dbg(lane->dev, "resetting lane %d\n", lane->id); ++ ++ /* COMPHY reset for internal logic */ ++ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, ++ SFT_RST_NO_REG, SFT_RST_NO_REG); ++ ++ /* COMPHY register reset (cleared automatically) */ ++ comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST); ++ ++ /* PIPE soft and register reset */ ++ data = PIPE_SOFT_RESET | PIPE_REG_RESET; ++ mask = data; ++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask); ++ ++ /* Release PIPE register reset */ ++ comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, ++ 0x0, PIPE_REG_RESET); ++ ++ /* Reset SB configuration register (only for lanes 0 and 1) */ ++ if (lane->id == 0 || lane->id == 1) { ++ u32 mask, data; ++ ++ data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT | ++ PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT; ++ mask = data | PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT; ++ comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask); ++ } ++ ++ return 0; ++} ++ ++static bool mvebu_a3700_comphy_check_mode(int lane, + enum phy_mode mode, + int submode) + { +@@ -122,7 +1170,7 @@ static int mvebu_a3700_comphy_get_fw_mod + + /* Unused PHY mux value is 0x0 */ + if (mode == PHY_MODE_INVALID) +- return -EINVAL; ++ return false; + + for (i = 0; i < n; i++) { + if (mvebu_a3700_comphy_modes[i].lane == lane && +@@ -132,27 +1180,30 @@ static int mvebu_a3700_comphy_get_fw_mod + } + + if (i == n) +- return -EINVAL; ++ return false; + +- return mvebu_a3700_comphy_modes[i].fw_mode; ++ return true; + } + + static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode, + int submode) + { + struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); +- int fw_mode; +- +- if (submode == PHY_INTERFACE_MODE_1000BASEX) +- submode = PHY_INTERFACE_MODE_SGMII; + +- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, mode, +- submode); +- if (fw_mode < 0) { ++ if (!mvebu_a3700_comphy_check_mode(lane->id, mode, submode)) { + dev_err(lane->dev, "invalid COMPHY mode\n"); +- return fw_mode; ++ return -EINVAL; + } + ++ /* Mode cannot be changed while the PHY is powered on */ ++ if (phy->power_count && ++ (lane->mode != mode || lane->submode != submode)) ++ return -EBUSY; ++ ++ /* If changing mode, ensure reset is called */ ++ if (lane->mode != PHY_MODE_INVALID && lane->mode != mode) ++ lane->needs_reset = true; ++ + /* Just remember the mode, ->power_on() will do the real setup */ + lane->mode = mode; + lane->submode = submode; +@@ -163,76 +1214,68 @@ static int mvebu_a3700_comphy_set_mode(s + static int mvebu_a3700_comphy_power_on(struct phy *phy) + { + struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); +- u32 fw_param; +- int fw_mode; +- int fw_port; + int ret; + +- fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, +- lane->mode, lane->submode); +- if (fw_mode < 0) { ++ if (!mvebu_a3700_comphy_check_mode(lane->id, lane->mode, ++ lane->submode)) { + dev_err(lane->dev, "invalid COMPHY mode\n"); +- return fw_mode; ++ return -EINVAL; ++ } ++ ++ if (lane->needs_reset) { ++ ret = mvebu_a3700_comphy_reset(phy); ++ if (ret) ++ return ret; ++ ++ lane->needs_reset = false; + } + + switch (lane->mode) { + case PHY_MODE_USB_HOST_SS: + dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id); +- fw_param = COMPHY_FW_MODE(fw_mode); +- break; ++ return mvebu_a3700_comphy_usb3_power_on(lane); + case PHY_MODE_SATA: + dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id); +- fw_param = COMPHY_FW_MODE(fw_mode); +- break; ++ return mvebu_a3700_comphy_sata_power_on(lane); + case PHY_MODE_ETHERNET: +- fw_port = (lane->id == 0) ? 1 : 0; +- switch (lane->submode) { +- case PHY_INTERFACE_MODE_SGMII: +- dev_dbg(lane->dev, "set lane %d to SGMII mode\n", +- lane->id); +- fw_param = COMPHY_FW_NET(fw_mode, fw_port, +- COMPHY_FW_SPEED_1_25G); +- break; +- case PHY_INTERFACE_MODE_2500BASEX: +- dev_dbg(lane->dev, "set lane %d to 2500BASEX mode\n", +- lane->id); +- fw_param = COMPHY_FW_NET(fw_mode, fw_port, +- COMPHY_FW_SPEED_3_125G); +- break; +- default: +- dev_err(lane->dev, "unsupported PHY submode (%d)\n", +- lane->submode); +- return -ENOTSUPP; +- } +- break; ++ dev_dbg(lane->dev, "set lane %d to Ethernet mode\n", lane->id); ++ return mvebu_a3700_comphy_ethernet_power_on(lane); + case PHY_MODE_PCIE: + dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); +- fw_param = COMPHY_FW_PCIE(fw_mode, COMPHY_FW_SPEED_5G, +- phy->attrs.bus_width); +- break; ++ return mvebu_a3700_comphy_pcie_power_on(lane); + default: + dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode); +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + } +- +- ret = mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param); +- if (ret == -EOPNOTSUPP) +- dev_err(lane->dev, +- "unsupported SMC call, try updating your firmware\n"); +- +- return ret; + } + + static int mvebu_a3700_comphy_power_off(struct phy *phy) + { + struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); + +- return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_OFF, lane->id, 0); ++ switch (lane->mode) { ++ case PHY_MODE_USB_HOST_SS: ++ mvebu_a3700_comphy_usb3_power_off(lane); ++ return 0; ++ case PHY_MODE_SATA: ++ mvebu_a3700_comphy_sata_power_off(lane); ++ return 0; ++ case PHY_MODE_ETHERNET: ++ mvebu_a3700_comphy_ethernet_power_off(lane); ++ return 0; ++ case PHY_MODE_PCIE: ++ mvebu_a3700_comphy_pcie_power_off(lane); ++ return 0; ++ default: ++ dev_err(lane->dev, "invalid COMPHY mode\n"); ++ return -EINVAL; ++ } + } + + static const struct phy_ops mvebu_a3700_comphy_ops = { + .power_on = mvebu_a3700_comphy_power_on, + .power_off = mvebu_a3700_comphy_power_off, ++ .reset = mvebu_a3700_comphy_reset, + .set_mode = mvebu_a3700_comphy_set_mode, + .owner = THIS_MODULE, + }; +@@ -256,13 +1299,75 @@ static struct phy *mvebu_a3700_comphy_xl + return ERR_PTR(-EINVAL); + } + ++ lane->invert_tx = args->args[1] & BIT(0); ++ lane->invert_rx = args->args[1] & BIT(1); ++ + return phy; + } + + static int mvebu_a3700_comphy_probe(struct platform_device *pdev) + { ++ struct mvebu_a3700_comphy_priv *priv; + struct phy_provider *provider; + struct device_node *child; ++ struct resource *res; ++ struct clk *clk; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->lock); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "comphy"); ++ priv->comphy_regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->comphy_regs)) ++ return PTR_ERR(priv->comphy_regs); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "lane1_pcie_gbe"); ++ priv->lane1_phy_regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->lane1_phy_regs)) ++ return PTR_ERR(priv->lane1_phy_regs); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "lane0_usb3_gbe"); ++ priv->lane0_phy_regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->lane0_phy_regs)) ++ return PTR_ERR(priv->lane0_phy_regs); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "lane2_sata_usb3"); ++ priv->lane2_phy_indirect = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->lane2_phy_indirect)) ++ return PTR_ERR(priv->lane2_phy_indirect); ++ ++ /* ++ * Driver needs to know if reference xtal clock is 40MHz or 25MHz. ++ * Old DT bindings do not have xtal clk present. So do not fail here ++ * and expects that default 25MHz reference clock is used. ++ */ ++ clk = clk_get(&pdev->dev, "xtal"); ++ if (IS_ERR(clk)) { ++ if (PTR_ERR(clk) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_warn(&pdev->dev, "missing 'xtal' clk (%ld)\n", ++ PTR_ERR(clk)); ++ } else { ++ ret = clk_prepare_enable(clk); ++ if (ret) { ++ dev_warn(&pdev->dev, "enabling xtal clk failed (%d)\n", ++ ret); ++ } else { ++ if (clk_get_rate(clk) == 40000000) ++ priv->xtal_is_40m = true; ++ clk_disable_unprepare(clk); ++ } ++ clk_put(clk); ++ } ++ ++ dev_set_drvdata(&pdev->dev, priv); + + for_each_available_child_of_node(pdev->dev.of_node, child) { + struct mvebu_a3700_comphy_lane *lane; +@@ -277,7 +1382,7 @@ static int mvebu_a3700_comphy_probe(stru + continue; + } + +- if (lane_id >= MVEBU_A3700_COMPHY_LANES) { ++ if (lane_id >= 3) { + dev_err(&pdev->dev, "invalid 'reg' property\n"); + continue; + } +@@ -295,11 +1400,21 @@ static int mvebu_a3700_comphy_probe(stru + return PTR_ERR(phy); + } + ++ lane->priv = priv; + lane->dev = &pdev->dev; + lane->mode = PHY_MODE_INVALID; + lane->submode = PHY_INTERFACE_MODE_NA; + lane->id = lane_id; ++ lane->invert_tx = false; ++ lane->invert_rx = false; + phy_set_drvdata(phy, lane); ++ ++ /* ++ * To avoid relying on the bootloader/firmware configuration, ++ * power off all comphys. ++ */ ++ mvebu_a3700_comphy_reset(phy); ++ lane->needs_reset = false; + } + + provider = devm_of_phy_provider_register(&pdev->dev, +@@ -323,5 +1438,7 @@ static struct platform_driver mvebu_a370 + module_platform_driver(mvebu_a3700_comphy_driver); + + MODULE_AUTHOR("Miquèl Raynal "); ++MODULE_AUTHOR("Pali Rohár "); ++MODULE_AUTHOR("Marek Behún "); + MODULE_DESCRIPTION("Common PHY driver for A3700"); + MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch b/target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch new file mode 100644 index 0000000000..33203a154d --- /dev/null +++ b/target/linux/generic/pending-5.15/851-0003-arm64-dts-marvell-armada-37xx-Add-xtal-clock-to-comp.patch @@ -0,0 +1,31 @@ +From 66c51c39fd4bf05e99debf0e71de5704231c57dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 23 Sep 2021 19:26:26 +0200 +Subject: [PATCH] arm64: dts: marvell: armada-37xx: Add xtal clock to comphy + node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Kernel driver phy-mvebu-a3700-comphy.c needs to know the rate of the +reference xtal clock. So add missing xtal clock source into comphy device +tree node. If the property is not present, the driver defaults to 25 MHz +xtal rate (which, as far as we know, is used by all the existing boards). + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -265,6 +265,8 @@ + "lane2_sata_usb3"; + #address-cells = <1>; + #size-cells = <0>; ++ clocks = <&xtalclk>; ++ clock-names = "xtal"; + + comphy0: phy@0 { + reg = <0>; diff --git a/target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch b/target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch new file mode 100644 index 0000000000..3c994d2548 --- /dev/null +++ b/target/linux/generic/pending-5.15/851-0004-Revert-ata-ahci-mvebu-Make-SATA-PHY-optional-for-Arm.patch @@ -0,0 +1,61 @@ +From 750bb44dbbe9dfb4ba3e1f8a746b831b39ba3cd9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 23 Sep 2021 19:35:57 +0200 +Subject: [PATCH] Revert "ata: ahci: mvebu: Make SATA PHY optional for Armada + 3720" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit 45aefe3d2251e4e229d7662052739f96ad1d08d9. + +Armada 3720 PHY driver (phy-mvebu-a3700-comphy.c) does not return +-EOPNOTSUPP from phy_power_on() callback anymore. + +So remove AHCI_HFLAG_IGN_NOTSUPP_POWER_ON flag from Armada 3720 plat data. + +AHCI_HFLAG_IGN_NOTSUPP_POWER_ON is not used by any other ahci driver, so +remove this flag completely. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Acked-by: Miquel Raynal +--- + drivers/ata/ahci.h | 2 -- + drivers/ata/ahci_mvebu.c | 2 +- + drivers/ata/libahci_platform.c | 2 +- + 3 files changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -240,8 +240,6 @@ enum { + as default lpm_policy */ + AHCI_HFLAG_SUSPEND_PHYS = (1 << 26), /* handle PHYs during + suspend/resume */ +- AHCI_HFLAG_IGN_NOTSUPP_POWER_ON = (1 << 27), /* ignore -EOPNOTSUPP +- from phy_power_on() */ + AHCI_HFLAG_NO_SXS = (1 << 28), /* SXS not supported */ + + /* ap->flags bits */ +--- a/drivers/ata/ahci_mvebu.c ++++ b/drivers/ata/ahci_mvebu.c +@@ -227,7 +227,7 @@ static const struct ahci_mvebu_plat_data + + static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = { + .plat_config = ahci_mvebu_armada_3700_config, +- .flags = AHCI_HFLAG_SUSPEND_PHYS | AHCI_HFLAG_IGN_NOTSUPP_POWER_ON, ++ .flags = AHCI_HFLAG_SUSPEND_PHYS, + }; + + static const struct of_device_id ahci_mvebu_of_match[] = { +--- a/drivers/ata/libahci_platform.c ++++ b/drivers/ata/libahci_platform.c +@@ -59,7 +59,7 @@ int ahci_platform_enable_phys(struct ahc + } + + rc = phy_power_on(hpriv->phys[i]); +- if (rc && !(rc == -EOPNOTSUPP && (hpriv->flags & AHCI_HFLAG_IGN_NOTSUPP_POWER_ON))) { ++ if (rc) { + phy_exit(hpriv->phys[i]); + goto disable_phys; + } diff --git a/target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch b/target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch new file mode 100644 index 0000000000..b8a3e880ce --- /dev/null +++ b/target/linux/generic/pending-5.15/851-0005-Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch @@ -0,0 +1,163 @@ +From 9f0dfb279b1dd505d5e10b10e4a78a62030978d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 23 Sep 2021 19:40:06 +0200 +Subject: [PATCH] Revert "usb: host: xhci: mvebu: make USB 3.0 PHY optional for + Armada 3720" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit 3241929b67d28c83945d3191c6816a3271fd6b85. + +Armada 3720 phy driver (phy-mvebu-a3700-comphy.c) does not return +-EOPNOTSUPP from phy_power_on() callback anymore. + +So remove XHCI_SKIP_PHY_INIT flag from xhci_mvebu_a3700_plat_setup() and +then also whole xhci_mvebu_a3700_plat_setup() function which is there just +to handle -EOPNOTSUPP for XHCI_SKIP_PHY_INIT. + +xhci plat_setup callback is not used by any other xhci plat driver, so +remove this callback completely. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Acked-by: Miquel Raynal +--- + drivers/usb/host/xhci-mvebu.c | 42 ----------------------------------- + drivers/usb/host/xhci-mvebu.h | 6 ----- + drivers/usb/host/xhci-plat.c | 20 +---------------- + drivers/usb/host/xhci-plat.h | 1 - + 4 files changed, 1 insertion(+), 68 deletions(-) + +--- a/drivers/usb/host/xhci-mvebu.c ++++ b/drivers/usb/host/xhci-mvebu.c +@@ -8,7 +8,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -74,47 +73,6 @@ int xhci_mvebu_mbus_init_quirk(struct us + + return 0; + } +- +-int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd) +-{ +- struct xhci_hcd *xhci = hcd_to_xhci(hcd); +- struct device *dev = hcd->self.controller; +- struct phy *phy; +- int ret; +- +- /* Old bindings miss the PHY handle */ +- phy = of_phy_get(dev->of_node, "usb3-phy"); +- if (IS_ERR(phy) && PTR_ERR(phy) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- else if (IS_ERR(phy)) +- goto phy_out; +- +- ret = phy_init(phy); +- if (ret) +- goto phy_put; +- +- ret = phy_set_mode(phy, PHY_MODE_USB_HOST_SS); +- if (ret) +- goto phy_exit; +- +- ret = phy_power_on(phy); +- if (ret == -EOPNOTSUPP) { +- /* Skip initializatin of XHCI PHY when it is unsupported by firmware */ +- dev_warn(dev, "PHY unsupported by firmware\n"); +- xhci->quirks |= XHCI_SKIP_PHY_INIT; +- } +- if (ret) +- goto phy_exit; +- +- phy_power_off(phy); +-phy_exit: +- phy_exit(phy); +-phy_put: +- of_phy_put(phy); +-phy_out: +- +- return 0; +-} + + int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) + { +--- a/drivers/usb/host/xhci-mvebu.h ++++ b/drivers/usb/host/xhci-mvebu.h +@@ -12,18 +12,12 @@ struct usb_hcd; + + #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU) + int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd); +-int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd); + int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd); + #else + static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) + { + return 0; + } +- +-static inline int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd) +-{ +- return 0; +-} + + static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) + { +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -44,16 +44,6 @@ static void xhci_priv_plat_start(struct + priv->plat_start(hcd); + } + +-static int xhci_priv_plat_setup(struct usb_hcd *hcd) +-{ +- struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); +- +- if (!priv->plat_setup) +- return 0; +- +- return priv->plat_setup(hcd); +-} +- + static int xhci_priv_init_quirk(struct usb_hcd *hcd) + { + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); +@@ -121,7 +111,6 @@ static const struct xhci_plat_priv xhci_ + }; + + static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { +- .plat_setup = xhci_mvebu_a3700_plat_setup, + .init_quirk = xhci_mvebu_a3700_init_quirk, + }; + +@@ -341,14 +330,7 @@ static int xhci_plat_probe(struct platfo + + hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); + xhci->shared_hcd->tpl_support = hcd->tpl_support; +- +- if (priv) { +- ret = xhci_priv_plat_setup(hcd); +- if (ret) +- goto disable_usb_phy; +- } +- +- if ((xhci->quirks & XHCI_SKIP_PHY_INIT) || (priv && (priv->quirks & XHCI_SKIP_PHY_INIT))) ++ if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) + hcd->skip_phy_initialization = 1; + + if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK)) +--- a/drivers/usb/host/xhci-plat.h ++++ b/drivers/usb/host/xhci-plat.h +@@ -13,7 +13,6 @@ + struct xhci_plat_priv { + const char *firmware_name; + unsigned long long quirks; +- int (*plat_setup)(struct usb_hcd *); + void (*plat_start)(struct usb_hcd *); + int (*init_quirk)(struct usb_hcd *); + int (*suspend_quirk)(struct usb_hcd *); diff --git a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch new file mode 100644 index 0000000000..857ee66a31 --- /dev/null +++ b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch @@ -0,0 +1,36 @@ +From 9a352062b7e3857742389dff6f64393481dc755e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 23 Sep 2021 19:37:05 +0200 +Subject: [PATCH] Revert "PCI: aardvark: Fix initialization with old Marvell's + Arm Trusted Firmware" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit b0c6ae0f8948a2be6bf4e8b4bbab9ca1343289b6. + +Armada 3720 phy driver (phy-mvebu-a3700-comphy.c) does not return +-EOPNOTSUPP from phy_power_on() callback anymore. + +So remove dead code which handles -EOPNOTSUPP return value. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Acked-by: Miquel Raynal +--- + drivers/pci/controller/pci-aardvark.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -1637,9 +1637,7 @@ static int advk_pcie_enable_phy(struct a + } + + ret = phy_power_on(pcie->phy); +- if (ret == -EOPNOTSUPP) { +- dev_warn(&pcie->pdev->dev, "PHY unsupported by firmware\n"); +- } else if (ret) { ++ if (ret) { + phy_exit(pcie->phy); + return ret; + } diff --git a/target/linux/generic/pending-5.15/920-mangle_bootargs.patch b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch new file mode 100644 index 0000000000..fc64a4205e --- /dev/null +++ b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch @@ -0,0 +1,71 @@ +From: Imre Kaloz +Subject: init: add CONFIG_MANGLE_BOOTARGS and disable it by default + +Enabling this option renames the bootloader supplied root= +and rootfstype= variables, which might have to be know but +would break the automatisms OpenWrt uses. + +Signed-off-by: Imre Kaloz +--- + init/Kconfig | 9 +++++++++ + init/main.c | 24 ++++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1800,6 +1800,15 @@ config EMBEDDED + an embedded system so certain expert options are available + for configuration. + ++config MANGLE_BOOTARGS ++ bool "Rename offending bootargs" ++ depends on EXPERT ++ help ++ Sometimes the bootloader passed bogus root= and rootfstype= ++ parameters to the kernel, and while you want to ignore them, ++ you need to know the values f.e. to support dual firmware ++ layouts on the flash. ++ + config HAVE_PERF_EVENTS + bool + help +--- a/init/main.c ++++ b/init/main.c +@@ -608,6 +608,29 @@ static inline void setup_nr_cpu_ids(void + static inline void smp_prepare_cpus(unsigned int maxcpus) { } + #endif + ++#ifdef CONFIG_MANGLE_BOOTARGS ++static void __init mangle_bootargs(char *command_line) ++{ ++ char *rootdev; ++ char *rootfs; ++ ++ rootdev = strstr(command_line, "root=/dev/mtdblock"); ++ ++ if (rootdev) ++ strncpy(rootdev, "mangled_rootblock=", 18); ++ ++ rootfs = strstr(command_line, "rootfstype"); ++ ++ if (rootfs) ++ strncpy(rootfs, "mangled_fs", 10); ++ ++} ++#else ++static void __init mangle_bootargs(char *command_line) ++{ ++} ++#endif ++ + /* + * We need to store the untouched command line for future reference. + * We also need to store the touched command line since the parameter +@@ -869,6 +892,7 @@ asmlinkage __visible void __init __no_sa + pr_notice("%s", linux_banner); + early_security_init(); + setup_arch(&command_line); ++ mangle_bootargs(command_line); + setup_boot_config(command_line); + setup_command_line(command_line); + setup_nr_cpu_ids(); From 79dfa447333cdab7e8b03e068473b3a8deda2c9a Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 4 Nov 2021 23:21:11 +0100 Subject: [PATCH 04/26] generic: 5.15: drop upstream patch Drop upstream patch from backport dir for kernel 5.15 Signed-off-by: Ansuel Smith --- ...dcode-path-to-awk-in-scripts-ld-vers.patch | 30 - ...station-poweroff-add-missing-put_dev.patch | 27 - ...a-neon-optimize-for-non-block-size-m.patch | 272 -- ...a-neon-add-missing-counter-increment.patch | 38 - ...ut-frequently-used-members-above-cac.patch | 42 - ...CPU_MIPS64-for-remaining-MIPS64-CPUs.patch | 36 - ...boot-put-appended-dtb-into-a-section.patch | 36 - ...convert-fixed-partitions-to-the-json.patch | 324 -- ...move-partition-binding-to-its-own-fi.patch | 115 - ...d-add-binding-for-BCM4908-partitions.patch | 92 - ...art-support-BCM4908-fixed-partitions.patch | 654 ---- ...rt-limit-parsing-of-deprecated-DT-sy.patch | 69 - ...rt-make-symbol-bcm4908_partitions_qu.patch | 34 - ...em-cells-compatible-to-parse-mtd-as-.patch | 38 - ...ings-nvmem-drop-nodename-restriction.patch | 25 - ...Document-use-of-nvmem-cells-compatib.patch | 117 - ...add-binding-for-Linksys-Northstar-pa.patch | 98 - ...rt-support-Linksys-Northstar-partiti.patch | 156 - ...0002-Disable-buffered-writes-for-AMD.patch | 54 - ...ings-mtd-brcm-trx-Add-brcm-trx-magic.patch | 32 - ...Allow-to-specify-brcm-trx-magic-in-D.patch | 50 - ...Allow-to-use-TRX-parser-on-Mediatek-.patch | 25 - ...13-ubifs-default-to-zstd-compression.patch | 25 - ...pi-poll-functionality-to-__napi_poll.patch | 88 - ...threaded-able-napi-poll-loop-support.patch | 261 -- ...tribute-to-control-napi-threaded-mod.patch | 177 - ...ween-napi-kthread-mode-and-busy-poll.patch | 93 - ...up-on-napi_disable-for-threaded-napi.patch | 53 - ...table-add-hash-offset-field-to-tuple.patch | 52 - ...ble-separate-replace-destroy-and-sta.patch | 98 - ...ack-Remove-unused-variable-declarati.patch | 22 - ...ble-consolidate-skb_try_make_writabl.patch | 291 -- ...ble-move-skb_try_make_writable-befor.patch | 35 - ...ble-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch | 82 - ...wtable-fast-NAT-functions-never-fail.patch | 394 --- ...ble-call-dst_check-to-fall-back-to-c.patch | 46 - ...ble-refresh-timeout-after-dst-and-wr.patch | 49 - ...es-update-table-flags-from-the-commi.patch | 103 - ...arding-path-from-virtual-netdevice-a.patch | 170 - ...lve-forwarding-path-for-vlan-devices.patch | 80 - ...ve-forwarding-path-for-bridge-device.patch | 62 - ...ve-forwarding-path-for-VLAN-tag-acti.patch | 207 -- ...forwarding-path-for-bridge-pppoe-dev.patch | 113 - ...-forwarding-path-for-dsa-slave-ports.patch | 63 - ...filter-flowtable-add-xmit-path-types.patch | 147 - ...ble-use-dev_fill_forward_path-to-obt.patch | 191 -- ...ble-use-dev_fill_forward_path-to-obt.patch | 374 --- ...netfilter-flowtable-add-vlan-support.patch | 410 --- ...ble-add-bridge-vlan-filtering-suppor.patch | 30 - ...etfilter-flowtable-add-pppoe-support.patch | 145 - ...-netfilter-flowtable-add-dsa-support.patch | 32 - ...ter-flowtable-bridge-and-vlan-suppor.patch | 107 - ...ble-add-offload-support-for-xmit-pat.patch | 310 -- ...ow_offload-use-direct-xmit-if-hardwa.patch | 114 - ...ble-bridge-vlan-hardware-offload-and.patch | 123 - ...w_offload-add-FLOW_ACTION_PPPOE_PUSH.patch | 30 - ...ble-support-for-FLOW_ACTION_PPPOE_PU.patch | 35 - ...sa-slave-add-support-for-TC_SETUP_FT.patch | 53 - ...k_eth_soc-fix-parsing-packets-in-GDM.patch | 68 - ..._eth_soc-add-support-for-initializin.patch | 1308 -------- ..._eth_soc-add-flow-offloading-support.patch | 568 ---- ...e-update-documentation-with-enhancem.patch | 236 -- ...rnet-mediatek-ppe-fix-busy-wait-loop.patch | 72 - ...iatek-fix-a-typo-bug-in-flow-offload.patch | 29 - ..._eth_soc-unmap-RX-data-before-callin.patch | 38 - ...et-mtk_eth_soc-fix-build_skb-cleanup.patch | 38 - ...net-mtk_eth_soc-use-napi_consume_skb.patch | 77 - ..._eth_soc-reduce-MDIO-bus-access-late.patch | 30 - ..._eth_soc-remove-unnecessary-TX-queue.patch | 54 - ..._eth_soc-use-larger-burst-size-for-Q.patch | 37 - ...-mtk_eth_soc-increase-DMA-ring-sizes.patch | 26 - ..._eth_soc-implement-dynamic-interrupt.patch | 313 -- ..._eth_soc-cache-HW-pointer-of-last-fr.patch | 73 - ..._eth_soc-only-read-the-full-RX-descr.patch | 49 - ..._eth_soc-reduce-unnecessary-interrup.patch | 39 - ...et-mtk_eth_soc-rework-NAPI-callbacks.patch | 110 - ..._eth_soc-set-PPE-flow-hash-as-skb-ha.patch | 47 - ..._eth_soc-use-iopoll.h-macro-for-DMA-.patch | 71 - ...t-ethernet-mtk_eth_soc-missing-mutex.patch | 63 - ...t-mtk_eth_soc-handle-VLAN-pop-action.patch | 22 - ...ble-dst_check-from-garbage-collector.patch | 159 - ...ack-Introduce-tcp-offload-timeout-co.patch | 94 - ...ack-Introduce-udp-offload-timeout-co.patch | 92 - ...ble-Set-offload-timeouts-according-t.patch | 134 - ...thernet-mediatek-support-setting-MTU.patch | 138 - ...x-select-correct-page-on-config-init.patch | 108 - ...ix-probe-error-if-copper-page-is-sel.patch | 73 - ...10-v5.12-net-phy-Add-100-base-x-mode.patch | 56 - ...-sfp-add-support-for-100-base-x-SFPs.patch | 40 - ...phy-marvell-refactor-HWMON-OOP-style.patch | 549 ---- ...-marvell-add-SFP-support-for-88E1510.patch | 161 - ...cally-bring-up-DSA-master-when-openi.patch | 85 - ...y-switchdev-of-disappearance-of-old-.patch | 126 - ...r-when-a-non-legacy-FDB-operation-fa.patch | 52 - ...e-switchdev_notifier_fdb_info-in-dsa.patch | 226 -- ...tchdev-event-implementation-under-th.patch | 85 - ...ly-in-dsa_slave_switchdev_event-if-w.patch | 42 - ...or-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch | 264 -- ...setup-core-clock-even-in-TRGMII-mode.patch | 84 - ...-mt7530-MT7530-optional-GPIO-support.patch | 181 -- ...-mt7530-Add-support-for-EEE-features.patch | 120 - ...the-dst-buffer-to-of_get_mac_address.patch | 1935 ----------- ..._addr_nvmem-for-non-platform-devices.patch | 77 - ...andle-deferred-probe-error-due-to-ma.patch | 42 - ...platform-handle-mac-address-deferral.patch | 36 - ...k-change-simple-print-to-dev-variant.patch | 35 - ...use-iopoll-macro-for-qca8k_busy_wait.patch | 61 - ...prove-qca8k-read-write-rmw-bus-acces.patch | 86 - ...a-qca8k-handle-qca8k_set_page-errors.patch | 101 - ...ndle-error-with-qca8k_read-operation.patch | 207 -- ...ndle-error-with-qca8k_write-operatio.patch | 263 -- ...andle-error-with-qca8k_rmw-operation.patch | 226 -- ...8k-handle-error-from-qca8k_busy_wait.patch | 66 - ...qca8k-add-support-for-qca8327-switch.patch | 96 - ...sa-qca8k-Document-new-compatible-qca.patch | 26 - ...add-priority-tweak-to-qca8337-switch.patch | 130 - ...a-qca8k-limit-port5-delay-to-qca8337.patch | 31 - ...d-GLOBAL_FC-settings-needed-for-qca8.patch | 48 - ...dsa-qca8k-add-support-for-switch-rev.patch | 114 - ...d-ethernet-ports-fallback-to-setup_m.patch | 28 - ...-qca8k-make-rgmii-delay-configurable.patch | 188 -- ...clear-MASTER_EN-after-phy-read-write.patch | 50 - ...a-qca8k-protect-MASTER-busy_wait-wit.patch | 128 - ...qca8k-enlarge-mdio-delay-and-timeout.patch | 39 - ...d-support-for-internal-phy-and-inter.patch | 267 -- ...ngs-dsa-qca8k-Document-internal-mdio.patch | 93 - ...prove-internal-mdio-read-write-bus-a.patch | 95 - ...ss-switch_revision-info-to-phy-dev_f.patch | 48 - ...ort-for-qca8k-switch-internal-PHY-in.patch | 229 -- ...issing-unlock-on-error-in-qca8k-vlan.patch | 64 - ...eck-return-value-of-read-functions-c.patch | 348 -- ...d-missing-check-return-value-in-qca8.patch | 47 - ...x-an-endian-bug-in-qca8k-get-ethtool.patch | 47 - ...eck-the-correct-variable-in-qca8k-se.patch | 31 - ...ernel-panic-with-legacy-mdio-mapping.patch | 80 - ...-Add-debug-prints-in-b53_vlan_enable.patch | 65 - ...sa-b53-spi-allow-device-tree-probing.patch | 41 - ...3-net-dsa-b53-relax-is63xx-condition.patch | 31 - ...tag_brcm-add-support-for-legacy-tags.patch | 180 - ...0005-net-dsa-b53-support-legacy-tags.patch | 53 - ...dsa-b53-mmap-Add-device-tree-support.patch | 92 - ...-spi-add-missing-MODULE_DEVICE_TABLE.patch | 27 - ...Do-not-force-CPU-to-be-always-tagged.patch | 86 - ...3-remove-redundant-null-check-on-dev.patch | 30 - ...Create-default-VLAN-entry-explicitly.patch | 71 - ...t-skb-offload_fwd_mark-when-not-offl.patch | 138 - ...1-net-dsa-mt7530-support-setting-MTU.patch | 112 - ...-dsa-mt7530-enable-MTU-normalization.patch | 36 - ...a-mt7530-support-setting-ageing-time.patch | 99 - ...disable-learning-on-standalone-ports.patch | 65 - ...enable-assisted-learning-on-CPU-port.patch | 102 - ...se-independent-VLAN-learning-on-VLAN.patch | 262 -- ...-mt7530-set-STP-state-on-filter-ID-1.patch | 40 - ...lways-install-FDB-entries-with-IVL-a.patch | 54 - ...et-dsa-mt7530-support-MDB-operations.patch | 171 - ...MediaTek-Gigabit-Ethernet-PHY-driver.patch | 159 - ...net-dsa-mt7530-add-interrupt-support.patch | 425 --- ...5.15-1-igc-remove-_I_PHY_ID-checking.patch | 73 - ...v5.15-2-igc-remove-phy-type-checking.patch | 43 - ...ovide-missing-documentation-for-some.patch | 72 - ...x-a-couple-of-spelling-errors-in-fw_.patch | 34 - ...153_ecm-support-ECM-mode-for-RTL8153.patch | 320 -- ...12-net-usb-r8152-use-new-tasklet-API.patch | 41 - ...veral-functions-about-phy-patch-requ.patch | 198 -- ...t-the-flow-of-power-cut-for-RTL8153B.patch | 134 - ...152-enable-U1-U2-for-USB_SPEED_SUPER.patch | 47 - ...f-the-pointer-of-the-function-exists.patch | 51 - ...r8152-replace-netif_err-with-dev_err.patch | 36 - ...rtl_set_eee_plus-and-r8153b_green_en.patch | 89 - ...ter-fram-gap-time-depending-on-speed.patch | 75 - ...just-rtl8152_check_firmware-function.patch | 152 - ...8152-add-help-function-to-change-mtu.patch | 157 - .../793-v5.13-r8152-support-new-chips.patch | 2886 ----------------- ...port-PHY-firmware-for-RTL8156-series.patch | 691 ---- ...rch-the-configuration-of-vendor-mode.patch | 79 - ..._nvram-rename-finding-function-and-i.patch | 80 - ..._nvram-add-helper-checking-for-NVRAM.patch | 90 - ...7xx_nvram-extract-code-copying-NVRAM.patch | 80 - ..._nvram-look-for-NVRAM-with-for-inste.patch | 37 - ..._nvram-inline-code-checking-NVRAM-si.patch | 70 - ...rious-flag-to-disable-overcurrent-ch.patch | 88 - ...-platform-add-spurious_oc-DT-support.patch | 31 - ...-declare-its-reliance-on-msi-domains.patch | 34 - ...declar-their-reliance-on-msi-domains.patch | 44 - ...ertise-lack-of-built-in-msi-handling.patch | 59 - ...ialize-enable-GPIO-direction-to-outp.patch | 28 - ...mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch | 67 - ...mvebu-a3700-comphy-Remove-unsupporte.patch | 40 - 188 files changed, 26893 deletions(-) delete mode 100644 target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch delete mode 100644 target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch delete mode 100644 target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch delete mode 100644 target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch delete mode 100644 target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch delete mode 100644 target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch delete mode 100644 target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch delete mode 100644 target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch delete mode 100644 target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch delete mode 100644 target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch delete mode 100644 target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch delete mode 100644 target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch delete mode 100644 target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch delete mode 100644 target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch delete mode 100644 target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch delete mode 100644 target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch delete mode 100644 target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch delete mode 100644 target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch delete mode 100644 target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch delete mode 100644 target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch delete mode 100644 target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch delete mode 100644 target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch delete mode 100644 target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch delete mode 100644 target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch delete mode 100644 target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch delete mode 100644 target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch delete mode 100644 target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch delete mode 100644 target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch delete mode 100644 target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch delete mode 100644 target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch delete mode 100644 target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch delete mode 100644 target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch delete mode 100644 target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch delete mode 100644 target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch delete mode 100644 target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch delete mode 100644 target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch delete mode 100644 target/linux/generic/backport-5.15/719-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch delete mode 100644 target/linux/generic/backport-5.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch delete mode 100644 target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch delete mode 100644 target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch delete mode 100644 target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch delete mode 100644 target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch delete mode 100644 target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch delete mode 100644 target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch delete mode 100644 target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch delete mode 100644 target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch delete mode 100644 target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch delete mode 100644 target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch delete mode 100644 target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch delete mode 100644 target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch delete mode 100644 target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch delete mode 100644 target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch delete mode 100644 target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch delete mode 100644 target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch delete mode 100644 target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch delete mode 100644 target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch delete mode 100644 target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch delete mode 100644 target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch delete mode 100644 target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch delete mode 100644 target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch delete mode 100644 target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch delete mode 100644 target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch delete mode 100644 target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch delete mode 100644 target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch delete mode 100644 target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch delete mode 100644 target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch delete mode 100644 target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch delete mode 100644 target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch delete mode 100644 target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch delete mode 100644 target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch delete mode 100644 target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch delete mode 100644 target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch delete mode 100644 target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch delete mode 100644 target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch delete mode 100644 target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch delete mode 100644 target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch delete mode 100644 target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch delete mode 100644 target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch delete mode 100644 target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch delete mode 100644 target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch delete mode 100644 target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch delete mode 100644 target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch delete mode 100644 target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch delete mode 100644 target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch delete mode 100644 target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch delete mode 100644 target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch delete mode 100644 target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch delete mode 100644 target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch delete mode 100644 target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch delete mode 100644 target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch delete mode 100644 target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch delete mode 100644 target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch delete mode 100644 target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch delete mode 100644 target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch delete mode 100644 target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch delete mode 100644 target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch delete mode 100644 target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch delete mode 100644 target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch delete mode 100644 target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch delete mode 100644 target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch delete mode 100644 target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch delete mode 100644 target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch delete mode 100644 target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch delete mode 100644 target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch diff --git a/target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch b/target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch deleted file mode 100644 index 7ac4f9d240..0000000000 --- a/target/linux/generic/backport-5.15/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 13b1ecc3401653a355798eb1dee10cc1608202f4 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Mon, 18 Jan 2016 12:27:49 +0100 -Subject: [PATCH 33/34] Kbuild: don't hardcode path to awk in - scripts/ld-version.sh - -On some systems /usr/bin/awk does not exist, or is broken. Find it via -$PATH instead. - -Signed-off-by: Felix Fietkau ---- - scripts/ld-version.sh | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/scripts/ld-version.sh -+++ b/scripts/ld-version.sh -@@ -1,6 +1,7 @@ --#!/usr/bin/awk -f -+#!/bin/sh - # SPDX-License-Identifier: GPL-2.0 - # extract linker version number from stdin and turn into single number -+exec awk ' - { - gsub(".*\\)", ""); - gsub(".*version ", ""); -@@ -9,3 +10,4 @@ - print a[1]*100000000 + a[2]*1000000 + a[3]*10000; - exit - } -+' diff --git a/target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch b/target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch deleted file mode 100644 index 66e75bf514..0000000000 --- a/target/linux/generic/backport-5.15/026-power-reset-linkstation-poweroff-add-missing-put_dev.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 1027a42c25cbf8cfc4ade6503c5110aae04866af Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez=20Cabanelas?= -Date: Fri, 16 Oct 2020 20:22:37 +0200 -Subject: [PATCH] power: reset: linkstation-poweroff: add missing put_device() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The of_mdio_find_bus() takes a reference to the underlying device -structure, we should release that reference using a put_device() call. - -Signed-off-by: Daniel González Cabanelas -Signed-off-by: Sebastian Reichel ---- - drivers/power/reset/linkstation-poweroff.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/power/reset/linkstation-poweroff.c -+++ b/drivers/power/reset/linkstation-poweroff.c -@@ -113,6 +113,7 @@ static int __init linkstation_poweroff_i - return -EPROBE_DEFER; - - phydev = phy_find_first(bus); -+ put_device(&bus->dev); - if (!phydev) - return -EPROBE_DEFER; - diff --git a/target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch b/target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch deleted file mode 100644 index b1f46e9af8..0000000000 --- a/target/linux/generic/backport-5.15/071-crypto-arm-chacha-neon-optimize-for-non-block-size-m.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 03662fcd41f4b764857f17b95f9a2a63c24bddd4 Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel -Date: Tue, 3 Nov 2020 17:28:09 +0100 -Subject: [PATCH 1/2] crypto: arm/chacha-neon - optimize for non-block size - multiples - -commit 86cd97ec4b943af35562a74688bc4e909b32c3d1 upstream. - -The current NEON based ChaCha implementation for ARM is optimized for -multiples of 4x the ChaCha block size (64 bytes). This makes sense for -block encryption, but given that ChaCha is also often used in the -context of networking, it makes sense to consider arbitrary length -inputs as well. - -For example, WireGuard typically uses 1420 byte packets, and performing -ChaCha encryption involves 5 invocations of chacha_4block_xor_neon() -and 3 invocations of chacha_block_xor_neon(), where the last one also -involves a memcpy() using a buffer on the stack to process the final -chunk of 1420 % 64 == 12 bytes. - -Let's optimize for this case as well, by letting chacha_4block_xor_neon() -deal with any input size between 64 and 256 bytes, using NEON permutation -instructions and overlapping loads and stores. This way, the 140 byte -tail of a 1420 byte input buffer can simply be processed in one go. - -This results in the following performance improvements for 1420 byte -blocks, without significant impact on power-of-2 input sizes. (Note -that Raspberry Pi is widely used in combination with a 32-bit kernel, -even though the core is 64-bit capable) - - Cortex-A8 (BeagleBone) : 7% - Cortex-A15 (Calxeda Midway) : 21% - Cortex-A53 (Raspberry Pi 3) : 3% - Cortex-A72 (Raspberry Pi 4) : 19% - -Cc: Eric Biggers -Cc: "Jason A . Donenfeld" -Signed-off-by: Ard Biesheuvel -Signed-off-by: Herbert Xu -Signed-off-by: Jason A. Donenfeld ---- - arch/arm/crypto/chacha-glue.c | 34 +++++------ - arch/arm/crypto/chacha-neon-core.S | 97 +++++++++++++++++++++++++++--- - 2 files changed, 107 insertions(+), 24 deletions(-) - ---- a/arch/arm/crypto/chacha-glue.c -+++ b/arch/arm/crypto/chacha-glue.c -@@ -23,7 +23,7 @@ - asmlinkage void chacha_block_xor_neon(const u32 *state, u8 *dst, const u8 *src, - int nrounds); - asmlinkage void chacha_4block_xor_neon(const u32 *state, u8 *dst, const u8 *src, -- int nrounds); -+ int nrounds, unsigned int nbytes); - asmlinkage void hchacha_block_arm(const u32 *state, u32 *out, int nrounds); - asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds); - -@@ -42,24 +42,24 @@ static void chacha_doneon(u32 *state, u8 - { - u8 buf[CHACHA_BLOCK_SIZE]; - -- while (bytes >= CHACHA_BLOCK_SIZE * 4) { -- chacha_4block_xor_neon(state, dst, src, nrounds); -- bytes -= CHACHA_BLOCK_SIZE * 4; -- src += CHACHA_BLOCK_SIZE * 4; -- dst += CHACHA_BLOCK_SIZE * 4; -- state[12] += 4; -- } -- while (bytes >= CHACHA_BLOCK_SIZE) { -- chacha_block_xor_neon(state, dst, src, nrounds); -- bytes -= CHACHA_BLOCK_SIZE; -- src += CHACHA_BLOCK_SIZE; -- dst += CHACHA_BLOCK_SIZE; -- state[12]++; -+ while (bytes > CHACHA_BLOCK_SIZE) { -+ unsigned int l = min(bytes, CHACHA_BLOCK_SIZE * 4U); -+ -+ chacha_4block_xor_neon(state, dst, src, nrounds, l); -+ bytes -= l; -+ src += l; -+ dst += l; -+ state[12] += DIV_ROUND_UP(l, CHACHA_BLOCK_SIZE); - } - if (bytes) { -- memcpy(buf, src, bytes); -- chacha_block_xor_neon(state, buf, buf, nrounds); -- memcpy(dst, buf, bytes); -+ const u8 *s = src; -+ u8 *d = dst; -+ -+ if (bytes != CHACHA_BLOCK_SIZE) -+ s = d = memcpy(buf, src, bytes); -+ chacha_block_xor_neon(state, d, s, nrounds); -+ if (d != dst) -+ memcpy(dst, buf, bytes); - } - } - ---- a/arch/arm/crypto/chacha-neon-core.S -+++ b/arch/arm/crypto/chacha-neon-core.S -@@ -47,6 +47,7 @@ - */ - - #include -+#include - - .text - .fpu neon -@@ -205,7 +206,7 @@ ENDPROC(hchacha_block_neon) - - .align 5 - ENTRY(chacha_4block_xor_neon) -- push {r4-r5} -+ push {r4, lr} - mov r4, sp // preserve the stack pointer - sub ip, sp, #0x20 // allocate a 32 byte buffer - bic ip, ip, #0x1f // aligned to 32 bytes -@@ -229,10 +230,10 @@ ENTRY(chacha_4block_xor_neon) - vld1.32 {q0-q1}, [r0] - vld1.32 {q2-q3}, [ip] - -- adr r5, .Lctrinc -+ adr lr, .Lctrinc - vdup.32 q15, d7[1] - vdup.32 q14, d7[0] -- vld1.32 {q4}, [r5, :128] -+ vld1.32 {q4}, [lr, :128] - vdup.32 q13, d6[1] - vdup.32 q12, d6[0] - vdup.32 q11, d5[1] -@@ -455,7 +456,7 @@ ENTRY(chacha_4block_xor_neon) - - // Re-interleave the words in the first two rows of each block (x0..7). - // Also add the counter values 0-3 to x12[0-3]. -- vld1.32 {q8}, [r5, :128] // load counter values 0-3 -+ vld1.32 {q8}, [lr, :128] // load counter values 0-3 - vzip.32 q0, q1 // => (0 1 0 1) (0 1 0 1) - vzip.32 q2, q3 // => (2 3 2 3) (2 3 2 3) - vzip.32 q4, q5 // => (4 5 4 5) (4 5 4 5) -@@ -493,6 +494,8 @@ ENTRY(chacha_4block_xor_neon) - - // Re-interleave the words in the last two rows of each block (x8..15). - vld1.32 {q8-q9}, [sp, :256] -+ mov sp, r4 // restore original stack pointer -+ ldr r4, [r4, #8] // load number of bytes - vzip.32 q12, q13 // => (12 13 12 13) (12 13 12 13) - vzip.32 q14, q15 // => (14 15 14 15) (14 15 14 15) - vzip.32 q8, q9 // => (8 9 8 9) (8 9 8 9) -@@ -520,41 +523,121 @@ ENTRY(chacha_4block_xor_neon) - // XOR the rest of the data with the keystream - - vld1.8 {q0-q1}, [r2]! -+ subs r4, r4, #96 - veor q0, q0, q8 - veor q1, q1, q12 -+ ble .Lle96 - vst1.8 {q0-q1}, [r1]! - - vld1.8 {q0-q1}, [r2]! -+ subs r4, r4, #32 - veor q0, q0, q2 - veor q1, q1, q6 -+ ble .Lle128 - vst1.8 {q0-q1}, [r1]! - - vld1.8 {q0-q1}, [r2]! -+ subs r4, r4, #32 - veor q0, q0, q10 - veor q1, q1, q14 -+ ble .Lle160 - vst1.8 {q0-q1}, [r1]! - - vld1.8 {q0-q1}, [r2]! -+ subs r4, r4, #32 - veor q0, q0, q4 - veor q1, q1, q5 -+ ble .Lle192 - vst1.8 {q0-q1}, [r1]! - - vld1.8 {q0-q1}, [r2]! -+ subs r4, r4, #32 - veor q0, q0, q9 - veor q1, q1, q13 -+ ble .Lle224 - vst1.8 {q0-q1}, [r1]! - - vld1.8 {q0-q1}, [r2]! -+ subs r4, r4, #32 - veor q0, q0, q3 - veor q1, q1, q7 -+ blt .Llt256 -+.Lout: - vst1.8 {q0-q1}, [r1]! - - vld1.8 {q0-q1}, [r2] -- mov sp, r4 // restore original stack pointer - veor q0, q0, q11 - veor q1, q1, q15 - vst1.8 {q0-q1}, [r1] - -- pop {r4-r5} -- bx lr -+ pop {r4, pc} -+ -+.Lle192: -+ vmov q4, q9 -+ vmov q5, q13 -+ -+.Lle160: -+ // nothing to do -+ -+.Lfinalblock: -+ // Process the final block if processing less than 4 full blocks. -+ // Entered with 32 bytes of ChaCha cipher stream in q4-q5, and the -+ // previous 32 byte output block that still needs to be written at -+ // [r1] in q0-q1. -+ beq .Lfullblock -+ -+.Lpartialblock: -+ adr lr, .Lpermute + 32 -+ add r2, r2, r4 -+ add lr, lr, r4 -+ add r4, r4, r1 -+ -+ vld1.8 {q2-q3}, [lr] -+ vld1.8 {q6-q7}, [r2] -+ -+ add r4, r4, #32 -+ -+ vtbl.8 d4, {q4-q5}, d4 -+ vtbl.8 d5, {q4-q5}, d5 -+ vtbl.8 d6, {q4-q5}, d6 -+ vtbl.8 d7, {q4-q5}, d7 -+ -+ veor q6, q6, q2 -+ veor q7, q7, q3 -+ -+ vst1.8 {q6-q7}, [r4] // overlapping stores -+ vst1.8 {q0-q1}, [r1] -+ pop {r4, pc} -+ -+.Lfullblock: -+ vmov q11, q4 -+ vmov q15, q5 -+ b .Lout -+.Lle96: -+ vmov q4, q2 -+ vmov q5, q6 -+ b .Lfinalblock -+.Lle128: -+ vmov q4, q10 -+ vmov q5, q14 -+ b .Lfinalblock -+.Lle224: -+ vmov q4, q3 -+ vmov q5, q7 -+ b .Lfinalblock -+.Llt256: -+ vmov q4, q11 -+ vmov q5, q15 -+ b .Lpartialblock - ENDPROC(chacha_4block_xor_neon) -+ -+ .align L1_CACHE_SHIFT -+.Lpermute: -+ .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 -+ .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f -+ .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 -+ .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f -+ .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 -+ .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f -+ .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 -+ .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f diff --git a/target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch b/target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch deleted file mode 100644 index 1e4d2041e5..0000000000 --- a/target/linux/generic/backport-5.15/072-crypto-arm-chacha-neon-add-missing-counter-increment.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 7f63462faf9eab69132bea9abd48c2c05a93145b Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel -Date: Sun, 13 Dec 2020 15:39:29 +0100 -Subject: [PATCH 2/2] crypto: arm/chacha-neon - add missing counter increment - -commit fd16931a2f518a32753920ff20895e5cf04c8ff1 upstream. - -Commit 86cd97ec4b943af3 ("crypto: arm/chacha-neon - optimize for non-block -size multiples") refactored the chacha block handling in the glue code in -a way that may result in the counter increment to be omitted when calling -chacha_block_xor_neon() to process a full block. This violates the skcipher -API, which requires that the output IV is suitable for handling more input -as long as the preceding input has been presented in round multiples of the -block size. Also, the same code is exposed via the chacha library interface -whose callers may actually rely on this increment to occur even for final -blocks that are smaller than the chacha block size. - -So increment the counter after calling chacha_block_xor_neon(). - -Fixes: 86cd97ec4b943af3 ("crypto: arm/chacha-neon - optimize for non-block size multiples") -Reported-by: Eric Biggers -Signed-off-by: Ard Biesheuvel -Signed-off-by: Herbert Xu -Signed-off-by: Jason A. Donenfeld ---- - arch/arm/crypto/chacha-glue.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/crypto/chacha-glue.c -+++ b/arch/arm/crypto/chacha-glue.c -@@ -60,6 +60,7 @@ static void chacha_doneon(u32 *state, u8 - chacha_block_xor_neon(state, d, s, nrounds); - if (d != dst) - memcpy(dst, buf, bytes); -+ state[12]++; - } - } - diff --git a/target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch b/target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch deleted file mode 100644 index 444fd677b4..0000000000 --- a/target/linux/generic/backport-5.15/080-wireguard-peer-put-frequently-used-members-above-cac.patch +++ /dev/null @@ -1,42 +0,0 @@ -From a13827e9091c07e25cdeec9a402d74a27e2a1111 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Mon, 22 Feb 2021 17:25:46 +0100 -Subject: [PATCH] wireguard: peer: put frequently used members above cache - lines - -commit 5a0598695634a6bb4126818902dd9140cd9df8b6 upstream. - -The is_dead boolean is checked for every single packet, while the -internal_id member is used basically only for pr_debug messages. So it -makes sense to hoist up is_dead into some space formerly unused by a -struct hole, while demoting internal_api to below the lowest struct -cache line. - -Signed-off-by: Jason A. Donenfeld -Signed-off-by: Jakub Kicinski -Signed-off-by: Jason A. Donenfeld ---- - drivers/net/wireguard/peer.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireguard/peer.h -+++ b/drivers/net/wireguard/peer.h -@@ -39,6 +39,7 @@ struct wg_peer { - struct prev_queue tx_queue, rx_queue; - struct sk_buff_head staged_packet_queue; - int serial_work_cpu; -+ bool is_dead; - struct noise_keypairs keypairs; - struct endpoint endpoint; - struct dst_cache endpoint_cache; -@@ -61,9 +62,8 @@ struct wg_peer { - struct rcu_head rcu; - struct list_head peer_list; - struct list_head allowedips_list; -- u64 internal_id; - struct napi_struct napi; -- bool is_dead; -+ u64 internal_id; - }; - - struct wg_peer *wg_peer_create(struct wg_device *wg, diff --git a/target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch b/target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch deleted file mode 100644 index fafe530ac5..0000000000 --- a/target/linux/generic/backport-5.15/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 6523061868212473f63812a0c477a161742bed42 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Sat, 27 Feb 2021 13:20:24 +0100 -Subject: [PATCH] MIPS: select CPU_MIPS64 for remaining MIPS64 CPUs - -The CPU_MIPS64 and CPU_MIPS32 variables are supposed to be able to -distinguish broadly between 64-bit and 32-bit MIPS CPUs. However, they -weren't selected by the specialty CPUs, Octeon and Loongson, which meant -it was possible to hit a weird state of: - - MIPS=y, CONFIG_64BIT=y, CPU_MIPS64=n - -This commit rectifies the issue by having CPU_MIPS64 be selected when -the missing Octeon or Loongson models are selected. - -Cc: Thomas Bogendoerfer -Cc: Ralf Baechle -Cc: George Cherian -Cc: Huacai Chen -Cc: Jiaxun Yang -Signed-off-by: Jason A. Donenfeld ---- - arch/mips/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -2088,7 +2088,7 @@ config CPU_MIPS32 - config CPU_MIPS64 - bool - default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R5 || \ -- CPU_MIPS64_R6 -+ CPU_MIPS64_R6 || CPU_LOONGSON64 || CPU_CAVIUM_OCTEON - - # - # These indicate the revision of the architecture diff --git a/target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch b/target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch deleted file mode 100644 index 3f8808f702..0000000000 --- a/target/linux/generic/backport-5.15/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 7d1531c81c0fb4c93bea8dc316043ad0e4d0c270 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Sun, 25 Oct 2020 23:19:40 +0800 -Subject: [PATCH] MIPS: zboot: put appended dtb into a section - -This will make a separated section for dtb appear in ELF, and we can -then use objcopy to patch a dtb into vmlinuz when RAW_APPENDED_DTB -is set in kernel config. - -command to patch a dtb: -objcopy --set-section-flags=.appended_dtb=alloc,contents \ - --update-section=.appended_dtb=.dtb vmlinuz vmlinuz-dtb - -Signed-off-by: Chuanhong Guo ---- - arch/mips/boot/compressed/ld.script | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/arch/mips/boot/compressed/ld.script -+++ b/arch/mips/boot/compressed/ld.script -@@ -31,9 +31,12 @@ SECTIONS - CONSTRUCTORS - . = ALIGN(16); - } -- __appended_dtb = .; -- /* leave space for appended DTB */ -- . += 0x100000; -+ -+ .appended_dtb : { -+ __appended_dtb = .; -+ /* leave space for appended DTB */ -+ . += 0x100000; -+ } - - _edata = .; - /* End of data section */ diff --git a/target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch b/target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch deleted file mode 100644 index 8aded43526..0000000000 --- a/target/linux/generic/backport-5.15/401-v5.11-dt-bindings-mtd-convert-fixed-partitions-to-the-json.patch +++ /dev/null @@ -1,324 +0,0 @@ -From 04e9ab75267489224364fa510a88ada83e11c325 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 10 Dec 2020 18:23:52 +0100 -Subject: [PATCH] dt-bindings: mtd: convert "fixed-partitions" to the - json-schema -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This standardizes its documentation, allows validating with Makefile -checks and helps writing DTS files. - -Noticeable changes: -1. Dropped "Partitions can be represented by sub-nodes of a flash - device." as we also support subpartitions (don't have to be part of - flash device node) -2. Dropped "to Linux" as bindings are meant to be os agnostic. - -Signed-off-by: Rafał Miłecki -Link: https://lore.kernel.org/r/20201210172352.31632-1-zajec5@gmail.com -Signed-off-by: Rob Herring ---- - .../devicetree/bindings/mtd/partition.txt | 131 +-------------- - .../mtd/partitions/fixed-partitions.yaml | 152 ++++++++++++++++++ - 2 files changed, 154 insertions(+), 129 deletions(-) - create mode 100644 Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml - ---- a/Documentation/devicetree/bindings/mtd/partition.txt -+++ b/Documentation/devicetree/bindings/mtd/partition.txt -@@ -24,137 +24,10 @@ another partitioning method. - Available bindings are listed in the "partitions" subdirectory. - - --Fixed Partitions --================ -- --Partitions can be represented by sub-nodes of a flash device. This can be used --on platforms which have strong conventions about which portions of a flash are --used for what purposes, but which don't use an on-flash partition table such --as RedBoot. -- --The partition table should be a subnode of the flash node and should be named --'partitions'. This node should have the following property: --- compatible : (required) must be "fixed-partitions" --Partitions are then defined in subnodes of the partitions node. -+Deprecated: partitions defined in flash node -+============================================ - - For backwards compatibility partitions as direct subnodes of the flash device are - supported. This use is discouraged. - NOTE: also for backwards compatibility, direct subnodes that have a compatible - string are not considered partitions, as they may be used for other bindings. -- --#address-cells & #size-cells must both be present in the partitions subnode of the --flash device. There are two valid values for both: --<1>: for partitions that require a single 32-bit cell to represent their -- size/address (aka the value is below 4 GiB) --<2>: for partitions that require two 32-bit cells to represent their -- size/address (aka the value is 4 GiB or greater). -- --Required properties: --- reg : The partition's offset and size within the flash -- --Optional properties: --- label : The label / name for this partition. If omitted, the label is taken -- from the node name (excluding the unit address). --- read-only : This parameter, if present, is a hint to Linux that this -- partition should only be mounted read-only. This is usually used for flash -- partitions containing early-boot firmware images or data which should not be -- clobbered. --- lock : Do not unlock the partition at initialization time (not supported on -- all devices) --- slc-mode: This parameter, if present, allows one to emulate SLC mode on a -- partition attached to an MLC NAND thus making this partition immune to -- paired-pages corruptions -- --Examples: -- -- --flash@0 { -- partitions { -- compatible = "fixed-partitions"; -- #address-cells = <1>; -- #size-cells = <1>; -- -- partition@0 { -- label = "u-boot"; -- reg = <0x0000000 0x100000>; -- read-only; -- }; -- -- uimage@100000 { -- reg = <0x0100000 0x200000>; -- }; -- }; --}; -- --flash@1 { -- partitions { -- compatible = "fixed-partitions"; -- #address-cells = <1>; -- #size-cells = <2>; -- -- /* a 4 GiB partition */ -- partition@0 { -- label = "filesystem"; -- reg = <0x00000000 0x1 0x00000000>; -- }; -- }; --}; -- --flash@2 { -- partitions { -- compatible = "fixed-partitions"; -- #address-cells = <2>; -- #size-cells = <2>; -- -- /* an 8 GiB partition */ -- partition@0 { -- label = "filesystem #1"; -- reg = <0x0 0x00000000 0x2 0x00000000>; -- }; -- -- /* a 4 GiB partition */ -- partition@200000000 { -- label = "filesystem #2"; -- reg = <0x2 0x00000000 0x1 0x00000000>; -- }; -- }; --}; -- --flash@3 { -- partitions { -- compatible = "fixed-partitions"; -- #address-cells = <1>; -- #size-cells = <1>; -- -- partition@0 { -- label = "bootloader"; -- reg = <0x000000 0x100000>; -- read-only; -- }; -- -- firmware@100000 { -- label = "firmware"; -- reg = <0x100000 0xe00000>; -- compatible = "brcm,trx"; -- }; -- -- calibration@f00000 { -- label = "calibration"; -- reg = <0xf00000 0x100000>; -- compatible = "fixed-partitions"; -- ranges = <0 0xf00000 0x100000>; -- #address-cells = <1>; -- #size-cells = <1>; -- -- partition@0 { -- label = "wifi0"; -- reg = <0x000000 0x080000>; -- }; -- -- partition@80000 { -- label = "wifi1"; -- reg = <0x080000 0x080000>; -- }; -- }; -- }; --}; ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml -@@ -0,0 +1,152 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/partitions/fixed-partitions.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Fixed partitions -+ -+description: | -+ This binding can be used on platforms which have strong conventions about -+ which portions of a flash are used for what purposes, but which don't use an -+ on-flash partition table such as RedBoot. -+ -+ The partition table should be a node named "partitions". Partitions are then -+ defined as subnodes. -+ -+maintainers: -+ - Rafał Miłecki -+ -+properties: -+ compatible: -+ const: fixed-partitions -+ -+ "#address-cells": true -+ -+ "#size-cells": true -+ -+patternProperties: -+ "@[0-9a-f]+$": -+ description: node describing a single flash partition -+ type: object -+ -+ properties: -+ reg: -+ description: partition's offset and size within the flash -+ maxItems: 1 -+ -+ label: -+ description: The label / name for this partition. If omitted, the label -+ is taken from the node name (excluding the unit address). -+ -+ read-only: -+ description: This parameter, if present, is a hint that this partition -+ should only be mounted read-only. This is usually used for flash -+ partitions containing early-boot firmware images or data which should -+ not be clobbered. -+ type: boolean -+ -+ lock: -+ description: Do not unlock the partition at initialization time (not -+ supported on all devices) -+ type: boolean -+ -+ slc-mode: -+ description: This parameter, if present, allows one to emulate SLC mode -+ on a partition attached to an MLC NAND thus making this partition -+ immune to paired-pages corruptions -+ type: boolean -+ -+ required: -+ - reg -+ -+required: -+ - "#address-cells" -+ - "#size-cells" -+ -+additionalProperties: true -+ -+examples: -+ - | -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "u-boot"; -+ reg = <0x0000000 0x100000>; -+ read-only; -+ }; -+ -+ uimage@100000 { -+ reg = <0x0100000 0x200000>; -+ }; -+ }; -+ - | -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <2>; -+ -+ /* a 4 GiB partition */ -+ partition@0 { -+ label = "filesystem"; -+ reg = <0x00000000 0x1 0x00000000>; -+ }; -+ }; -+ - | -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ /* an 8 GiB partition */ -+ partition@0 { -+ label = "filesystem #1"; -+ reg = <0x0 0x00000000 0x2 0x00000000>; -+ }; -+ -+ /* a 4 GiB partition */ -+ partition@200000000 { -+ label = "filesystem #2"; -+ reg = <0x2 0x00000000 0x1 0x00000000>; -+ }; -+ }; -+ - | -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bootloader"; -+ reg = <0x000000 0x100000>; -+ read-only; -+ }; -+ -+ firmware@100000 { -+ compatible = "brcm,trx"; -+ label = "firmware"; -+ reg = <0x100000 0xe00000>; -+ }; -+ -+ calibration@f00000 { -+ compatible = "fixed-partitions"; -+ label = "calibration"; -+ reg = <0xf00000 0x100000>; -+ ranges = <0 0xf00000 0x100000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "wifi0"; -+ reg = <0x000000 0x080000>; -+ }; -+ -+ partition@80000 { -+ label = "wifi1"; -+ reg = <0x080000 0x080000>; -+ }; -+ }; -+ }; diff --git a/target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch b/target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch deleted file mode 100644 index f3b1179ecd..0000000000 --- a/target/linux/generic/backport-5.15/402-v5.12-0001-dt-bindings-mtd-move-partition-binding-to-its-own-fi.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 6418522022c706fd867b00b2571edba48b8fa8c7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 11 Feb 2021 23:04:25 +0100 -Subject: [PATCH] dt-bindings: mtd: move partition binding to its own file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Single partition binding is quite common and may be: -1. Used by multiple parsers -2. Extended for more specific cases - -Move it to separated file to avoid code duplication. - -Signed-off-by: Rafał Miłecki -Reviewed-by: Rob Herring -Signed-off-by: Richard Weinberger ---- - .../mtd/partitions/fixed-partitions.yaml | 33 +------------ - .../bindings/mtd/partitions/partition.yaml | 47 +++++++++++++++++++ - 2 files changed, 48 insertions(+), 32 deletions(-) - create mode 100644 Documentation/devicetree/bindings/mtd/partitions/partition.yaml - ---- a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml -+++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml -@@ -27,38 +27,7 @@ properties: - - patternProperties: - "@[0-9a-f]+$": -- description: node describing a single flash partition -- type: object -- -- properties: -- reg: -- description: partition's offset and size within the flash -- maxItems: 1 -- -- label: -- description: The label / name for this partition. If omitted, the label -- is taken from the node name (excluding the unit address). -- -- read-only: -- description: This parameter, if present, is a hint that this partition -- should only be mounted read-only. This is usually used for flash -- partitions containing early-boot firmware images or data which should -- not be clobbered. -- type: boolean -- -- lock: -- description: Do not unlock the partition at initialization time (not -- supported on all devices) -- type: boolean -- -- slc-mode: -- description: This parameter, if present, allows one to emulate SLC mode -- on a partition attached to an MLC NAND thus making this partition -- immune to paired-pages corruptions -- type: boolean -- -- required: -- - reg -+ $ref: "partition.yaml#" - - required: - - "#address-cells" ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml -@@ -0,0 +1,47 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/partitions/partition.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Partition -+ -+description: | -+ This binding describes a single flash partition. Each partition must have its -+ relative offset and size specified. Depending on partition function extra -+ properties can be used. -+ -+maintainers: -+ - Rafał Miłecki -+ -+properties: -+ reg: -+ description: partition's offset and size within the flash -+ maxItems: 1 -+ -+ label: -+ description: The label / name for this partition. If omitted, the label -+ is taken from the node name (excluding the unit address). -+ -+ read-only: -+ description: This parameter, if present, is a hint that this partition -+ should only be mounted read-only. This is usually used for flash -+ partitions containing early-boot firmware images or data which should -+ not be clobbered. -+ type: boolean -+ -+ lock: -+ description: Do not unlock the partition at initialization time (not -+ supported on all devices) -+ type: boolean -+ -+ slc-mode: -+ description: This parameter, if present, allows one to emulate SLC mode -+ on a partition attached to an MLC NAND thus making this partition -+ immune to paired-pages corruptions -+ type: boolean -+ -+required: -+ - reg -+ -+additionalProperties: true diff --git a/target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch b/target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch deleted file mode 100644 index 8576c7d78d..0000000000 --- a/target/linux/generic/backport-5.15/402-v5.12-0002-dt-bindings-mtd-add-binding-for-BCM4908-partitions.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 6e9dff6fe3fbc452f16566e4a7e293b0decefdba Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 11 Feb 2021 23:04:26 +0100 -Subject: [PATCH] dt-bindings: mtd: add binding for BCM4908 partitions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM4908 uses fixed partitions layout but function of some partitions may -vary. Some devices use multiple firmware partitions and those partitions -should be marked to let system discover their purpose. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Richard Weinberger ---- - .../partitions/brcm,bcm4908-partitions.yaml | 70 +++++++++++++++++++ - 1 file changed, 70 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml -@@ -0,0 +1,70 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/partitions/brcm,bcm4908-partitions.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Broadcom BCM4908 partitioning -+ -+description: | -+ Broadcom BCM4908 CFE bootloader supports two firmware partitions. One is used -+ for regular booting, the other is treated as fallback. -+ -+ This binding allows defining all fixed partitions and marking those containing -+ firmware. System can use that information e.g. for booting or flashing -+ purposes. -+ -+maintainers: -+ - Rafał Miłecki -+ -+properties: -+ compatible: -+ const: brcm,bcm4908-partitions -+ -+ "#address-cells": -+ enum: [ 1, 2 ] -+ -+ "#size-cells": -+ enum: [ 1, 2 ] -+ -+patternProperties: -+ "^partition@[0-9a-f]+$": -+ $ref: "partition.yaml#" -+ properties: -+ compatible: -+ const: brcm,bcm4908-firmware -+ unevaluatedProperties: false -+ -+required: -+ - "#address-cells" -+ - "#size-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ partitions { -+ compatible = "brcm,bcm4908-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "cferom"; -+ reg = <0x0 0x100000>; -+ }; -+ -+ partition@100000 { -+ compatible = "brcm,bcm4908-firmware"; -+ reg = <0x100000 0xf00000>; -+ }; -+ -+ partition@1000000 { -+ compatible = "brcm,bcm4908-firmware"; -+ reg = <0x1000000 0xf00000>; -+ }; -+ -+ partition@1f00000 { -+ label = "calibration"; -+ reg = <0x1f00000 0x100000>; -+ }; -+ }; diff --git a/target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch b/target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch deleted file mode 100644 index d3891228e2..0000000000 --- a/target/linux/generic/backport-5.15/403-v5.13-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch +++ /dev/null @@ -1,654 +0,0 @@ -From afbef8efb591792579c633a7c545f914c6165f82 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 11 Feb 2021 23:04:27 +0100 -Subject: [PATCH] mtd: parsers: ofpart: support BCM4908 fixed partitions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some devices use fixed partitioning with some partitions requiring some -extra logic. E.g. BCM4908 may have multiple firmware partitions but -detecting currently used one requires checking bootloader parameters. - -To support such cases without duplicating a lot of code (without copying -most of the ofpart.c code) support for post-parsing callback was added. - -BCM4908 support in ofpart can be enabled using config option and results -in compiling & executing a specific callback. It simply reads offset of -currently used firmware partition from the DT. Bootloader specifies it -using the "brcm_blparms" property. - -Signed-off-by: Rafał Miłecki ---- - drivers/mtd/parsers/Kconfig | 9 +++ - drivers/mtd/parsers/Makefile | 2 + - drivers/mtd/parsers/ofpart_bcm4908.c | 64 +++++++++++++++++++ - drivers/mtd/parsers/ofpart_bcm4908.h | 15 +++++ - .../mtd/parsers/{ofpart.c => ofpart_core.c} | 28 +++++++- - 5 files changed, 116 insertions(+), 2 deletions(-) - create mode 100644 drivers/mtd/parsers/ofpart_bcm4908.c - create mode 100644 drivers/mtd/parsers/ofpart_bcm4908.h - rename drivers/mtd/parsers/{ofpart.c => ofpart_core.c} (88%) - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -67,6 +67,15 @@ config MTD_OF_PARTS - flash memory node, as described in - Documentation/devicetree/bindings/mtd/partition.txt. - -+config MTD_OF_PARTS_BCM4908 -+ bool "BCM4908 partitioning support" -+ depends on MTD_OF_PARTS && (ARCH_BCM4908 || COMPILE_TEST) -+ default ARCH_BCM4908 -+ help -+ This provides partitions parser for BCM4908 family devices -+ that can have multiple "firmware" partitions. It takes care of -+ finding currently used one and backup ones. -+ - config MTD_PARSER_IMAGETAG - tristate "Parser for BCM963XX Image Tag format partitions" - depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -4,6 +4,8 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4 - obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o - obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o - obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o -+ofpart-y += ofpart_core.o -+ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o - obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o ---- /dev/null -+++ b/drivers/mtd/parsers/ofpart_bcm4908.c -@@ -0,0 +1,64 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2021 Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ofpart_bcm4908.h" -+ -+#define BLPARAMS_FW_OFFSET "NAND_RFS_OFS" -+ -+static long long bcm4908_partitions_fw_offset(void) -+{ -+ struct device_node *root; -+ struct property *prop; -+ const char *s; -+ -+ root = of_find_node_by_path("/"); -+ if (!root) -+ return -ENOENT; -+ -+ of_property_for_each_string(root, "brcm_blparms", prop, s) { -+ size_t len = strlen(BLPARAMS_FW_OFFSET); -+ unsigned long offset; -+ int err; -+ -+ if (strncmp(s, BLPARAMS_FW_OFFSET, len) || s[len] != '=') -+ continue; -+ -+ err = kstrtoul(s + len + 1, 0, &offset); -+ if (err) { -+ pr_err("failed to parse %s\n", s + len + 1); -+ return err; -+ } -+ -+ return offset << 10; -+ } -+ -+ return -ENOENT; -+} -+ -+int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts) -+{ -+ long long fw_offset; -+ int i; -+ -+ fw_offset = bcm4908_partitions_fw_offset(); -+ -+ for (i = 0; i < nr_parts; i++) { -+ if (of_device_is_compatible(parts[i].of_node, "brcm,bcm4908-firmware")) { -+ if (fw_offset < 0 || parts[i].offset == fw_offset) -+ parts[i].name = "firmware"; -+ else -+ parts[i].name = "backup"; -+ } -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/mtd/parsers/ofpart_bcm4908.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __BCM4908_PARTITIONS_H -+#define __BCM4908_PARTITIONS_H -+ -+#ifdef CONFIG_MTD_OF_PARTS_BCM4908 -+int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); -+#else -+static inline int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, -+ int nr_parts) -+{ -+ return -EOPNOTSUPP; -+} -+#endif -+ -+#endif ---- a/drivers/mtd/parsers/ofpart.c -+++ /dev/null -@@ -1,239 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0-or-later --/* -- * Flash partitions described by the OF (or flattened) device tree -- * -- * Copyright © 2006 MontaVista Software Inc. -- * Author: Vitaly Wool -- * -- * Revised to handle newer style flash binding by: -- * Copyright © 2007 David Gibson, IBM Corporation. -- */ -- --#include --#include --#include --#include --#include --#include -- --static bool node_has_compatible(struct device_node *pp) --{ -- return of_get_property(pp, "compatible", NULL); --} -- --static int parse_fixed_partitions(struct mtd_info *master, -- const struct mtd_partition **pparts, -- struct mtd_part_parser_data *data) --{ -- struct mtd_partition *parts; -- struct device_node *mtd_node; -- struct device_node *ofpart_node; -- const char *partname; -- struct device_node *pp; -- int nr_parts, i, ret = 0; -- bool dedicated = true; -- -- -- /* Pull of_node from the master device node */ -- mtd_node = mtd_get_of_node(master); -- if (!mtd_node) -- return 0; -- -- ofpart_node = of_get_child_by_name(mtd_node, "partitions"); -- if (!ofpart_node) { -- /* -- * We might get here even when ofpart isn't used at all (e.g., -- * when using another parser), so don't be louder than -- * KERN_DEBUG -- */ -- pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", -- master->name, mtd_node); -- ofpart_node = mtd_node; -- dedicated = false; -- } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) { -- /* The 'partitions' subnode might be used by another parser */ -- return 0; -- } -- -- /* First count the subnodes */ -- nr_parts = 0; -- for_each_child_of_node(ofpart_node, pp) { -- if (!dedicated && node_has_compatible(pp)) -- continue; -- -- nr_parts++; -- } -- -- if (nr_parts == 0) -- return 0; -- -- parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); -- if (!parts) -- return -ENOMEM; -- -- i = 0; -- for_each_child_of_node(ofpart_node, pp) { -- const __be32 *reg; -- int len; -- int a_cells, s_cells; -- -- if (!dedicated && node_has_compatible(pp)) -- continue; -- -- reg = of_get_property(pp, "reg", &len); -- if (!reg) { -- if (dedicated) { -- pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n", -- master->name, pp, -- mtd_node); -- goto ofpart_fail; -- } else { -- nr_parts--; -- continue; -- } -- } -- -- a_cells = of_n_addr_cells(pp); -- s_cells = of_n_size_cells(pp); -- if (len / 4 != a_cells + s_cells) { -- pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n", -- master->name, pp, -- mtd_node); -- goto ofpart_fail; -- } -- -- parts[i].offset = of_read_number(reg, a_cells); -- parts[i].size = of_read_number(reg + a_cells, s_cells); -- parts[i].of_node = pp; -- -- partname = of_get_property(pp, "label", &len); -- if (!partname) -- partname = of_get_property(pp, "name", &len); -- parts[i].name = partname; -- -- if (of_get_property(pp, "read-only", &len)) -- parts[i].mask_flags |= MTD_WRITEABLE; -- -- if (of_get_property(pp, "lock", &len)) -- parts[i].mask_flags |= MTD_POWERUP_LOCK; -- -- if (of_property_read_bool(pp, "slc-mode")) -- parts[i].add_flags |= MTD_SLC_ON_MLC_EMULATION; -- -- i++; -- } -- -- if (!nr_parts) -- goto ofpart_none; -- -- *pparts = parts; -- return nr_parts; -- --ofpart_fail: -- pr_err("%s: error parsing ofpart partition %pOF (%pOF)\n", -- master->name, pp, mtd_node); -- ret = -EINVAL; --ofpart_none: -- of_node_put(pp); -- kfree(parts); -- return ret; --} -- --static const struct of_device_id parse_ofpart_match_table[] = { -- { .compatible = "fixed-partitions" }, -- {}, --}; --MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); -- --static struct mtd_part_parser ofpart_parser = { -- .parse_fn = parse_fixed_partitions, -- .name = "fixed-partitions", -- .of_match_table = parse_ofpart_match_table, --}; -- --static int parse_ofoldpart_partitions(struct mtd_info *master, -- const struct mtd_partition **pparts, -- struct mtd_part_parser_data *data) --{ -- struct mtd_partition *parts; -- struct device_node *dp; -- int i, plen, nr_parts; -- const struct { -- __be32 offset, len; -- } *part; -- const char *names; -- -- /* Pull of_node from the master device node */ -- dp = mtd_get_of_node(master); -- if (!dp) -- return 0; -- -- part = of_get_property(dp, "partitions", &plen); -- if (!part) -- return 0; /* No partitions found */ -- -- pr_warn("Device tree uses obsolete partition map binding: %pOF\n", dp); -- -- nr_parts = plen / sizeof(part[0]); -- -- parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); -- if (!parts) -- return -ENOMEM; -- -- names = of_get_property(dp, "partition-names", &plen); -- -- for (i = 0; i < nr_parts; i++) { -- parts[i].offset = be32_to_cpu(part->offset); -- parts[i].size = be32_to_cpu(part->len) & ~1; -- /* bit 0 set signifies read only partition */ -- if (be32_to_cpu(part->len) & 1) -- parts[i].mask_flags = MTD_WRITEABLE; -- -- if (names && (plen > 0)) { -- int len = strlen(names) + 1; -- -- parts[i].name = names; -- plen -= len; -- names += len; -- } else { -- parts[i].name = "unnamed"; -- } -- -- part++; -- } -- -- *pparts = parts; -- return nr_parts; --} -- --static struct mtd_part_parser ofoldpart_parser = { -- .parse_fn = parse_ofoldpart_partitions, -- .name = "ofoldpart", --}; -- --static int __init ofpart_parser_init(void) --{ -- register_mtd_parser(&ofpart_parser); -- register_mtd_parser(&ofoldpart_parser); -- return 0; --} -- --static void __exit ofpart_parser_exit(void) --{ -- deregister_mtd_parser(&ofpart_parser); -- deregister_mtd_parser(&ofoldpart_parser); --} -- --module_init(ofpart_parser_init); --module_exit(ofpart_parser_exit); -- --MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree"); --MODULE_AUTHOR("Vitaly Wool, David Gibson"); --/* -- * When MTD core cannot find the requested parser, it tries to load the module -- * with the same name. Since we provide the ofoldpart parser, we should have -- * the corresponding alias. -- */ --MODULE_ALIAS("fixed-partitions"); --MODULE_ALIAS("ofoldpart"); ---- /dev/null -+++ b/drivers/mtd/parsers/ofpart_core.c -@@ -0,0 +1,263 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Flash partitions described by the OF (or flattened) device tree -+ * -+ * Copyright © 2006 MontaVista Software Inc. -+ * Author: Vitaly Wool -+ * -+ * Revised to handle newer style flash binding by: -+ * Copyright © 2007 David Gibson, IBM Corporation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ofpart_bcm4908.h" -+ -+struct fixed_partitions_quirks { -+ int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); -+}; -+ -+struct fixed_partitions_quirks bcm4908_partitions_quirks = { -+ .post_parse = bcm4908_partitions_post_parse, -+}; -+ -+static const struct of_device_id parse_ofpart_match_table[]; -+ -+static bool node_has_compatible(struct device_node *pp) -+{ -+ return of_get_property(pp, "compatible", NULL); -+} -+ -+static int parse_fixed_partitions(struct mtd_info *master, -+ const struct mtd_partition **pparts, -+ struct mtd_part_parser_data *data) -+{ -+ const struct fixed_partitions_quirks *quirks; -+ const struct of_device_id *of_id; -+ struct mtd_partition *parts; -+ struct device_node *mtd_node; -+ struct device_node *ofpart_node; -+ const char *partname; -+ struct device_node *pp; -+ int nr_parts, i, ret = 0; -+ bool dedicated = true; -+ -+ /* Pull of_node from the master device node */ -+ mtd_node = mtd_get_of_node(master); -+ if (!mtd_node) -+ return 0; -+ -+ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); -+ if (!ofpart_node) { -+ /* -+ * We might get here even when ofpart isn't used at all (e.g., -+ * when using another parser), so don't be louder than -+ * KERN_DEBUG -+ */ -+ pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", -+ master->name, mtd_node); -+ ofpart_node = mtd_node; -+ dedicated = false; -+ } -+ -+ of_id = of_match_node(parse_ofpart_match_table, ofpart_node); -+ if (dedicated && !of_id) { -+ /* The 'partitions' subnode might be used by another parser */ -+ return 0; -+ } -+ -+ quirks = of_id ? of_id->data : NULL; -+ -+ /* First count the subnodes */ -+ nr_parts = 0; -+ for_each_child_of_node(ofpart_node, pp) { -+ if (!dedicated && node_has_compatible(pp)) -+ continue; -+ -+ nr_parts++; -+ } -+ -+ if (nr_parts == 0) -+ return 0; -+ -+ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); -+ if (!parts) -+ return -ENOMEM; -+ -+ i = 0; -+ for_each_child_of_node(ofpart_node, pp) { -+ const __be32 *reg; -+ int len; -+ int a_cells, s_cells; -+ -+ if (!dedicated && node_has_compatible(pp)) -+ continue; -+ -+ reg = of_get_property(pp, "reg", &len); -+ if (!reg) { -+ if (dedicated) { -+ pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n", -+ master->name, pp, -+ mtd_node); -+ goto ofpart_fail; -+ } else { -+ nr_parts--; -+ continue; -+ } -+ } -+ -+ a_cells = of_n_addr_cells(pp); -+ s_cells = of_n_size_cells(pp); -+ if (len / 4 != a_cells + s_cells) { -+ pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n", -+ master->name, pp, -+ mtd_node); -+ goto ofpart_fail; -+ } -+ -+ parts[i].offset = of_read_number(reg, a_cells); -+ parts[i].size = of_read_number(reg + a_cells, s_cells); -+ parts[i].of_node = pp; -+ -+ partname = of_get_property(pp, "label", &len); -+ if (!partname) -+ partname = of_get_property(pp, "name", &len); -+ parts[i].name = partname; -+ -+ if (of_get_property(pp, "read-only", &len)) -+ parts[i].mask_flags |= MTD_WRITEABLE; -+ -+ if (of_get_property(pp, "lock", &len)) -+ parts[i].mask_flags |= MTD_POWERUP_LOCK; -+ -+ if (of_property_read_bool(pp, "slc-mode")) -+ parts[i].add_flags |= MTD_SLC_ON_MLC_EMULATION; -+ -+ i++; -+ } -+ -+ if (!nr_parts) -+ goto ofpart_none; -+ -+ if (quirks && quirks->post_parse) -+ quirks->post_parse(master, parts, nr_parts); -+ -+ *pparts = parts; -+ return nr_parts; -+ -+ofpart_fail: -+ pr_err("%s: error parsing ofpart partition %pOF (%pOF)\n", -+ master->name, pp, mtd_node); -+ ret = -EINVAL; -+ofpart_none: -+ of_node_put(pp); -+ kfree(parts); -+ return ret; -+} -+ -+static const struct of_device_id parse_ofpart_match_table[] = { -+ /* Generic */ -+ { .compatible = "fixed-partitions" }, -+ /* Customized */ -+ { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); -+ -+static struct mtd_part_parser ofpart_parser = { -+ .parse_fn = parse_fixed_partitions, -+ .name = "fixed-partitions", -+ .of_match_table = parse_ofpart_match_table, -+}; -+ -+static int parse_ofoldpart_partitions(struct mtd_info *master, -+ const struct mtd_partition **pparts, -+ struct mtd_part_parser_data *data) -+{ -+ struct mtd_partition *parts; -+ struct device_node *dp; -+ int i, plen, nr_parts; -+ const struct { -+ __be32 offset, len; -+ } *part; -+ const char *names; -+ -+ /* Pull of_node from the master device node */ -+ dp = mtd_get_of_node(master); -+ if (!dp) -+ return 0; -+ -+ part = of_get_property(dp, "partitions", &plen); -+ if (!part) -+ return 0; /* No partitions found */ -+ -+ pr_warn("Device tree uses obsolete partition map binding: %pOF\n", dp); -+ -+ nr_parts = plen / sizeof(part[0]); -+ -+ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); -+ if (!parts) -+ return -ENOMEM; -+ -+ names = of_get_property(dp, "partition-names", &plen); -+ -+ for (i = 0; i < nr_parts; i++) { -+ parts[i].offset = be32_to_cpu(part->offset); -+ parts[i].size = be32_to_cpu(part->len) & ~1; -+ /* bit 0 set signifies read only partition */ -+ if (be32_to_cpu(part->len) & 1) -+ parts[i].mask_flags = MTD_WRITEABLE; -+ -+ if (names && (plen > 0)) { -+ int len = strlen(names) + 1; -+ -+ parts[i].name = names; -+ plen -= len; -+ names += len; -+ } else { -+ parts[i].name = "unnamed"; -+ } -+ -+ part++; -+ } -+ -+ *pparts = parts; -+ return nr_parts; -+} -+ -+static struct mtd_part_parser ofoldpart_parser = { -+ .parse_fn = parse_ofoldpart_partitions, -+ .name = "ofoldpart", -+}; -+ -+static int __init ofpart_parser_init(void) -+{ -+ register_mtd_parser(&ofpart_parser); -+ register_mtd_parser(&ofoldpart_parser); -+ return 0; -+} -+ -+static void __exit ofpart_parser_exit(void) -+{ -+ deregister_mtd_parser(&ofpart_parser); -+ deregister_mtd_parser(&ofoldpart_parser); -+} -+ -+module_init(ofpart_parser_init); -+module_exit(ofpart_parser_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree"); -+MODULE_AUTHOR("Vitaly Wool, David Gibson"); -+/* -+ * When MTD core cannot find the requested parser, it tries to load the module -+ * with the same name. Since we provide the ofoldpart parser, we should have -+ * the corresponding alias. -+ */ -+MODULE_ALIAS("fixed-partitions"); -+MODULE_ALIAS("ofoldpart"); diff --git a/target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch b/target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch deleted file mode 100644 index 55a91d7680..0000000000 --- a/target/linux/generic/backport-5.15/404-v5.13-mtd-parsers-ofpart-limit-parsing-of-deprecated-DT-sy.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 2d751203aacf86a1b301a188d8551c7da91043ab Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Tue, 2 Mar 2021 20:00:12 +0100 -Subject: [PATCH] mtd: parsers: ofpart: limit parsing of deprecated DT syntax -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For backward compatibility ofpart still supports the old syntax like: -spi-flash@0 { - compatible = "jedec,spi-nor"; - reg = <0x0>; - - partition@0 { - label = "bootloader"; - reg = <0x0 0x100000>; - }; -}; -(without "partitions" subnode). - -There is no reason however to support nested partitions without a clear -"compatible" string like: -partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "bootloader"; - reg = <0x0 0x100000>; - - partition@0 { - label = "config"; - reg = <0x80000 0x80000>; - }; - }; -}; -(we never officially supported or documented that). - -Make sure ofpart doesn't attempt to parse above. - -Cc: Ansuel Smith -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210302190012.1255-1-zajec5@gmail.com ---- - drivers/mtd/parsers/ofpart_core.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/parsers/ofpart_core.c -+++ b/drivers/mtd/parsers/ofpart_core.c -@@ -53,7 +53,7 @@ static int parse_fixed_partitions(struct - return 0; - - ofpart_node = of_get_child_by_name(mtd_node, "partitions"); -- if (!ofpart_node) { -+ if (!ofpart_node && !master->parent) { - /* - * We might get here even when ofpart isn't used at all (e.g., - * when using another parser), so don't be louder than -@@ -64,6 +64,8 @@ static int parse_fixed_partitions(struct - ofpart_node = mtd_node; - dedicated = false; - } -+ if (!ofpart_node) -+ return 0; - - of_id = of_match_node(parse_ofpart_match_table, ofpart_node); - if (dedicated && !of_id) { diff --git a/target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch b/target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch deleted file mode 100644 index f1b778a6e1..0000000000 --- a/target/linux/generic/backport-5.15/405-v5.13-mtd-parsers-ofpart-make-symbol-bcm4908_partitions_qu.patch +++ /dev/null @@ -1,34 +0,0 @@ -From b87b6d2d6f540e29c3f98e1572d64e560d73d6c1 Mon Sep 17 00:00:00 2001 -From: Wei Yongjun -Date: Thu, 4 Mar 2021 06:46:00 +0000 -Subject: [PATCH] mtd: parsers: ofpart: make symbol 'bcm4908_partitions_quirks' - static - -The sparse tool complains as follows: - -drivers/mtd/parsers/ofpart_core.c:25:32: warning: - symbol 'bcm4908_partitions_quirks' was not declared. Should it be static? - -This symbol is not used outside of ofpart_core.c, so this -commit marks it static. - -Fixes: 457da931b608 ("mtd: parsers: ofpart: support BCM4908 fixed partitions") -Reported-by: Hulk Robot -Signed-off-by: Wei Yongjun -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210304064600.3279138-1-weiyongjun1@huawei.com ---- - drivers/mtd/parsers/ofpart_core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/mtd/parsers/ofpart_core.c -+++ b/drivers/mtd/parsers/ofpart_core.c -@@ -22,7 +22,7 @@ struct fixed_partitions_quirks { - int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); - }; - --struct fixed_partitions_quirks bcm4908_partitions_quirks = { -+static struct fixed_partitions_quirks bcm4908_partitions_quirks = { - .post_parse = bcm4908_partitions_post_parse, - }; - diff --git a/target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch b/target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch deleted file mode 100644 index 28335cb71f..0000000000 --- a/target/linux/generic/backport-5.15/406-v5.13-0001-mtd-core-add-nvmem-cells-compatible-to-parse-mtd-as-.patch +++ /dev/null @@ -1,38 +0,0 @@ -From a5d83d6e2bc747b13f347962d4b335d70b23559b Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 12 Mar 2021 07:28:19 +0100 -Subject: [PATCH] mtd: core: add nvmem-cells compatible to parse mtd as nvmem - cells -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Partitions that contains the nvmem-cells compatible will register -their direct subonodes as nvmem cells and the node will be treated as a -nvmem provider. - -Signed-off-by: Ansuel Smith -Tested-by: Rafał Miłecki ---- - drivers/mtd/mtdcore.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -531,6 +531,7 @@ static int mtd_nvmem_reg_read(void *priv - - static int mtd_nvmem_add(struct mtd_info *mtd) - { -+ struct device_node *node = mtd_get_of_node(mtd); - struct nvmem_config config = {}; - - config.id = -1; -@@ -543,7 +544,7 @@ static int mtd_nvmem_add(struct mtd_info - config.stride = 1; - config.read_only = true; - config.root_only = true; -- config.no_of_node = true; -+ config.no_of_node = !of_device_is_compatible(node, "nvmem-cells"); - config.priv = mtd; - - mtd->nvmem = nvmem_register(&config); diff --git a/target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch b/target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch deleted file mode 100644 index 14ea3f6b8c..0000000000 --- a/target/linux/generic/backport-5.15/406-v5.13-0002-dt-bindings-nvmem-drop-nodename-restriction.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 42645976c3289b03a12f1bd2bc131fd98fc27170 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 12 Mar 2021 07:28:20 +0100 -Subject: [PATCH] devicetree: nvmem: nvmem: drop $nodename restriction - -Drop $nodename restriction as now mtd partition can also be used as -nvmem provider. - -Signed-off-by: Ansuel Smith ---- - Documentation/devicetree/bindings/nvmem/nvmem.yaml | 3 --- - 1 file changed, 3 deletions(-) - ---- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml -+++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml -@@ -20,9 +20,6 @@ description: | - storage device. - - properties: -- $nodename: -- pattern: "^(eeprom|efuse|nvram)(@.*|-[0-9a-f])*$" -- - "#address-cells": - const: 1 - diff --git a/target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch b/target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch deleted file mode 100644 index 0eb4c637cf..0000000000 --- a/target/linux/generic/backport-5.15/406-v5.13-0003-dt-bindings-mtd-Document-use-of-nvmem-cells-compatib.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 377aa0135dc8489312edd3184d143ce3a89ff7ee Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 12 Mar 2021 07:28:21 +0100 -Subject: [PATCH] dt-bindings: mtd: Document use of nvmem-cells compatible - -Document nvmem-cells compatible used to treat mtd partitions as a -nvmem provider. - -Signed-off-by: Ansuel Smith -Reviewed-by: Rob Herring ---- - .../bindings/mtd/partitions/nvmem-cells.yaml | 99 +++++++++++++++++++ - 1 file changed, 99 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml -@@ -0,0 +1,99 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/partitions/nvmem-cells.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Nvmem cells -+ -+description: | -+ Any partition containing the compatible "nvmem-cells" will register as a -+ nvmem provider. -+ Each direct subnodes represents a nvmem cell following the nvmem binding. -+ Nvmem binding to declare nvmem-cells can be found in: -+ Documentation/devicetree/bindings/nvmem/nvmem.yaml -+ -+maintainers: -+ - Ansuel Smith -+ -+allOf: -+ - $ref: /schemas/nvmem/nvmem.yaml# -+ -+properties: -+ compatible: -+ const: nvmem-cells -+ -+required: -+ - compatible -+ -+additionalProperties: true -+ -+examples: -+ - | -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ /* ... */ -+ -+ }; -+ art: art@1200000 { -+ compatible = "nvmem-cells"; -+ reg = <0x1200000 0x0140000>; -+ label = "art"; -+ read-only; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ macaddr_gmac1: macaddr_gmac1@0 { -+ reg = <0x0 0x6>; -+ }; -+ -+ macaddr_gmac2: macaddr_gmac2@6 { -+ reg = <0x6 0x6>; -+ }; -+ -+ pre_cal_24g: pre_cal_24g@1000 { -+ reg = <0x1000 0x2f20>; -+ }; -+ -+ pre_cal_5g: pre_cal_5g@5000{ -+ reg = <0x5000 0x2f20>; -+ }; -+ }; -+ - | -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bootloader"; -+ reg = <0x000000 0x100000>; -+ read-only; -+ }; -+ -+ firmware@100000 { -+ compatible = "brcm,trx"; -+ label = "firmware"; -+ reg = <0x100000 0xe00000>; -+ }; -+ -+ calibration@f00000 { -+ compatible = "nvmem-cells"; -+ label = "calibration"; -+ reg = <0xf00000 0x100000>; -+ ranges = <0 0xf00000 0x100000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ wifi0@0 { -+ reg = <0x000000 0x080000>; -+ }; -+ -+ wifi1@80000 { -+ reg = <0x080000 0x080000>; -+ }; -+ }; -+ }; diff --git a/target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch b/target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch deleted file mode 100644 index 35a4afd67b..0000000000 --- a/target/linux/generic/backport-5.15/407-v5.13-0001-dt-bindings-mtd-add-binding-for-Linksys-Northstar-pa.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 2fa7294175c76e1ec568aa75c1891fd908728c8d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 12 Mar 2021 14:49:18 +0100 -Subject: [PATCH] dt-bindings: mtd: add binding for Linksys Northstar - partitions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Linksys on Broadcom Northstar devices uses fixed flash layout with -multiple firmware partitions. - -Signed-off-by: Rafał Miłecki -Reviewed-by: Rob Herring -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210312134919.7767-1-zajec5@gmail.com ---- - .../mtd/partitions/linksys,ns-partitions.yaml | 74 +++++++++++++++++++ - 1 file changed, 74 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml -@@ -0,0 +1,74 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mtd/partitions/linksys,ns-partitions.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Linksys Northstar partitioning -+ -+description: | -+ Linksys devices based on Broadcom Northstar architecture often use two -+ firmware partitions. One is used for regular booting, the other is treated as -+ fallback. -+ -+ This binding allows defining all fixed partitions and marking those containing -+ firmware. System can use that information e.g. for booting or flashing -+ purposes. -+ -+maintainers: -+ - Rafał Miłecki -+ -+properties: -+ compatible: -+ const: linksys,ns-partitions -+ -+ "#address-cells": -+ enum: [ 1, 2 ] -+ -+ "#size-cells": -+ enum: [ 1, 2 ] -+ -+patternProperties: -+ "^partition@[0-9a-f]+$": -+ $ref: "partition.yaml#" -+ properties: -+ compatible: -+ items: -+ - const: linksys,ns-firmware -+ - const: brcm,trx -+ unevaluatedProperties: false -+ -+required: -+ - "#address-cells" -+ - "#size-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ partitions { -+ compatible = "linksys,ns-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "boot"; -+ reg = <0x0 0x100000>; -+ read-only; -+ }; -+ -+ partition@100000 { -+ label = "nvram"; -+ reg = <0x100000 0x100000>; -+ }; -+ -+ partition@200000 { -+ compatible = "linksys,ns-firmware", "brcm,trx"; -+ reg = <0x200000 0xf00000>; -+ }; -+ -+ partition@1100000 { -+ compatible = "linksys,ns-firmware", "brcm,trx"; -+ reg = <0x1100000 0xf00000>; -+ }; -+ }; diff --git a/target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch b/target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch deleted file mode 100644 index f317889785..0000000000 --- a/target/linux/generic/backport-5.15/407-v5.13-0002-mtd-parsers-ofpart-support-Linksys-Northstar-partiti.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 7134a2d026d942210b4d26d6059c9d979ca7866e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 12 Mar 2021 14:49:19 +0100 -Subject: [PATCH] mtd: parsers: ofpart: support Linksys Northstar partitions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This allows extending ofpart parser with support for Linksys Northstar -devices. That support uses recently added quirks mechanism. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210312134919.7767-2-zajec5@gmail.com ---- - drivers/mtd/parsers/Kconfig | 10 +++++ - drivers/mtd/parsers/Makefile | 1 + - drivers/mtd/parsers/ofpart_core.c | 6 +++ - drivers/mtd/parsers/ofpart_linksys_ns.c | 50 +++++++++++++++++++++++++ - drivers/mtd/parsers/ofpart_linksys_ns.h | 18 +++++++++ - 5 files changed, 85 insertions(+) - create mode 100644 drivers/mtd/parsers/ofpart_linksys_ns.c - create mode 100644 drivers/mtd/parsers/ofpart_linksys_ns.h - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -76,6 +76,16 @@ config MTD_OF_PARTS_BCM4908 - that can have multiple "firmware" partitions. It takes care of - finding currently used one and backup ones. - -+config MTD_OF_PARTS_LINKSYS_NS -+ bool "Linksys Northstar partitioning support" -+ depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST) -+ default ARCH_BCM_5301X -+ help -+ This provides partitions parser for Linksys devices based on Broadcom -+ Northstar architecture. Linksys commonly uses fixed flash layout with -+ two "firmware" partitions. Currently used firmware has to be detected -+ using CFE environment variable. -+ - config MTD_PARSER_IMAGETAG - tristate "Parser for BCM963XX Image Tag format partitions" - depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -6,6 +6,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdl - obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o - ofpart-y += ofpart_core.o - ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o -+ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o - obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o ---- a/drivers/mtd/parsers/ofpart_core.c -+++ b/drivers/mtd/parsers/ofpart_core.c -@@ -17,6 +17,7 @@ - #include - - #include "ofpart_bcm4908.h" -+#include "ofpart_linksys_ns.h" - - struct fixed_partitions_quirks { - int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); -@@ -26,6 +27,10 @@ static struct fixed_partitions_quirks bc - .post_parse = bcm4908_partitions_post_parse, - }; - -+static struct fixed_partitions_quirks linksys_ns_partitions_quirks = { -+ .post_parse = linksys_ns_partitions_post_parse, -+}; -+ - static const struct of_device_id parse_ofpart_match_table[]; - - static bool node_has_compatible(struct device_node *pp) -@@ -167,6 +172,7 @@ static const struct of_device_id parse_o - { .compatible = "fixed-partitions" }, - /* Customized */ - { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, }, -+ { .compatible = "linksys,ns-partitions", .data = &linksys_ns_partitions_quirks, }, - {}, - }; - MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); ---- /dev/null -+++ b/drivers/mtd/parsers/ofpart_linksys_ns.c -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2021 Rafał Miłecki -+ */ -+ -+#include -+#include -+#include -+ -+#include "ofpart_linksys_ns.h" -+ -+#define NVRAM_BOOT_PART "bootpartition" -+ -+static int ofpart_linksys_ns_bootpartition(void) -+{ -+ char buf[4]; -+ int bootpartition; -+ -+ /* Check CFE environment variable */ -+ if (bcm47xx_nvram_getenv(NVRAM_BOOT_PART, buf, sizeof(buf)) > 0) { -+ if (!kstrtoint(buf, 0, &bootpartition)) -+ return bootpartition; -+ pr_warn("Failed to parse %s value \"%s\"\n", NVRAM_BOOT_PART, -+ buf); -+ } else { -+ pr_warn("Failed to get NVRAM \"%s\"\n", NVRAM_BOOT_PART); -+ } -+ -+ return 0; -+} -+ -+int linksys_ns_partitions_post_parse(struct mtd_info *mtd, -+ struct mtd_partition *parts, -+ int nr_parts) -+{ -+ int bootpartition = ofpart_linksys_ns_bootpartition(); -+ int trx_idx = 0; -+ int i; -+ -+ for (i = 0; i < nr_parts; i++) { -+ if (of_device_is_compatible(parts[i].of_node, "linksys,ns-firmware")) { -+ if (trx_idx++ == bootpartition) -+ parts[i].name = "firmware"; -+ else -+ parts[i].name = "backup"; -+ } -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/mtd/parsers/ofpart_linksys_ns.h -@@ -0,0 +1,18 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __OFPART_LINKSYS_NS_H -+#define __OFPART_LINKSYS_NS_H -+ -+#ifdef CONFIG_MTD_OF_PARTS_LINKSYS_NS -+int linksys_ns_partitions_post_parse(struct mtd_info *mtd, -+ struct mtd_partition *parts, -+ int nr_parts); -+#else -+static inline int linksys_ns_partitions_post_parse(struct mtd_info *mtd, -+ struct mtd_partition *parts, -+ int nr_parts) -+{ -+ return -EOPNOTSUPP; -+} -+#endif -+ -+#endif diff --git a/target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch b/target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch deleted file mode 100644 index 3af641e62e..0000000000 --- a/target/linux/generic/backport-5.15/408-v5.13-mtd-cfi_cmdset_0002-Disable-buffered-writes-for-AMD.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 7e4404113686868858a34210c28ae122e967aa64 Mon Sep 17 00:00:00 2001 -From: Mauri Sandberg -Date: Tue, 9 Mar 2021 19:48:59 +0200 -Subject: [PATCH] mtd: cfi_cmdset_0002: Disable buffered writes for AMD chip - 0x2201 - -Buffer writes do not work with AMD chip 0x2201. The chip in question -is a AMD/Spansion/Cypress Semiconductor S29GL256N and datasheet [1] -talks about writing buffers being possible. While waiting for a neater -solution resort to writing word-sized chunks only. - -Without the patch kernel logs will be flooded with entries like below: - -jffs2_scan_eraseblock(): End of filesystem marker found at 0x0 -jffs2_build_filesystem(): unlocking the mtd device... -done. -jffs2_build_filesystem(): erasing all blocks after the end marker... -MTD do_write_buffer_wait(): software timeout, address:0x01ec000a. -jffs2: Write clean marker to block at 0x01920000 failed: -5 -MTD do_write_buffer_wait(): software timeout, address:0x01e2000a. -jffs2: Write clean marker to block at 0x01880000 failed: -5 -MTD do_write_buffer_wait(): software timeout, address:0x01e0000a. -jffs2: Write clean marker to block at 0x01860000 failed: -5 -MTD do_write_buffer_wait(): software timeout, address:0x01dc000a. -jffs2: Write clean marker to block at 0x01820000 failed: -5 -MTD do_write_buffer_wait(): software timeout, address:0x01da000a. -jffs2: Write clean marker to block at 0x01800000 failed: -5 -... - -Tested on a Buffalo wzr-hp-g300nh running kernel 5.10.16. - -[1] https://www.cypress.com/file/219941/download -or https://datasheetspdf.com/pdf-file/565708/SPANSION/S29GL256N/1 - -Signed-off-by: Mauri Sandberg -Signed-off-by: Vignesh Raghavendra -Link: https://lore.kernel.org/r/20210309174859.362060-1-sandberg@mailfence.com ---- - drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -272,6 +272,10 @@ static void fixup_use_write_buffers(stru - { - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; -+ -+ if (cfi->mfr == CFI_MFR_AMD && cfi->id == 0x2201) -+ return; -+ - if (cfi->cfiq->BufWriteTimeoutTyp) { - pr_debug("Using buffer write method\n"); - mtd->_write = cfi_amdstd_write_buffers; diff --git a/target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch b/target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch deleted file mode 100644 index 1f34652141..0000000000 --- a/target/linux/generic/backport-5.15/409-v5.14-0001-dt-bindings-mtd-brcm-trx-Add-brcm-trx-magic.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a4d82940ff85a7e307953dfa715f65d5ab487e10 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 18 Apr 2021 23:46:14 +0200 -Subject: dt-bindings: mtd: brcm,trx: Add brcm,trx-magic - -This adds the description of an additional property which allows to -specify a custom partition parser magic to detect a trx partition. -Buffalo has multiple device which are using the trx format, but with -different magic values. - -Signed-off-by: Hauke Mehrtens -Acked-by: Rob Herring -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-2-hauke@hauke-m.de ---- - .../devicetree/bindings/mtd/partitions/brcm,trx.txt | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt -+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt -@@ -28,6 +28,11 @@ detected by a software parsing TRX heade - Required properties: - - compatible : (required) must be "brcm,trx" - -+Optional properties: -+ -+- brcm,trx-magic: TRX magic, if it is different from the default magic -+ 0x30524448 as a u32. -+ - Example: - - flash@0 { diff --git a/target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch b/target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch deleted file mode 100644 index de2d914852..0000000000 --- a/target/linux/generic/backport-5.15/409-v5.14-0002-mtd-parsers-trx-Allow-to-specify-brcm-trx-magic-in-D.patch +++ /dev/null @@ -1,50 +0,0 @@ -From d7f7e04f8b67571a4bf5a0dcd4f9da4214f5262c Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 18 Apr 2021 23:46:15 +0200 -Subject: mtd: parsers: trx: Allow to specify brcm, trx-magic in DT - -Buffalo uses a different TRX magic for every device, to be able to use -this trx parser, make it possible to specify the TRX magic in device -tree. If no TRX magic is specified in device tree, the standard value -will be used. This value should only be specified if a vendor chooses to -use a non standard TRX magic. - -Signed-off-by: Hauke Mehrtens -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-3-hauke@hauke-m.de ---- - drivers/mtd/parsers/parser_trx.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/parsers/parser_trx.c -+++ b/drivers/mtd/parsers/parser_trx.c -@@ -51,13 +51,20 @@ static int parser_trx_parse(struct mtd_i - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) - { -+ struct device_node *np = mtd_get_of_node(mtd); - struct mtd_partition *parts; - struct mtd_partition *part; - struct trx_header trx; - size_t bytes_read; - uint8_t curr_part = 0, i = 0; -+ uint32_t trx_magic = TRX_MAGIC; - int err; - -+ /* Get different magic from device tree if specified */ -+ err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic); -+ if (err != 0 && err != -EINVAL) -+ pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err); -+ - parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), - GFP_KERNEL); - if (!parts) -@@ -70,7 +77,7 @@ static int parser_trx_parse(struct mtd_i - return err; - } - -- if (trx.magic != TRX_MAGIC) { -+ if (trx.magic != trx_magic) { - kfree(parts); - return -ENOENT; - } diff --git a/target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch b/target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch deleted file mode 100644 index faac535270..0000000000 --- a/target/linux/generic/backport-5.15/409-v5.14-0003-mtd-parsers-trx-Allow-to-use-TRX-parser-on-Mediatek-.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 81bb218c829246962a6327c64eec18ddcc049936 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 18 Apr 2021 23:46:16 +0200 -Subject: mtd: parsers: trx: Allow to use TRX parser on Mediatek SoCs - -Buffalo uses the TRX partition format also on Mediatek MT7622 SoCs. - -Signed-off-by: Hauke Mehrtens -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-4-hauke@hauke-m.de ---- - drivers/mtd/parsers/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -115,7 +115,7 @@ config MTD_AFS_PARTS - - config MTD_PARSER_TRX - tristate "Parser for TRX format partitions" -- depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) -+ depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST) - help - TRX is a firmware format used by Broadcom on their devices. It - may contain up to 3/4 partitions (depending on the version). diff --git a/target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch b/target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch deleted file mode 100644 index dd50c19c27..0000000000 --- a/target/linux/generic/backport-5.15/500-v5.13-ubifs-default-to-zstd-compression.patch +++ /dev/null @@ -1,25 +0,0 @@ -From dcdf415b740923530dc71d89fecc8361078473f5 Mon Sep 17 00:00:00 2001 -From: Rui Salvaterra -Date: Mon, 5 Apr 2021 16:11:55 +0100 -Subject: [PATCH] ubifs: default to zstd compression - -Compared to lzo and zlib, zstd is the best all-around performer, both in terms -of speed and compression ratio. Set it as the default, if available. - -Signed-off-by: Rui Salvaterra ---- - fs/ubifs/sb.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/fs/ubifs/sb.c -+++ b/fs/ubifs/sb.c -@@ -53,6 +53,9 @@ - - static int get_default_compressor(struct ubifs_info *c) - { -+ if (ubifs_compr_present(c, UBIFS_COMPR_ZSTD)) -+ return UBIFS_COMPR_ZSTD; -+ - if (ubifs_compr_present(c, UBIFS_COMPR_LZO)) - return UBIFS_COMPR_LZO; - diff --git a/target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch b/target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch deleted file mode 100644 index 1fca4a5e74..0000000000 --- a/target/linux/generic/backport-5.15/600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch +++ /dev/null @@ -1,88 +0,0 @@ -From: Felix Fietkau -Date: Mon, 8 Feb 2021 11:34:08 -0800 -Subject: [PATCH] net: extract napi poll functionality to __napi_poll() - -This commit introduces a new function __napi_poll() which does the main -logic of the existing napi_poll() function, and will be called by other -functions in later commits. -This idea and implementation is done by Felix Fietkau and -is proposed as part of the patch to move napi work to work_queue -context. -This commit by itself is a code restructure. - -Signed-off-by: Felix Fietkau -Signed-off-by: Wei Wang -Reviewed-by: Alexander Duyck -Signed-off-by: David S. Miller ---- - ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -6805,15 +6805,10 @@ void __netif_napi_del(struct napi_struct - } - EXPORT_SYMBOL(__netif_napi_del); - --static int napi_poll(struct napi_struct *n, struct list_head *repoll) -+static int __napi_poll(struct napi_struct *n, bool *repoll) - { -- void *have; - int work, weight; - -- list_del_init(&n->poll_list); -- -- have = netpoll_poll_lock(n); -- - weight = n->weight; - - /* This NAPI_STATE_SCHED test is for avoiding a race -@@ -6833,7 +6828,7 @@ static int napi_poll(struct napi_struct - n->poll, work, weight); - - if (likely(work < weight)) -- goto out_unlock; -+ return work; - - /* Drivers must not modify the NAPI state if they - * consume the entire weight. In such cases this code -@@ -6842,7 +6837,7 @@ static int napi_poll(struct napi_struct - */ - if (unlikely(napi_disable_pending(n))) { - napi_complete(n); -- goto out_unlock; -+ return work; - } - - if (n->gro_bitmask) { -@@ -6860,12 +6855,29 @@ static int napi_poll(struct napi_struct - if (unlikely(!list_empty(&n->poll_list))) { - pr_warn_once("%s: Budget exhausted after napi rescheduled\n", - n->dev ? n->dev->name : "backlog"); -- goto out_unlock; -+ return work; - } - -- list_add_tail(&n->poll_list, repoll); -+ *repoll = true; -+ -+ return work; -+} -+ -+static int napi_poll(struct napi_struct *n, struct list_head *repoll) -+{ -+ bool do_repoll = false; -+ void *have; -+ int work; -+ -+ list_del_init(&n->poll_list); -+ -+ have = netpoll_poll_lock(n); -+ -+ work = __napi_poll(n, &do_repoll); -+ -+ if (do_repoll) -+ list_add_tail(&n->poll_list, repoll); - --out_unlock: - netpoll_poll_unlock(have); - - return work; diff --git a/target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch b/target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch deleted file mode 100644 index 38e276ef72..0000000000 --- a/target/linux/generic/backport-5.15/601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch +++ /dev/null @@ -1,261 +0,0 @@ -From: Wei Wang -Date: Mon, 8 Feb 2021 11:34:09 -0800 -Subject: [PATCH] net: implement threaded-able napi poll loop support - -This patch allows running each napi poll loop inside its own -kernel thread. -The kthread is created during netif_napi_add() if dev->threaded -is set. And threaded mode is enabled in napi_enable(). We will -provide a way to set dev->threaded and enable threaded mode -without a device up/down in the following patch. - -Once that threaded mode is enabled and the kthread is -started, napi_schedule() will wake-up such thread instead -of scheduling the softirq. - -The threaded poll loop behaves quite likely the net_rx_action, -but it does not have to manipulate local irqs and uses -an explicit scheduling point based on netdev_budget. - -Co-developed-by: Paolo Abeni -Signed-off-by: Paolo Abeni -Co-developed-by: Hannes Frederic Sowa -Signed-off-by: Hannes Frederic Sowa -Co-developed-by: Jakub Kicinski -Signed-off-by: Jakub Kicinski -Signed-off-by: Wei Wang -Reviewed-by: Alexander Duyck -Signed-off-by: David S. Miller ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -347,6 +347,7 @@ struct napi_struct { - struct list_head dev_list; - struct hlist_node napi_hash_node; - unsigned int napi_id; -+ struct task_struct *thread; - }; - - enum { -@@ -357,6 +358,7 @@ enum { - NAPI_STATE_LISTED, /* NAPI added to system lists */ - NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ - NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ -+ NAPI_STATE_THREADED, /* The poll is performed inside its own thread*/ - }; - - enum { -@@ -367,6 +369,7 @@ enum { - NAPIF_STATE_LISTED = BIT(NAPI_STATE_LISTED), - NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), - NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), -+ NAPIF_STATE_THREADED = BIT(NAPI_STATE_THREADED), - }; - - enum gro_result { -@@ -497,20 +500,7 @@ static inline bool napi_complete(struct - */ - void napi_disable(struct napi_struct *n); - --/** -- * napi_enable - enable NAPI scheduling -- * @n: NAPI context -- * -- * Resume NAPI from being scheduled on this context. -- * Must be paired with napi_disable. -- */ --static inline void napi_enable(struct napi_struct *n) --{ -- BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); -- smp_mb__before_atomic(); -- clear_bit(NAPI_STATE_SCHED, &n->state); -- clear_bit(NAPI_STATE_NPSVC, &n->state); --} -+void napi_enable(struct napi_struct *n); - - /** - * napi_synchronize - wait until NAPI is not running -@@ -1842,6 +1832,8 @@ enum netdev_ml_priv_type { - * - * @wol_enabled: Wake-on-LAN is enabled - * -+ * @threaded: napi threaded mode is enabled -+ * - * @net_notifier_list: List of per-net netdev notifier block - * that follow this device when it is moved - * to another network namespace. -@@ -2161,6 +2153,7 @@ struct net_device { - struct lock_class_key *qdisc_running_key; - bool proto_down; - unsigned wol_enabled:1; -+ unsigned threaded:1; - - struct list_head net_notifier_list; - ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -91,6 +91,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1500,6 +1501,27 @@ void netdev_notify_peers(struct net_devi - } - EXPORT_SYMBOL(netdev_notify_peers); - -+static int napi_threaded_poll(void *data); -+ -+static int napi_kthread_create(struct napi_struct *n) -+{ -+ int err = 0; -+ -+ /* Create and wake up the kthread once to put it in -+ * TASK_INTERRUPTIBLE mode to avoid the blocked task -+ * warning and work with loadavg. -+ */ -+ n->thread = kthread_run(napi_threaded_poll, n, "napi/%s-%d", -+ n->dev->name, n->napi_id); -+ if (IS_ERR(n->thread)) { -+ err = PTR_ERR(n->thread); -+ pr_err("kthread_run failed with err %d\n", err); -+ n->thread = NULL; -+ } -+ -+ return err; -+} -+ - static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack) - { - const struct net_device_ops *ops = dev->netdev_ops; -@@ -4267,6 +4289,21 @@ int gro_normal_batch __read_mostly = 8; - static inline void ____napi_schedule(struct softnet_data *sd, - struct napi_struct *napi) - { -+ struct task_struct *thread; -+ -+ if (test_bit(NAPI_STATE_THREADED, &napi->state)) { -+ /* Paired with smp_mb__before_atomic() in -+ * napi_enable(). Use READ_ONCE() to guarantee -+ * a complete read on napi->thread. Only call -+ * wake_up_process() when it's not NULL. -+ */ -+ thread = READ_ONCE(napi->thread); -+ if (thread) { -+ wake_up_process(thread); -+ return; -+ } -+ } -+ - list_add_tail(&napi->poll_list, &sd->poll_list); - __raise_softirq_irqoff(NET_RX_SOFTIRQ); - } -@@ -6758,6 +6795,12 @@ void netif_napi_add(struct net_device *d - set_bit(NAPI_STATE_NPSVC, &napi->state); - list_add_rcu(&napi->dev_list, &dev->napi_list); - napi_hash_add(napi); -+ /* Create kthread for this napi if dev->threaded is set. -+ * Clear dev->threaded if kthread creation failed so that -+ * threaded mode will not be enabled in napi_enable(). -+ */ -+ if (dev->threaded && napi_kthread_create(napi)) -+ dev->threaded = 0; - } - EXPORT_SYMBOL(netif_napi_add); - -@@ -6774,9 +6817,28 @@ void napi_disable(struct napi_struct *n) - hrtimer_cancel(&n->timer); - - clear_bit(NAPI_STATE_DISABLE, &n->state); -+ clear_bit(NAPI_STATE_THREADED, &n->state); - } - EXPORT_SYMBOL(napi_disable); - -+/** -+ * napi_enable - enable NAPI scheduling -+ * @n: NAPI context -+ * -+ * Resume NAPI from being scheduled on this context. -+ * Must be paired with napi_disable. -+ */ -+void napi_enable(struct napi_struct *n) -+{ -+ BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); -+ smp_mb__before_atomic(); -+ clear_bit(NAPI_STATE_SCHED, &n->state); -+ clear_bit(NAPI_STATE_NPSVC, &n->state); -+ if (n->dev->threaded && n->thread) -+ set_bit(NAPI_STATE_THREADED, &n->state); -+} -+EXPORT_SYMBOL(napi_enable); -+ - static void flush_gro_hash(struct napi_struct *napi) - { - int i; -@@ -6802,6 +6864,11 @@ void __netif_napi_del(struct napi_struct - - flush_gro_hash(napi); - napi->gro_bitmask = 0; -+ -+ if (napi->thread) { -+ kthread_stop(napi->thread); -+ napi->thread = NULL; -+ } - } - EXPORT_SYMBOL(__netif_napi_del); - -@@ -6883,6 +6950,51 @@ static int napi_poll(struct napi_struct - return work; - } - -+static int napi_thread_wait(struct napi_struct *napi) -+{ -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ while (!kthread_should_stop() && !napi_disable_pending(napi)) { -+ if (test_bit(NAPI_STATE_SCHED, &napi->state)) { -+ WARN_ON(!list_empty(&napi->poll_list)); -+ __set_current_state(TASK_RUNNING); -+ return 0; -+ } -+ -+ schedule(); -+ set_current_state(TASK_INTERRUPTIBLE); -+ } -+ __set_current_state(TASK_RUNNING); -+ return -1; -+} -+ -+static int napi_threaded_poll(void *data) -+{ -+ struct napi_struct *napi = data; -+ void *have; -+ -+ while (!napi_thread_wait(napi)) { -+ for (;;) { -+ bool repoll = false; -+ -+ local_bh_disable(); -+ -+ have = netpoll_poll_lock(napi); -+ __napi_poll(napi, &repoll); -+ netpoll_poll_unlock(have); -+ -+ __kfree_skb_flush(); -+ local_bh_enable(); -+ -+ if (!repoll) -+ break; -+ -+ cond_resched(); -+ } -+ } -+ return 0; -+} -+ - static __latent_entropy void net_rx_action(struct softirq_action *h) - { - struct softnet_data *sd = this_cpu_ptr(&softnet_data); diff --git a/target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch b/target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch deleted file mode 100644 index c3119a6e9b..0000000000 --- a/target/linux/generic/backport-5.15/602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch +++ /dev/null @@ -1,177 +0,0 @@ -From: Wei Wang -Date: Mon, 8 Feb 2021 11:34:10 -0800 -Subject: [PATCH] net: add sysfs attribute to control napi threaded mode - -This patch adds a new sysfs attribute to the network device class. -Said attribute provides a per-device control to enable/disable the -threaded mode for all the napi instances of the given network device, -without the need for a device up/down. -User sets it to 1 or 0 to enable or disable threaded mode. -Note: when switching between threaded and the current softirq based mode -for a napi instance, it will not immediately take effect if the napi is -currently being polled. The mode switch will happen for the next time -napi_schedule() is called. - -Co-developed-by: Paolo Abeni -Signed-off-by: Paolo Abeni -Co-developed-by: Hannes Frederic Sowa -Signed-off-by: Hannes Frederic Sowa -Co-developed-by: Felix Fietkau -Signed-off-by: Felix Fietkau -Signed-off-by: Wei Wang -Reviewed-by: Alexander Duyck -Signed-off-by: David S. Miller ---- - ---- a/Documentation/ABI/testing/sysfs-class-net -+++ b/Documentation/ABI/testing/sysfs-class-net -@@ -337,3 +337,18 @@ Contact: netdev@vger.kernel.org - Description: - 32-bit unsigned integer counting the number of times the link has - been down -+ -+What: /sys/class/net//threaded -+Date: Jan 2021 -+KernelVersion: 5.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Boolean value to control the threaded mode per device. User could -+ set this value to enable/disable threaded mode for all napi -+ belonging to this device, without the need to do device up/down. -+ -+ Possible values: -+ == ================================== -+ 0 threaded mode disabled for this dev -+ 1 threaded mode enabled for this dev -+ == ================================== ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -491,6 +491,8 @@ static inline bool napi_complete(struct - return napi_complete_done(n, 0); - } - -+int dev_set_threaded(struct net_device *dev, bool threaded); -+ - /** - * napi_disable - prevent NAPI from scheduling - * @n: NAPI context ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -4293,8 +4293,9 @@ static inline void ____napi_schedule(str - - if (test_bit(NAPI_STATE_THREADED, &napi->state)) { - /* Paired with smp_mb__before_atomic() in -- * napi_enable(). Use READ_ONCE() to guarantee -- * a complete read on napi->thread. Only call -+ * napi_enable()/dev_set_threaded(). -+ * Use READ_ONCE() to guarantee a complete -+ * read on napi->thread. Only call - * wake_up_process() when it's not NULL. - */ - thread = READ_ONCE(napi->thread); -@@ -6768,6 +6769,49 @@ static void init_gro_hash(struct napi_st - napi->gro_bitmask = 0; - } - -+int dev_set_threaded(struct net_device *dev, bool threaded) -+{ -+ struct napi_struct *napi; -+ int err = 0; -+ -+ if (dev->threaded == threaded) -+ return 0; -+ -+ if (threaded) { -+ list_for_each_entry(napi, &dev->napi_list, dev_list) { -+ if (!napi->thread) { -+ err = napi_kthread_create(napi); -+ if (err) { -+ threaded = false; -+ break; -+ } -+ } -+ } -+ } -+ -+ dev->threaded = threaded; -+ -+ /* Make sure kthread is created before THREADED bit -+ * is set. -+ */ -+ smp_mb__before_atomic(); -+ -+ /* Setting/unsetting threaded mode on a napi might not immediately -+ * take effect, if the current napi instance is actively being -+ * polled. In this case, the switch between threaded mode and -+ * softirq mode will happen in the next round of napi_schedule(). -+ * This should not cause hiccups/stalls to the live traffic. -+ */ -+ list_for_each_entry(napi, &dev->napi_list, dev_list) { -+ if (threaded) -+ set_bit(NAPI_STATE_THREADED, &napi->state); -+ else -+ clear_bit(NAPI_STATE_THREADED, &napi->state); -+ } -+ -+ return err; -+} -+ - void netif_napi_add(struct net_device *dev, struct napi_struct *napi, - int (*poll)(struct napi_struct *, int), int weight) - { ---- a/net/core/net-sysfs.c -+++ b/net/core/net-sysfs.c -@@ -587,6 +587,45 @@ static ssize_t phys_switch_id_show(struc - } - static DEVICE_ATTR_RO(phys_switch_id); - -+static ssize_t threaded_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct net_device *netdev = to_net_dev(dev); -+ ssize_t ret = -EINVAL; -+ -+ if (!rtnl_trylock()) -+ return restart_syscall(); -+ -+ if (dev_isalive(netdev)) -+ ret = sprintf(buf, fmt_dec, netdev->threaded); -+ -+ rtnl_unlock(); -+ return ret; -+} -+ -+static int modify_napi_threaded(struct net_device *dev, unsigned long val) -+{ -+ int ret; -+ -+ if (list_empty(&dev->napi_list)) -+ return -EOPNOTSUPP; -+ -+ if (val != 0 && val != 1) -+ return -EOPNOTSUPP; -+ -+ ret = dev_set_threaded(dev, val); -+ -+ return ret; -+} -+ -+static ssize_t threaded_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ return netdev_store(dev, attr, buf, len, modify_napi_threaded); -+} -+static DEVICE_ATTR_RW(threaded); -+ - static struct attribute *net_class_attrs[] __ro_after_init = { - &dev_attr_netdev_group.attr, - &dev_attr_type.attr, -@@ -619,6 +658,7 @@ static struct attribute *net_class_attrs - &dev_attr_proto_down.attr, - &dev_attr_carrier_up_count.attr, - &dev_attr_carrier_down_count.attr, -+ &dev_attr_threaded.attr, - NULL, - }; - ATTRIBUTE_GROUPS(net_class); diff --git a/target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch b/target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch deleted file mode 100644 index febef3e28a..0000000000 --- a/target/linux/generic/backport-5.15/603-v5.12-net-fix-race-between-napi-kthread-mode-and-busy-poll.patch +++ /dev/null @@ -1,93 +0,0 @@ -From: Wei Wang -Date: Mon, 1 Mar 2021 17:21:13 -0800 -Subject: [PATCH] net: fix race between napi kthread mode and busy poll - -Currently, napi_thread_wait() checks for NAPI_STATE_SCHED bit to -determine if the kthread owns this napi and could call napi->poll() on -it. However, if socket busy poll is enabled, it is possible that the -busy poll thread grabs this SCHED bit (after the previous napi->poll() -invokes napi_complete_done() and clears SCHED bit) and tries to poll -on the same napi. napi_disable() could grab the SCHED bit as well. -This patch tries to fix this race by adding a new bit -NAPI_STATE_SCHED_THREADED in napi->state. This bit gets set in -____napi_schedule() if the threaded mode is enabled, and gets cleared -in napi_complete_done(), and we only poll the napi in kthread if this -bit is set. This helps distinguish the ownership of the napi between -kthread and other scenarios and fixes the race issue. - -Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") -Reported-by: Martin Zaharinov -Suggested-by: Jakub Kicinski -Signed-off-by: Wei Wang -Cc: Alexander Duyck -Cc: Eric Dumazet -Cc: Paolo Abeni -Cc: Hannes Frederic Sowa ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -359,6 +359,7 @@ enum { - NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ - NAPI_STATE_IN_BUSY_POLL,/* sk_busy_loop() owns this NAPI */ - NAPI_STATE_THREADED, /* The poll is performed inside its own thread*/ -+ NAPI_STATE_SCHED_THREADED, /* Napi is currently scheduled in threaded mode */ - }; - - enum { -@@ -370,6 +371,7 @@ enum { - NAPIF_STATE_NO_BUSY_POLL = BIT(NAPI_STATE_NO_BUSY_POLL), - NAPIF_STATE_IN_BUSY_POLL = BIT(NAPI_STATE_IN_BUSY_POLL), - NAPIF_STATE_THREADED = BIT(NAPI_STATE_THREADED), -+ NAPIF_STATE_SCHED_THREADED = BIT(NAPI_STATE_SCHED_THREADED), - }; - - enum gro_result { ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -4300,6 +4300,8 @@ static inline void ____napi_schedule(str - */ - thread = READ_ONCE(napi->thread); - if (thread) { -+ if (thread->state != TASK_INTERRUPTIBLE) -+ set_bit(NAPI_STATE_SCHED_THREADED, &napi->state); - wake_up_process(thread); - return; - } -@@ -6560,7 +6562,8 @@ bool napi_complete_done(struct napi_stru - - WARN_ON_ONCE(!(val & NAPIF_STATE_SCHED)); - -- new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED); -+ new = val & ~(NAPIF_STATE_MISSED | NAPIF_STATE_SCHED | -+ NAPIF_STATE_SCHED_THREADED); - - /* If STATE_MISSED was set, leave STATE_SCHED set, - * because we will call napi->poll() one more time. -@@ -6996,16 +6999,25 @@ static int napi_poll(struct napi_struct - - static int napi_thread_wait(struct napi_struct *napi) - { -+ bool woken = false; -+ - set_current_state(TASK_INTERRUPTIBLE); - - while (!kthread_should_stop() && !napi_disable_pending(napi)) { -- if (test_bit(NAPI_STATE_SCHED, &napi->state)) { -+ /* Testing SCHED_THREADED bit here to make sure the current -+ * kthread owns this napi and could poll on this napi. -+ * Testing SCHED bit is not enough because SCHED bit might be -+ * set by some other busy poll thread or by napi_disable(). -+ */ -+ if (test_bit(NAPI_STATE_SCHED_THREADED, &napi->state) || woken) { - WARN_ON(!list_empty(&napi->poll_list)); - __set_current_state(TASK_RUNNING); - return 0; - } - - schedule(); -+ /* woken being true indicates this thread owns this napi. */ -+ woken = true; - set_current_state(TASK_INTERRUPTIBLE); - } - __set_current_state(TASK_RUNNING); diff --git a/target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch b/target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch deleted file mode 100644 index 1223b15c33..0000000000 --- a/target/linux/generic/backport-5.15/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: Paolo Abeni -Date: Fri, 9 Apr 2021 17:24:17 +0200 -Subject: [PATCH] net: fix hangup on napi_disable for threaded napi - -napi_disable() is subject to an hangup, when the threaded -mode is enabled and the napi is under heavy traffic. - -If the relevant napi has been scheduled and the napi_disable() -kicks in before the next napi_threaded_wait() completes - so -that the latter quits due to the napi_disable_pending() condition, -the existing code leaves the NAPI_STATE_SCHED bit set and the -napi_disable() loop waiting for such bit will hang. - -This patch addresses the issue by dropping the NAPI_STATE_DISABLE -bit test in napi_thread_wait(). The later napi_threaded_poll() -iteration will take care of clearing the NAPI_STATE_SCHED. - -This also addresses a related problem reported by Jakub: -before this patch a napi_disable()/napi_enable() pair killed -the napi thread, effectively disabling the threaded mode. -On the patched kernel napi_disable() simply stops scheduling -the relevant thread. - -v1 -> v2: - - let the main napi_thread_poll() loop clear the SCHED bit - -Reported-by: Jakub Kicinski -Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") -Signed-off-by: Paolo Abeni -Reviewed-by: Eric Dumazet -Link: https://lore.kernel.org/r/883923fa22745a9589e8610962b7dc59df09fb1f.1617981844.git.pabeni@redhat.com -Signed-off-by: Jakub Kicinski ---- - ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -7003,7 +7003,7 @@ static int napi_thread_wait(struct napi_ - - set_current_state(TASK_INTERRUPTIBLE); - -- while (!kthread_should_stop() && !napi_disable_pending(napi)) { -+ while (!kthread_should_stop()) { - /* Testing SCHED_THREADED bit here to make sure the current - * kthread owns this napi and could poll on this napi. - * Testing SCHED bit is not enough because SCHED bit might be -@@ -7021,6 +7021,7 @@ static int napi_thread_wait(struct napi_ - set_current_state(TASK_INTERRUPTIBLE); - } - __set_current_state(TASK_RUNNING); -+ - return -1; - } - diff --git a/target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch b/target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch deleted file mode 100644 index c881ccfcb0..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-00-netfilter-flowtable-add-hash-offset-field-to-tuple.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Pablo Neira Ayuso -Date: Fri, 20 Nov 2020 13:49:13 +0100 -Subject: [PATCH] netfilter: flowtable: add hash offset field to tuple - -Add a placeholder field to calculate hash tuple offset. Similar to -2c407aca6497 ("netfilter: conntrack: avoid gcc-10 zero-length-bounds -warning"). - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -107,6 +107,10 @@ struct flow_offload_tuple { - - u8 l3proto; - u8 l4proto; -+ -+ /* All members above are keys for lookups, see flow_offload_hash(). */ -+ struct { } __hash; -+ - u8 dir; - - u16 mtu; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -191,14 +191,14 @@ static u32 flow_offload_hash(const void - { - const struct flow_offload_tuple *tuple = data; - -- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); -+ return jhash(tuple, offsetof(struct flow_offload_tuple, __hash), seed); - } - - static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) - { - const struct flow_offload_tuple_rhash *tuplehash = data; - -- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); -+ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, __hash), seed); - } - - static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, -@@ -207,7 +207,7 @@ static int flow_offload_hash_cmp(struct - const struct flow_offload_tuple *tuple = arg->key; - const struct flow_offload_tuple_rhash *x = ptr; - -- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) -+ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, __hash))) - return 1; - - return 0; diff --git a/target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch b/target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch deleted file mode 100644 index d98b4bfb7f..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-01-netfilter-flowtable-separate-replace-destroy-and-sta.patch +++ /dev/null @@ -1,98 +0,0 @@ -From: Oz Shlomo -Date: Tue, 23 Mar 2021 00:56:19 +0100 -Subject: [PATCH] netfilter: flowtable: separate replace, destroy and - stats to different workqueues - -Currently the flow table offload replace, destroy and stats work items are -executed on a single workqueue. As such, DESTROY and STATS commands may -be backloged after a burst of REPLACE work items. This scenario can bloat -up memory and may cause active connections to age. - -Instatiate add, del and stats workqueues to avoid backlogs of non-dependent -actions. Provide sysfs control over the workqueue attributes, allowing -userspace applications to control the workqueue cpumask. - -Signed-off-by: Oz Shlomo -Reviewed-by: Paul Blakey -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -13,7 +13,9 @@ - #include - #include - --static struct workqueue_struct *nf_flow_offload_wq; -+static struct workqueue_struct *nf_flow_offload_add_wq; -+static struct workqueue_struct *nf_flow_offload_del_wq; -+static struct workqueue_struct *nf_flow_offload_stats_wq; - - struct flow_offload_work { - struct list_head list; -@@ -827,7 +829,12 @@ static void flow_offload_work_handler(st - - static void flow_offload_queue_work(struct flow_offload_work *offload) - { -- queue_work(nf_flow_offload_wq, &offload->work); -+ if (offload->cmd == FLOW_CLS_REPLACE) -+ queue_work(nf_flow_offload_add_wq, &offload->work); -+ else if (offload->cmd == FLOW_CLS_DESTROY) -+ queue_work(nf_flow_offload_del_wq, &offload->work); -+ else -+ queue_work(nf_flow_offload_stats_wq, &offload->work); - } - - static struct flow_offload_work * -@@ -899,8 +906,11 @@ void nf_flow_offload_stats(struct nf_flo - - void nf_flow_table_offload_flush(struct nf_flowtable *flowtable) - { -- if (nf_flowtable_hw_offload(flowtable)) -- flush_workqueue(nf_flow_offload_wq); -+ if (nf_flowtable_hw_offload(flowtable)) { -+ flush_workqueue(nf_flow_offload_add_wq); -+ flush_workqueue(nf_flow_offload_del_wq); -+ flush_workqueue(nf_flow_offload_stats_wq); -+ } - } - - static int nf_flow_table_block_setup(struct nf_flowtable *flowtable, -@@ -1013,15 +1023,33 @@ EXPORT_SYMBOL_GPL(nf_flow_table_offload_ - - int nf_flow_table_offload_init(void) - { -- nf_flow_offload_wq = alloc_workqueue("nf_flow_table_offload", -- WQ_UNBOUND, 0); -- if (!nf_flow_offload_wq) -+ nf_flow_offload_add_wq = alloc_workqueue("nf_ft_offload_add", -+ WQ_UNBOUND | WQ_SYSFS, 0); -+ if (!nf_flow_offload_add_wq) - return -ENOMEM; - -+ nf_flow_offload_del_wq = alloc_workqueue("nf_ft_offload_del", -+ WQ_UNBOUND | WQ_SYSFS, 0); -+ if (!nf_flow_offload_del_wq) -+ goto err_del_wq; -+ -+ nf_flow_offload_stats_wq = alloc_workqueue("nf_ft_offload_stats", -+ WQ_UNBOUND | WQ_SYSFS, 0); -+ if (!nf_flow_offload_stats_wq) -+ goto err_stats_wq; -+ - return 0; -+ -+err_stats_wq: -+ destroy_workqueue(nf_flow_offload_del_wq); -+err_del_wq: -+ destroy_workqueue(nf_flow_offload_add_wq); -+ return -ENOMEM; - } - - void nf_flow_table_offload_exit(void) - { -- destroy_workqueue(nf_flow_offload_wq); -+ destroy_workqueue(nf_flow_offload_add_wq); -+ destroy_workqueue(nf_flow_offload_del_wq); -+ destroy_workqueue(nf_flow_offload_stats_wq); - } diff --git a/target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch b/target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch deleted file mode 100644 index 37e80d989d..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-03-netfilter-conntrack-Remove-unused-variable-declarati.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: YueHaibing -Date: Tue, 23 Mar 2021 00:56:21 +0100 -Subject: [PATCH] netfilter: conntrack: Remove unused variable - declaration - -commit e97c3e278e95 ("tproxy: split off ipv6 defragmentation to a separate -module") left behind this. - -Signed-off-by: YueHaibing -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h -+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h -@@ -4,7 +4,4 @@ - - extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; - --#include --extern struct ctl_table nf_ct_ipv6_sysctl_table[]; -- - #endif /* _NF_CONNTRACK_IPV6_H*/ diff --git a/target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch b/target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch deleted file mode 100644 index 9fd01b465e..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-04-netfilter-flowtable-consolidate-skb_try_make_writabl.patch +++ /dev/null @@ -1,291 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:22 +0100 -Subject: [PATCH] netfilter: flowtable: consolidate - skb_try_make_writable() call - -Fetch the layer 4 header size to be mangled by NAT when building the -tuple, then use it to make writable the network and the transport -headers. After this update, the NAT routines now assumes that the skbuff -area is writable. Do the pointer refetch only after the single -skb_try_make_writable() call. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -394,9 +394,6 @@ static int nf_flow_nat_port_tcp(struct s - { - struct tcphdr *tcph; - -- if (skb_try_make_writable(skb, thoff + sizeof(*tcph))) -- return -1; -- - tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false); - -@@ -408,9 +405,6 @@ static int nf_flow_nat_port_udp(struct s - { - struct udphdr *udph; - -- if (skb_try_make_writable(skb, thoff + sizeof(*udph))) -- return -1; -- - udph = (void *)(skb_network_header(skb) + thoff); - if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { - inet_proto_csum_replace2(&udph->check, skb, port, -@@ -446,9 +440,6 @@ int nf_flow_snat_port(const struct flow_ - struct flow_ports *hdr; - __be16 port, new_port; - -- if (skb_try_make_writable(skb, thoff + sizeof(*hdr))) -- return -1; -- - hdr = (void *)(skb_network_header(skb) + thoff); - - switch (dir) { -@@ -477,9 +468,6 @@ int nf_flow_dnat_port(const struct flow_ - struct flow_ports *hdr; - __be16 port, new_port; - -- if (skb_try_make_writable(skb, thoff + sizeof(*hdr))) -- return -1; -- - hdr = (void *)(skb_network_header(skb) + thoff); - - switch (dir) { ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -39,9 +39,6 @@ static int nf_flow_nat_ip_tcp(struct sk_ - { - struct tcphdr *tcph; - -- if (skb_try_make_writable(skb, thoff + sizeof(*tcph))) -- return -1; -- - tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); - -@@ -53,9 +50,6 @@ static int nf_flow_nat_ip_udp(struct sk_ - { - struct udphdr *udph; - -- if (skb_try_make_writable(skb, thoff + sizeof(*udph))) -- return -1; -- - udph = (void *)(skb_network_header(skb) + thoff); - if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { - inet_proto_csum_replace4(&udph->check, skb, addr, -@@ -136,19 +130,17 @@ static int nf_flow_dnat_ip(const struct - } - - static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, -- unsigned int thoff, enum flow_offload_tuple_dir dir) -+ unsigned int thoff, enum flow_offload_tuple_dir dir, -+ struct iphdr *iph) - { -- struct iphdr *iph = ip_hdr(skb); -- - if (test_bit(NF_FLOW_SNAT, &flow->flags) && - (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || -- nf_flow_snat_ip(flow, skb, ip_hdr(skb), thoff, dir) < 0)) -+ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) - return -1; - -- iph = ip_hdr(skb); - if (test_bit(NF_FLOW_DNAT, &flow->flags) && - (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || -- nf_flow_dnat_ip(flow, skb, ip_hdr(skb), thoff, dir) < 0)) -+ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) - return -1; - - return 0; -@@ -160,10 +152,10 @@ static bool ip_has_options(unsigned int - } - - static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, -- struct flow_offload_tuple *tuple) -+ struct flow_offload_tuple *tuple, u32 *hdrsize) - { -- unsigned int thoff, hdrsize; - struct flow_ports *ports; -+ unsigned int thoff; - struct iphdr *iph; - - if (!pskb_may_pull(skb, sizeof(*iph))) -@@ -178,10 +170,10 @@ static int nf_flow_tuple_ip(struct sk_bu - - switch (iph->protocol) { - case IPPROTO_TCP: -- hdrsize = sizeof(struct tcphdr); -+ *hdrsize = sizeof(struct tcphdr); - break; - case IPPROTO_UDP: -- hdrsize = sizeof(struct udphdr); -+ *hdrsize = sizeof(struct udphdr); - break; - default: - return -1; -@@ -191,7 +183,7 @@ static int nf_flow_tuple_ip(struct sk_bu - return -1; - - thoff = iph->ihl * 4; -- if (!pskb_may_pull(skb, thoff + hdrsize)) -+ if (!pskb_may_pull(skb, thoff + *hdrsize)) - return -1; - - iph = ip_hdr(skb); -@@ -252,11 +244,12 @@ nf_flow_offload_ip_hook(void *priv, stru - unsigned int thoff; - struct iphdr *iph; - __be32 nexthop; -+ u32 hdrsize; - - if (skb->protocol != htons(ETH_P_IP)) - return NF_ACCEPT; - -- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) -+ if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize) < 0) - return NF_ACCEPT; - - tuplehash = flow_offload_lookup(flow_table, &tuple); -@@ -271,11 +264,13 @@ nf_flow_offload_ip_hook(void *priv, stru - if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) - return NF_ACCEPT; - -- if (skb_try_make_writable(skb, sizeof(*iph))) -+ iph = ip_hdr(skb); -+ thoff = iph->ihl * 4; -+ if (skb_try_make_writable(skb, thoff + hdrsize)) - return NF_DROP; - -- thoff = ip_hdr(skb)->ihl * 4; -- if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) -+ iph = ip_hdr(skb); -+ if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) - return NF_ACCEPT; - - flow_offload_refresh(flow_table, flow); -@@ -285,10 +280,9 @@ nf_flow_offload_ip_hook(void *priv, stru - return NF_ACCEPT; - } - -- if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) -+ if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0) - return NF_DROP; - -- iph = ip_hdr(skb); - ip_decrease_ttl(iph); - skb->tstamp = 0; - -@@ -317,9 +311,6 @@ static int nf_flow_nat_ipv6_tcp(struct s - { - struct tcphdr *tcph; - -- if (skb_try_make_writable(skb, thoff + sizeof(*tcph))) -- return -1; -- - tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, - new_addr->s6_addr32, true); -@@ -333,9 +324,6 @@ static int nf_flow_nat_ipv6_udp(struct s - { - struct udphdr *udph; - -- if (skb_try_make_writable(skb, thoff + sizeof(*udph))) -- return -1; -- - udph = (void *)(skb_network_header(skb) + thoff); - if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { - inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, -@@ -417,31 +405,30 @@ static int nf_flow_dnat_ipv6(const struc - - static int nf_flow_nat_ipv6(const struct flow_offload *flow, - struct sk_buff *skb, -- enum flow_offload_tuple_dir dir) -+ enum flow_offload_tuple_dir dir, -+ struct ipv6hdr *ip6h) - { -- struct ipv6hdr *ip6h = ipv6_hdr(skb); - unsigned int thoff = sizeof(*ip6h); - - if (test_bit(NF_FLOW_SNAT, &flow->flags) && - (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || -- nf_flow_snat_ipv6(flow, skb, ipv6_hdr(skb), thoff, dir) < 0)) -+ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) - return -1; - -- ip6h = ipv6_hdr(skb); - if (test_bit(NF_FLOW_DNAT, &flow->flags) && - (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || -- nf_flow_dnat_ipv6(flow, skb, ipv6_hdr(skb), thoff, dir) < 0)) -+ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) - return -1; - - return 0; - } - - static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, -- struct flow_offload_tuple *tuple) -+ struct flow_offload_tuple *tuple, u32 *hdrsize) - { -- unsigned int thoff, hdrsize; - struct flow_ports *ports; - struct ipv6hdr *ip6h; -+ unsigned int thoff; - - if (!pskb_may_pull(skb, sizeof(*ip6h))) - return -1; -@@ -450,10 +437,10 @@ static int nf_flow_tuple_ipv6(struct sk_ - - switch (ip6h->nexthdr) { - case IPPROTO_TCP: -- hdrsize = sizeof(struct tcphdr); -+ *hdrsize = sizeof(struct tcphdr); - break; - case IPPROTO_UDP: -- hdrsize = sizeof(struct udphdr); -+ *hdrsize = sizeof(struct udphdr); - break; - default: - return -1; -@@ -463,7 +450,7 @@ static int nf_flow_tuple_ipv6(struct sk_ - return -1; - - thoff = sizeof(*ip6h); -- if (!pskb_may_pull(skb, thoff + hdrsize)) -+ if (!pskb_may_pull(skb, thoff + *hdrsize)) - return -1; - - ip6h = ipv6_hdr(skb); -@@ -493,11 +480,12 @@ nf_flow_offload_ipv6_hook(void *priv, st - struct net_device *outdev; - struct ipv6hdr *ip6h; - struct rt6_info *rt; -+ u32 hdrsize; - - if (skb->protocol != htons(ETH_P_IPV6)) - return NF_ACCEPT; - -- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) -+ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize) < 0) - return NF_ACCEPT; - - tuplehash = flow_offload_lookup(flow_table, &tuple); -@@ -523,13 +511,13 @@ nf_flow_offload_ipv6_hook(void *priv, st - return NF_ACCEPT; - } - -- if (skb_try_make_writable(skb, sizeof(*ip6h))) -+ if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) - return NF_DROP; - -- if (nf_flow_nat_ipv6(flow, skb, dir) < 0) -+ ip6h = ipv6_hdr(skb); -+ if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0) - return NF_DROP; - -- ip6h = ipv6_hdr(skb); - ip6h->hop_limit--; - skb->tstamp = 0; - diff --git a/target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch b/target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch deleted file mode 100644 index 84e294de7a..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-05-netfilter-flowtable-move-skb_try_make_writable-befor.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:23 +0100 -Subject: [PATCH] netfilter: flowtable: move skb_try_make_writable() - before NAT in IPv4 - -For consistency with the IPv6 flowtable datapath and to make sure the -skbuff is writable right before the NAT header updates. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -266,10 +266,6 @@ nf_flow_offload_ip_hook(void *priv, stru - - iph = ip_hdr(skb); - thoff = iph->ihl * 4; -- if (skb_try_make_writable(skb, thoff + hdrsize)) -- return NF_DROP; -- -- iph = ip_hdr(skb); - if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) - return NF_ACCEPT; - -@@ -280,6 +276,10 @@ nf_flow_offload_ip_hook(void *priv, stru - return NF_ACCEPT; - } - -+ if (skb_try_make_writable(skb, thoff + hdrsize)) -+ return NF_DROP; -+ -+ iph = ip_hdr(skb); - if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0) - return NF_DROP; - diff --git a/target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch b/target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch deleted file mode 100644 index 64a0e42079..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-06-netfilter-flowtable-move-FLOW_OFFLOAD_DIR_MAX-away-f.patch +++ /dev/null @@ -1,82 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:24 +0100 -Subject: [PATCH] netfilter: flowtable: move FLOW_OFFLOAD_DIR_MAX away - from enumeration - -This allows to remove the default case which should not ever happen and -that was added to avoid gcc warnings on unhandled FLOW_OFFLOAD_DIR_MAX -enumeration case. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -86,8 +86,8 @@ static inline bool nf_flowtable_hw_offlo - enum flow_offload_tuple_dir { - FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL, - FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY, -- FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX - }; -+#define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX - - struct flow_offload_tuple { - union { ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -453,8 +453,6 @@ int nf_flow_snat_port(const struct flow_ - new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; - hdr->dest = new_port; - break; -- default: -- return -1; - } - - return nf_flow_nat_port(skb, thoff, protocol, port, new_port); -@@ -481,8 +479,6 @@ int nf_flow_dnat_port(const struct flow_ - new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; - hdr->source = new_port; - break; -- default: -- return -1; - } - - return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -96,8 +96,6 @@ static int nf_flow_snat_ip(const struct - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; - iph->daddr = new_addr; - break; -- default: -- return -1; - } - csum_replace4(&iph->check, addr, new_addr); - -@@ -121,8 +119,6 @@ static int nf_flow_dnat_ip(const struct - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; - iph->saddr = new_addr; - break; -- default: -- return -1; - } - csum_replace4(&iph->check, addr, new_addr); - -@@ -371,8 +367,6 @@ static int nf_flow_snat_ipv6(const struc - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; - ip6h->daddr = new_addr; - break; -- default: -- return -1; - } - - return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); -@@ -396,8 +390,6 @@ static int nf_flow_dnat_ipv6(const struc - new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; - ip6h->saddr = new_addr; - break; -- default: -- return -1; - } - - return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); diff --git a/target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch b/target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch deleted file mode 100644 index 2224e095c9..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-07-netfilter-flowtable-fast-NAT-functions-never-fail.patch +++ /dev/null @@ -1,394 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:25 +0100 -Subject: [PATCH] netfilter: flowtable: fast NAT functions never fail - -Simplify existing fast NAT routines by returning void. After the -skb_try_make_writable() call consolidation, these routines cannot ever -fail. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -228,12 +228,12 @@ void nf_flow_table_free(struct nf_flowta - - void flow_offload_teardown(struct flow_offload *flow); - --int nf_flow_snat_port(const struct flow_offload *flow, -- struct sk_buff *skb, unsigned int thoff, -- u8 protocol, enum flow_offload_tuple_dir dir); --int nf_flow_dnat_port(const struct flow_offload *flow, -- struct sk_buff *skb, unsigned int thoff, -- u8 protocol, enum flow_offload_tuple_dir dir); -+void nf_flow_snat_port(const struct flow_offload *flow, -+ struct sk_buff *skb, unsigned int thoff, -+ u8 protocol, enum flow_offload_tuple_dir dir); -+void nf_flow_dnat_port(const struct flow_offload *flow, -+ struct sk_buff *skb, unsigned int thoff, -+ u8 protocol, enum flow_offload_tuple_dir dir); - - struct flow_ports { - __be16 source, dest; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -388,20 +388,17 @@ static void nf_flow_offload_work_gc(stru - queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); - } - -- --static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, -- __be16 port, __be16 new_port) -+static void nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, -+ __be16 port, __be16 new_port) - { - struct tcphdr *tcph; - - tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false); -- -- return 0; - } - --static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, -- __be16 port, __be16 new_port) -+static void nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, -+ __be16 port, __be16 new_port) - { - struct udphdr *udph; - -@@ -412,30 +409,24 @@ static int nf_flow_nat_port_udp(struct s - if (!udph->check) - udph->check = CSUM_MANGLED_0; - } -- -- return 0; - } - --static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, -- u8 protocol, __be16 port, __be16 new_port) -+static void nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, -+ u8 protocol, __be16 port, __be16 new_port) - { - switch (protocol) { - case IPPROTO_TCP: -- if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) -- return NF_DROP; -+ nf_flow_nat_port_tcp(skb, thoff, port, new_port); - break; - case IPPROTO_UDP: -- if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) -- return NF_DROP; -+ nf_flow_nat_port_udp(skb, thoff, port, new_port); - break; - } -- -- return 0; - } - --int nf_flow_snat_port(const struct flow_offload *flow, -- struct sk_buff *skb, unsigned int thoff, -- u8 protocol, enum flow_offload_tuple_dir dir) -+void nf_flow_snat_port(const struct flow_offload *flow, -+ struct sk_buff *skb, unsigned int thoff, -+ u8 protocol, enum flow_offload_tuple_dir dir) - { - struct flow_ports *hdr; - __be16 port, new_port; -@@ -455,13 +446,13 @@ int nf_flow_snat_port(const struct flow_ - break; - } - -- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); -+ nf_flow_nat_port(skb, thoff, protocol, port, new_port); - } - EXPORT_SYMBOL_GPL(nf_flow_snat_port); - --int nf_flow_dnat_port(const struct flow_offload *flow, -- struct sk_buff *skb, unsigned int thoff, -- u8 protocol, enum flow_offload_tuple_dir dir) -+void nf_flow_dnat_port(const struct flow_offload *flow, struct sk_buff *skb, -+ unsigned int thoff, u8 protocol, -+ enum flow_offload_tuple_dir dir) - { - struct flow_ports *hdr; - __be16 port, new_port; -@@ -481,7 +472,7 @@ int nf_flow_dnat_port(const struct flow_ - break; - } - -- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); -+ nf_flow_nat_port(skb, thoff, protocol, port, new_port); - } - EXPORT_SYMBOL_GPL(nf_flow_dnat_port); - ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -34,19 +34,17 @@ static int nf_flow_state_check(struct fl - return 0; - } - --static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, -- __be32 addr, __be32 new_addr) -+static void nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, -+ __be32 addr, __be32 new_addr) - { - struct tcphdr *tcph; - - tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); -- -- return 0; - } - --static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, -- __be32 addr, __be32 new_addr) -+static void nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, -+ __be32 addr, __be32 new_addr) - { - struct udphdr *udph; - -@@ -57,31 +55,25 @@ static int nf_flow_nat_ip_udp(struct sk_ - if (!udph->check) - udph->check = CSUM_MANGLED_0; - } -- -- return 0; - } - --static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, -- unsigned int thoff, __be32 addr, -- __be32 new_addr) -+static void nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, -+ unsigned int thoff, __be32 addr, -+ __be32 new_addr) - { - switch (iph->protocol) { - case IPPROTO_TCP: -- if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) -- return NF_DROP; -+ nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr); - break; - case IPPROTO_UDP: -- if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) -- return NF_DROP; -+ nf_flow_nat_ip_udp(skb, thoff, addr, new_addr); - break; - } -- -- return 0; - } - --static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, -- struct iphdr *iph, unsigned int thoff, -- enum flow_offload_tuple_dir dir) -+static void nf_flow_snat_ip(const struct flow_offload *flow, -+ struct sk_buff *skb, struct iphdr *iph, -+ unsigned int thoff, enum flow_offload_tuple_dir dir) - { - __be32 addr, new_addr; - -@@ -99,12 +91,12 @@ static int nf_flow_snat_ip(const struct - } - csum_replace4(&iph->check, addr, new_addr); - -- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); -+ nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); - } - --static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, -- struct iphdr *iph, unsigned int thoff, -- enum flow_offload_tuple_dir dir) -+static void nf_flow_dnat_ip(const struct flow_offload *flow, -+ struct sk_buff *skb, struct iphdr *iph, -+ unsigned int thoff, enum flow_offload_tuple_dir dir) - { - __be32 addr, new_addr; - -@@ -122,24 +114,21 @@ static int nf_flow_dnat_ip(const struct - } - csum_replace4(&iph->check, addr, new_addr); - -- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); -+ nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); - } - --static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, -+static void nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, - unsigned int thoff, enum flow_offload_tuple_dir dir, - struct iphdr *iph) - { -- if (test_bit(NF_FLOW_SNAT, &flow->flags) && -- (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || -- nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) -- return -1; -- -- if (test_bit(NF_FLOW_DNAT, &flow->flags) && -- (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || -- nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) -- return -1; -- -- return 0; -+ if (test_bit(NF_FLOW_SNAT, &flow->flags)) { -+ nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir); -+ nf_flow_snat_ip(flow, skb, iph, thoff, dir); -+ } -+ if (test_bit(NF_FLOW_DNAT, &flow->flags)) { -+ nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir); -+ nf_flow_dnat_ip(flow, skb, iph, thoff, dir); -+ } - } - - static bool ip_has_options(unsigned int thoff) -@@ -276,8 +265,7 @@ nf_flow_offload_ip_hook(void *priv, stru - return NF_DROP; - - iph = ip_hdr(skb); -- if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0) -- return NF_DROP; -+ nf_flow_nat_ip(flow, skb, thoff, dir, iph); - - ip_decrease_ttl(iph); - skb->tstamp = 0; -@@ -301,22 +289,21 @@ nf_flow_offload_ip_hook(void *priv, stru - } - EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); - --static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, -- struct in6_addr *addr, -- struct in6_addr *new_addr) -+static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, -+ struct in6_addr *addr, -+ struct in6_addr *new_addr, -+ struct ipv6hdr *ip6h) - { - struct tcphdr *tcph; - - tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, - new_addr->s6_addr32, true); -- -- return 0; - } - --static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, -- struct in6_addr *addr, -- struct in6_addr *new_addr) -+static void nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, -+ struct in6_addr *addr, -+ struct in6_addr *new_addr) - { - struct udphdr *udph; - -@@ -327,32 +314,26 @@ static int nf_flow_nat_ipv6_udp(struct s - if (!udph->check) - udph->check = CSUM_MANGLED_0; - } -- -- return 0; - } - --static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, -- unsigned int thoff, struct in6_addr *addr, -- struct in6_addr *new_addr) -+static void nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, -+ unsigned int thoff, struct in6_addr *addr, -+ struct in6_addr *new_addr) - { - switch (ip6h->nexthdr) { - case IPPROTO_TCP: -- if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) -- return NF_DROP; -+ nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr, ip6h); - break; - case IPPROTO_UDP: -- if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) -- return NF_DROP; -+ nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr); - break; - } -- -- return 0; - } - --static int nf_flow_snat_ipv6(const struct flow_offload *flow, -- struct sk_buff *skb, struct ipv6hdr *ip6h, -- unsigned int thoff, -- enum flow_offload_tuple_dir dir) -+static void nf_flow_snat_ipv6(const struct flow_offload *flow, -+ struct sk_buff *skb, struct ipv6hdr *ip6h, -+ unsigned int thoff, -+ enum flow_offload_tuple_dir dir) - { - struct in6_addr addr, new_addr; - -@@ -369,13 +350,13 @@ static int nf_flow_snat_ipv6(const struc - break; - } - -- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); -+ nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); - } - --static int nf_flow_dnat_ipv6(const struct flow_offload *flow, -- struct sk_buff *skb, struct ipv6hdr *ip6h, -- unsigned int thoff, -- enum flow_offload_tuple_dir dir) -+static void nf_flow_dnat_ipv6(const struct flow_offload *flow, -+ struct sk_buff *skb, struct ipv6hdr *ip6h, -+ unsigned int thoff, -+ enum flow_offload_tuple_dir dir) - { - struct in6_addr addr, new_addr; - -@@ -392,27 +373,24 @@ static int nf_flow_dnat_ipv6(const struc - break; - } - -- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); -+ nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); - } - --static int nf_flow_nat_ipv6(const struct flow_offload *flow, -- struct sk_buff *skb, -- enum flow_offload_tuple_dir dir, -- struct ipv6hdr *ip6h) -+static void nf_flow_nat_ipv6(const struct flow_offload *flow, -+ struct sk_buff *skb, -+ enum flow_offload_tuple_dir dir, -+ struct ipv6hdr *ip6h) - { - unsigned int thoff = sizeof(*ip6h); - -- if (test_bit(NF_FLOW_SNAT, &flow->flags) && -- (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || -- nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) -- return -1; -- -- if (test_bit(NF_FLOW_DNAT, &flow->flags) && -- (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || -- nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) -- return -1; -- -- return 0; -+ if (test_bit(NF_FLOW_SNAT, &flow->flags)) { -+ nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir); -+ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir); -+ } -+ if (test_bit(NF_FLOW_DNAT, &flow->flags)) { -+ nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir); -+ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir); -+ } - } - - static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, -@@ -507,8 +485,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - return NF_DROP; - - ip6h = ipv6_hdr(skb); -- if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0) -- return NF_DROP; -+ nf_flow_nat_ipv6(flow, skb, dir, ip6h); - - ip6h->hop_limit--; - skb->tstamp = 0; diff --git a/target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch b/target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch deleted file mode 100644 index 276785030d..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-08-netfilter-flowtable-call-dst_check-to-fall-back-to-c.patch +++ /dev/null @@ -1,46 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:26 +0100 -Subject: [PATCH] netfilter: flowtable: call dst_check() to fall back to - classic forwarding - -In case the route is stale, pass up the packet to the classic forwarding -path for re-evaluation and schedule this flow entry for removal. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -197,14 +197,6 @@ static bool nf_flow_exceeds_mtu(const st - return true; - } - --static int nf_flow_offload_dst_check(struct dst_entry *dst) --{ -- if (unlikely(dst_xfrm(dst))) -- return dst_check(dst, 0) ? 0 : -1; -- -- return 0; --} -- - static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, - const struct nf_hook_state *state, - struct dst_entry *dst) -@@ -256,7 +248,7 @@ nf_flow_offload_ip_hook(void *priv, stru - - flow_offload_refresh(flow_table, flow); - -- if (nf_flow_offload_dst_check(&rt->dst)) { -+ if (!dst_check(&rt->dst, 0)) { - flow_offload_teardown(flow); - return NF_ACCEPT; - } -@@ -476,7 +468,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - - flow_offload_refresh(flow_table, flow); - -- if (nf_flow_offload_dst_check(&rt->dst)) { -+ if (!dst_check(&rt->dst, 0)) { - flow_offload_teardown(flow); - return NF_ACCEPT; - } diff --git a/target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch b/target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch deleted file mode 100644 index 14ac2ee295..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-09-netfilter-flowtable-refresh-timeout-after-dst-and-wr.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:27 +0100 -Subject: [PATCH] netfilter: flowtable: refresh timeout after dst and - writable checks - -Refresh the timeout (and retry hardware offload) once the skbuff dst -is confirmed to be current and after the skbuff is made writable. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -246,8 +246,6 @@ nf_flow_offload_ip_hook(void *priv, stru - if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) - return NF_ACCEPT; - -- flow_offload_refresh(flow_table, flow); -- - if (!dst_check(&rt->dst, 0)) { - flow_offload_teardown(flow); - return NF_ACCEPT; -@@ -256,6 +254,8 @@ nf_flow_offload_ip_hook(void *priv, stru - if (skb_try_make_writable(skb, thoff + hdrsize)) - return NF_DROP; - -+ flow_offload_refresh(flow_table, flow); -+ - iph = ip_hdr(skb); - nf_flow_nat_ip(flow, skb, thoff, dir, iph); - -@@ -466,8 +466,6 @@ nf_flow_offload_ipv6_hook(void *priv, st - sizeof(*ip6h))) - return NF_ACCEPT; - -- flow_offload_refresh(flow_table, flow); -- - if (!dst_check(&rt->dst, 0)) { - flow_offload_teardown(flow); - return NF_ACCEPT; -@@ -476,6 +474,8 @@ nf_flow_offload_ipv6_hook(void *priv, st - if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) - return NF_DROP; - -+ flow_offload_refresh(flow_table, flow); -+ - ip6h = ipv6_hdr(skb); - nf_flow_nat_ipv6(flow, skb, dir, ip6h); - diff --git a/target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch b/target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch deleted file mode 100644 index fa6e0c4173..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 23 Mar 2021 00:56:28 +0100 -Subject: [PATCH] netfilter: nftables: update table flags from the commit - phase - -Do not update table flags from the preparation phase. Store the flags -update into the transaction, then update the flags from the commit -phase. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_tables.h -+++ b/include/net/netfilter/nf_tables.h -@@ -1470,13 +1470,16 @@ struct nft_trans_chain { - - struct nft_trans_table { - bool update; -- bool enable; -+ u8 state; -+ u32 flags; - }; - - #define nft_trans_table_update(trans) \ - (((struct nft_trans_table *)trans->data)->update) --#define nft_trans_table_enable(trans) \ -- (((struct nft_trans_table *)trans->data)->enable) -+#define nft_trans_table_state(trans) \ -+ (((struct nft_trans_table *)trans->data)->state) -+#define nft_trans_table_flags(trans) \ -+ (((struct nft_trans_table *)trans->data)->flags) - - struct nft_trans_elem { - struct nft_set *set; ---- a/net/netfilter/nf_tables_api.c -+++ b/net/netfilter/nf_tables_api.c -@@ -891,6 +891,12 @@ static void nf_tables_table_disable(stru - nft_table_disable(net, table, 0); - } - -+enum { -+ NFT_TABLE_STATE_UNCHANGED = 0, -+ NFT_TABLE_STATE_DORMANT, -+ NFT_TABLE_STATE_WAKEUP -+}; -+ - static int nf_tables_updtable(struct nft_ctx *ctx) - { - struct nft_trans *trans; -@@ -914,19 +920,17 @@ static int nf_tables_updtable(struct nft - - if ((flags & NFT_TABLE_F_DORMANT) && - !(ctx->table->flags & NFT_TABLE_F_DORMANT)) { -- nft_trans_table_enable(trans) = false; -+ nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT; - } else if (!(flags & NFT_TABLE_F_DORMANT) && - ctx->table->flags & NFT_TABLE_F_DORMANT) { -- ctx->table->flags &= ~NFT_TABLE_F_DORMANT; - ret = nf_tables_table_enable(ctx->net, ctx->table); - if (ret >= 0) -- nft_trans_table_enable(trans) = true; -- else -- ctx->table->flags |= NFT_TABLE_F_DORMANT; -+ nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP; - } - if (ret < 0) - goto err; - -+ nft_trans_table_flags(trans) = flags; - nft_trans_table_update(trans) = true; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); - return 0; -@@ -7908,11 +7912,10 @@ static int nf_tables_commit(struct net * - switch (trans->msg_type) { - case NFT_MSG_NEWTABLE: - if (nft_trans_table_update(trans)) { -- if (!nft_trans_table_enable(trans)) { -- nf_tables_table_disable(net, -- trans->ctx.table); -- trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; -- } -+ if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT) -+ nf_tables_table_disable(net, trans->ctx.table); -+ -+ trans->ctx.table->flags = nft_trans_table_flags(trans); - } else { - nft_clear(net, trans->ctx.table); - } -@@ -8125,11 +8128,9 @@ static int __nf_tables_abort(struct net - switch (trans->msg_type) { - case NFT_MSG_NEWTABLE: - if (nft_trans_table_update(trans)) { -- if (nft_trans_table_enable(trans)) { -- nf_tables_table_disable(net, -- trans->ctx.table); -- trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; -- } -+ if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP) -+ nf_tables_table_disable(net, trans->ctx.table); -+ - nft_trans_destroy(trans); - } else { - list_del_rcu(&trans->ctx.table->list); diff --git a/target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch b/target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch deleted file mode 100644 index a8fc1cabe2..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-11-net-resolve-forwarding-path-from-virtual-netdevice-a.patch +++ /dev/null @@ -1,170 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:32 +0100 -Subject: [PATCH] net: resolve forwarding path from virtual netdevice and - HW destination address - -This patch adds dev_fill_forward_path() which resolves the path to reach -the real netdevice from the IP forwarding side. This function takes as -input the netdevice and the destination hardware address and it walks -down the devices calling .ndo_fill_forward_path() for each device until -the real device is found. - -For instance, assuming the following topology: - - IP forwarding - / \ - br0 eth0 - / \ - eth1 eth2 - . - . - . - ethX - ab:cd:ef:ab:cd:ef - -where eth1 and eth2 are bridge ports and eth0 provides WAN connectivity. -ethX is the interface in another box which is connected to the eth1 -bridge port. - -For packets going through IP forwarding to br0 whose destination MAC -address is ab:cd:ef:ab:cd:ef, dev_fill_forward_path() provides the -following path: - - br0 -> eth1 - -.ndo_fill_forward_path for br0 looks up at the FDB for the bridge port -from the destination MAC address to get the bridge port eth1. - -This information allows to create a fast path that bypasses the classic -bridge and IP forwarding paths, so packets go directly from the bridge -port eth1 to eth0 (wan interface) and vice versa. - - fast path - .------------------------. - / \ - | IP forwarding | - | / \ \/ - | br0 eth0 - . / \ - -> eth1 eth2 - . - . - . - ethX - ab:cd:ef:ab:cd:ef - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -827,6 +827,27 @@ typedef u16 (*select_queue_fallback_t)(s - struct sk_buff *skb, - struct net_device *sb_dev); - -+enum net_device_path_type { -+ DEV_PATH_ETHERNET = 0, -+}; -+ -+struct net_device_path { -+ enum net_device_path_type type; -+ const struct net_device *dev; -+}; -+ -+#define NET_DEVICE_PATH_STACK_MAX 5 -+ -+struct net_device_path_stack { -+ int num_paths; -+ struct net_device_path path[NET_DEVICE_PATH_STACK_MAX]; -+}; -+ -+struct net_device_path_ctx { -+ const struct net_device *dev; -+ const u8 *daddr; -+}; -+ - enum tc_setup_type { - TC_SETUP_QDISC_MQPRIO, - TC_SETUP_CLSU32, -@@ -1273,6 +1294,8 @@ struct netdev_net_notifier { - * struct net_device *(*ndo_get_peer_dev)(struct net_device *dev); - * If a device is paired with a peer device, return the peer instance. - * The caller must be under RCU read context. -+ * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path); -+ * Get the forwarding path to reach the real device from the HW destination address - */ - struct net_device_ops { - int (*ndo_init)(struct net_device *dev); -@@ -1481,6 +1504,8 @@ struct net_device_ops { - int (*ndo_tunnel_ctl)(struct net_device *dev, - struct ip_tunnel_parm *p, int cmd); - struct net_device * (*ndo_get_peer_dev)(struct net_device *dev); -+ int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, -+ struct net_device_path *path); - }; - - /** -@@ -2828,6 +2853,8 @@ void dev_remove_offload(struct packet_of - - int dev_get_iflink(const struct net_device *dev); - int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); -+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr, -+ struct net_device_path_stack *stack); - struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags, - unsigned short mask); - struct net_device *dev_get_by_name(struct net *net, const char *name); ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -847,6 +847,52 @@ int dev_fill_metadata_dst(struct net_dev - } - EXPORT_SYMBOL_GPL(dev_fill_metadata_dst); - -+static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack) -+{ -+ int k = stack->num_paths++; -+ -+ if (WARN_ON_ONCE(k >= NET_DEVICE_PATH_STACK_MAX)) -+ return NULL; -+ -+ return &stack->path[k]; -+} -+ -+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr, -+ struct net_device_path_stack *stack) -+{ -+ const struct net_device *last_dev; -+ struct net_device_path_ctx ctx = { -+ .dev = dev, -+ .daddr = daddr, -+ }; -+ struct net_device_path *path; -+ int ret = 0; -+ -+ stack->num_paths = 0; -+ while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) { -+ last_dev = ctx.dev; -+ path = dev_fwd_path(stack); -+ if (!path) -+ return -1; -+ -+ memset(path, 0, sizeof(struct net_device_path)); -+ ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path); -+ if (ret < 0) -+ return -1; -+ -+ if (WARN_ON_ONCE(last_dev == ctx.dev)) -+ return -1; -+ } -+ path = dev_fwd_path(stack); -+ if (!path) -+ return -1; -+ path->type = DEV_PATH_ETHERNET; -+ path->dev = ctx.dev; -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(dev_fill_forward_path); -+ - /** - * __dev_get_by_name - find a device by its name - * @net: the applicable net namespace diff --git a/target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch b/target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch deleted file mode 100644 index 32c8c9bb78..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-12-net-8021q-resolve-forwarding-path-for-vlan-devices.patch +++ /dev/null @@ -1,80 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:33 +0100 -Subject: [PATCH] net: 8021q: resolve forwarding path for vlan devices - -Add .ndo_fill_forward_path for vlan devices. - -For instance, assuming the following topology: - - IP forwarding - / \ - eth0.100 eth0 - | - eth0 - . - . - . - ethX - ab:cd:ef:ab:cd:ef - -For packets going through IP forwarding to eth0.100 whose destination -MAC address is ab:cd:ef:ab:cd:ef, dev_fill_forward_path() provides the -following path: - - eth0.100 -> eth0 - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -829,11 +829,18 @@ typedef u16 (*select_queue_fallback_t)(s - - enum net_device_path_type { - DEV_PATH_ETHERNET = 0, -+ DEV_PATH_VLAN, - }; - - struct net_device_path { - enum net_device_path_type type; - const struct net_device *dev; -+ union { -+ struct { -+ u16 id; -+ __be16 proto; -+ } encap; -+ }; - }; - - #define NET_DEVICE_PATH_STACK_MAX 5 ---- a/net/8021q/vlan_dev.c -+++ b/net/8021q/vlan_dev.c -@@ -770,6 +770,20 @@ static int vlan_dev_get_iflink(const str - return real_dev->ifindex; - } - -+static int vlan_dev_fill_forward_path(struct net_device_path_ctx *ctx, -+ struct net_device_path *path) -+{ -+ struct vlan_dev_priv *vlan = vlan_dev_priv(ctx->dev); -+ -+ path->type = DEV_PATH_VLAN; -+ path->encap.id = vlan->vlan_id; -+ path->encap.proto = vlan->vlan_proto; -+ path->dev = ctx->dev; -+ ctx->dev = vlan->real_dev; -+ -+ return 0; -+} -+ - static const struct ethtool_ops vlan_ethtool_ops = { - .get_link_ksettings = vlan_ethtool_get_link_ksettings, - .get_drvinfo = vlan_ethtool_get_drvinfo, -@@ -808,6 +822,7 @@ static const struct net_device_ops vlan_ - #endif - .ndo_fix_features = vlan_dev_fix_features, - .ndo_get_iflink = vlan_dev_get_iflink, -+ .ndo_fill_forward_path = vlan_dev_fill_forward_path, - }; - - static void vlan_dev_free(struct net_device *dev) diff --git a/target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch b/target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch deleted file mode 100644 index bdb12b13a6..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-13-net-bridge-resolve-forwarding-path-for-bridge-device.patch +++ /dev/null @@ -1,62 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:34 +0100 -Subject: [PATCH] net: bridge: resolve forwarding path for bridge devices - -Add .ndo_fill_forward_path for bridge devices. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -830,6 +830,7 @@ typedef u16 (*select_queue_fallback_t)(s - enum net_device_path_type { - DEV_PATH_ETHERNET = 0, - DEV_PATH_VLAN, -+ DEV_PATH_BRIDGE, - }; - - struct net_device_path { ---- a/net/bridge/br_device.c -+++ b/net/bridge/br_device.c -@@ -398,6 +398,32 @@ static int br_del_slave(struct net_devic - return br_del_if(br, slave_dev); - } - -+static int br_fill_forward_path(struct net_device_path_ctx *ctx, -+ struct net_device_path *path) -+{ -+ struct net_bridge_fdb_entry *f; -+ struct net_bridge_port *dst; -+ struct net_bridge *br; -+ -+ if (netif_is_bridge_port(ctx->dev)) -+ return -1; -+ -+ br = netdev_priv(ctx->dev); -+ f = br_fdb_find_rcu(br, ctx->daddr, 0); -+ if (!f || !f->dst) -+ return -1; -+ -+ dst = READ_ONCE(f->dst); -+ if (!dst) -+ return -1; -+ -+ path->type = DEV_PATH_BRIDGE; -+ path->dev = dst->br->dev; -+ ctx->dev = dst->dev; -+ -+ return 0; -+} -+ - static const struct ethtool_ops br_ethtool_ops = { - .get_drvinfo = br_getinfo, - .get_link = ethtool_op_get_link, -@@ -432,6 +458,7 @@ static const struct net_device_ops br_ne - .ndo_bridge_setlink = br_setlink, - .ndo_bridge_dellink = br_dellink, - .ndo_features_check = passthru_features_check, -+ .ndo_fill_forward_path = br_fill_forward_path, - }; - - static struct device_type br_type = { diff --git a/target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch b/target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch deleted file mode 100644 index ba2b1a2877..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-14-net-bridge-resolve-forwarding-path-for-VLAN-tag-acti.patch +++ /dev/null @@ -1,207 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:35 +0100 -Subject: [PATCH] net: bridge: resolve forwarding path for VLAN tag - actions in bridge devices - -Depending on the VLAN settings of the bridge and the port, the bridge can -either add or remove a tag. When vlan filtering is enabled, the fdb lookup -also needs to know the VLAN tag/proto for the destination address -To provide this, keep track of the stack of VLAN tags for the path in the -lookup context - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -841,10 +841,20 @@ struct net_device_path { - u16 id; - __be16 proto; - } encap; -+ struct { -+ enum { -+ DEV_PATH_BR_VLAN_KEEP, -+ DEV_PATH_BR_VLAN_TAG, -+ DEV_PATH_BR_VLAN_UNTAG, -+ } vlan_mode; -+ u16 vlan_id; -+ __be16 vlan_proto; -+ } bridge; - }; - }; - - #define NET_DEVICE_PATH_STACK_MAX 5 -+#define NET_DEVICE_PATH_VLAN_MAX 2 - - struct net_device_path_stack { - int num_paths; -@@ -854,6 +864,12 @@ struct net_device_path_stack { - struct net_device_path_ctx { - const struct net_device *dev; - const u8 *daddr; -+ -+ int num_vlans; -+ struct { -+ u16 id; -+ __be16 proto; -+ } vlan[NET_DEVICE_PATH_VLAN_MAX]; - }; - - enum tc_setup_type { ---- a/net/8021q/vlan_dev.c -+++ b/net/8021q/vlan_dev.c -@@ -780,6 +780,12 @@ static int vlan_dev_fill_forward_path(st - path->encap.proto = vlan->vlan_proto; - path->dev = ctx->dev; - ctx->dev = vlan->real_dev; -+ if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan)) -+ return -ENOSPC; -+ -+ ctx->vlan[ctx->num_vlans].id = vlan->vlan_id; -+ ctx->vlan[ctx->num_vlans].proto = vlan->vlan_proto; -+ ctx->num_vlans++; - - return 0; - } ---- a/net/bridge/br_device.c -+++ b/net/bridge/br_device.c -@@ -409,7 +409,10 @@ static int br_fill_forward_path(struct n - return -1; - - br = netdev_priv(ctx->dev); -- f = br_fdb_find_rcu(br, ctx->daddr, 0); -+ -+ br_vlan_fill_forward_path_pvid(br, ctx, path); -+ -+ f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id); - if (!f || !f->dst) - return -1; - -@@ -417,10 +420,28 @@ static int br_fill_forward_path(struct n - if (!dst) - return -1; - -+ if (br_vlan_fill_forward_path_mode(br, dst, path)) -+ return -1; -+ - path->type = DEV_PATH_BRIDGE; - path->dev = dst->br->dev; - ctx->dev = dst->dev; - -+ switch (path->bridge.vlan_mode) { -+ case DEV_PATH_BR_VLAN_TAG: -+ if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan)) -+ return -ENOSPC; -+ ctx->vlan[ctx->num_vlans].id = path->bridge.vlan_id; -+ ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto; -+ ctx->num_vlans++; -+ break; -+ case DEV_PATH_BR_VLAN_UNTAG: -+ ctx->num_vlans--; -+ break; -+ case DEV_PATH_BR_VLAN_KEEP: -+ break; -+ } -+ - return 0; - } - ---- a/net/bridge/br_private.h -+++ b/net/bridge/br_private.h -@@ -1093,6 +1093,13 @@ void br_vlan_notify(const struct net_bri - bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, - const struct net_bridge_vlan *range_end); - -+void br_vlan_fill_forward_path_pvid(struct net_bridge *br, -+ struct net_device_path_ctx *ctx, -+ struct net_device_path *path); -+int br_vlan_fill_forward_path_mode(struct net_bridge *br, -+ struct net_bridge_port *dst, -+ struct net_device_path *path); -+ - static inline struct net_bridge_vlan_group *br_vlan_group( - const struct net_bridge *br) - { -@@ -1250,6 +1257,19 @@ static inline int nbp_get_num_vlan_infos - { - return 0; - } -+ -+static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br, -+ struct net_device_path_ctx *ctx, -+ struct net_device_path *path) -+{ -+} -+ -+static inline int br_vlan_fill_forward_path_mode(struct net_bridge *br, -+ struct net_bridge_port *dst, -+ struct net_device_path *path) -+{ -+ return 0; -+} - - static inline struct net_bridge_vlan_group *br_vlan_group( - const struct net_bridge *br) ---- a/net/bridge/br_vlan.c -+++ b/net/bridge/br_vlan.c -@@ -1327,6 +1327,59 @@ int br_vlan_get_pvid_rcu(const struct ne - } - EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu); - -+void br_vlan_fill_forward_path_pvid(struct net_bridge *br, -+ struct net_device_path_ctx *ctx, -+ struct net_device_path *path) -+{ -+ struct net_bridge_vlan_group *vg; -+ int idx = ctx->num_vlans - 1; -+ u16 vid; -+ -+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; -+ -+ if (!br_opt_get(br, BROPT_VLAN_ENABLED)) -+ return; -+ -+ vg = br_vlan_group(br); -+ -+ if (idx >= 0 && -+ ctx->vlan[idx].proto == br->vlan_proto) { -+ vid = ctx->vlan[idx].id; -+ } else { -+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_TAG; -+ vid = br_get_pvid(vg); -+ } -+ -+ path->bridge.vlan_id = vid; -+ path->bridge.vlan_proto = br->vlan_proto; -+} -+ -+int br_vlan_fill_forward_path_mode(struct net_bridge *br, -+ struct net_bridge_port *dst, -+ struct net_device_path *path) -+{ -+ struct net_bridge_vlan_group *vg; -+ struct net_bridge_vlan *v; -+ -+ if (!br_opt_get(br, BROPT_VLAN_ENABLED)) -+ return 0; -+ -+ vg = nbp_vlan_group_rcu(dst); -+ v = br_vlan_find(vg, path->bridge.vlan_id); -+ if (!v || !br_vlan_should_use(v)) -+ return -EINVAL; -+ -+ if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) -+ return 0; -+ -+ if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) -+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; -+ else -+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; -+ -+ return 0; -+} -+ - int br_vlan_get_info(const struct net_device *dev, u16 vid, - struct bridge_vlan_info *p_vinfo) - { diff --git a/target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch b/target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch deleted file mode 100644 index 712bb9ec97..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-15-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch +++ /dev/null @@ -1,113 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:36 +0100 -Subject: [PATCH] net: ppp: resolve forwarding path for bridge pppoe - devices - -Pass on the PPPoE session ID, destination hardware address and the real -device. - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -1466,12 +1466,34 @@ static void ppp_dev_priv_destructor(stru - ppp_destroy_interface(ppp); - } - -+static int ppp_fill_forward_path(struct net_device_path_ctx *ctx, -+ struct net_device_path *path) -+{ -+ struct ppp *ppp = netdev_priv(ctx->dev); -+ struct ppp_channel *chan; -+ struct channel *pch; -+ -+ if (ppp->flags & SC_MULTILINK) -+ return -EOPNOTSUPP; -+ -+ if (list_empty(&ppp->channels)) -+ return -ENODEV; -+ -+ pch = list_first_entry(&ppp->channels, struct channel, clist); -+ chan = pch->chan; -+ if (!chan->ops->fill_forward_path) -+ return -EOPNOTSUPP; -+ -+ return chan->ops->fill_forward_path(ctx, path, chan); -+} -+ - static const struct net_device_ops ppp_netdev_ops = { - .ndo_init = ppp_dev_init, - .ndo_uninit = ppp_dev_uninit, - .ndo_start_xmit = ppp_start_xmit, - .ndo_do_ioctl = ppp_net_ioctl, - .ndo_get_stats64 = ppp_get_stats64, -+ .ndo_fill_forward_path = ppp_fill_forward_path, - }; - - static struct device_type ppp_type = { ---- a/drivers/net/ppp/pppoe.c -+++ b/drivers/net/ppp/pppoe.c -@@ -972,8 +972,31 @@ static int pppoe_xmit(struct ppp_channel - return __pppoe_xmit(sk, skb); - } - -+static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx, -+ struct net_device_path *path, -+ const struct ppp_channel *chan) -+{ -+ struct sock *sk = (struct sock *)chan->private; -+ struct pppox_sock *po = pppox_sk(sk); -+ struct net_device *dev = po->pppoe_dev; -+ -+ if (sock_flag(sk, SOCK_DEAD) || -+ !(sk->sk_state & PPPOX_CONNECTED) || !dev) -+ return -1; -+ -+ path->type = DEV_PATH_PPPOE; -+ path->encap.proto = htons(ETH_P_PPP_SES); -+ path->encap.id = be16_to_cpu(po->num); -+ memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); -+ path->dev = ctx->dev; -+ ctx->dev = dev; -+ -+ return 0; -+} -+ - static const struct ppp_channel_ops pppoe_chan_ops = { - .start_xmit = pppoe_xmit, -+ .fill_forward_path = pppoe_fill_forward_path, - }; - - static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -831,6 +831,7 @@ enum net_device_path_type { - DEV_PATH_ETHERNET = 0, - DEV_PATH_VLAN, - DEV_PATH_BRIDGE, -+ DEV_PATH_PPPOE, - }; - - struct net_device_path { -@@ -840,6 +841,7 @@ struct net_device_path { - struct { - u16 id; - __be16 proto; -+ u8 h_dest[ETH_ALEN]; - } encap; - struct { - enum { ---- a/include/linux/ppp_channel.h -+++ b/include/linux/ppp_channel.h -@@ -28,6 +28,9 @@ struct ppp_channel_ops { - int (*start_xmit)(struct ppp_channel *, struct sk_buff *); - /* Handle an ioctl call that has come in via /dev/ppp. */ - int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); -+ int (*fill_forward_path)(struct net_device_path_ctx *, -+ struct net_device_path *, -+ const struct ppp_channel *); - }; - - struct ppp_channel { diff --git a/target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch b/target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch deleted file mode 100644 index 1d3021a575..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-16-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch +++ /dev/null @@ -1,63 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:37 +0100 -Subject: [PATCH] net: dsa: resolve forwarding path for dsa slave ports - -Add .ndo_fill_forward_path for dsa slave port devices - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -832,6 +832,7 @@ enum net_device_path_type { - DEV_PATH_VLAN, - DEV_PATH_BRIDGE, - DEV_PATH_PPPOE, -+ DEV_PATH_DSA, - }; - - struct net_device_path { -@@ -852,6 +853,10 @@ struct net_device_path { - u16 vlan_id; - __be16 vlan_proto; - } bridge; -+ struct { -+ int port; -+ u16 proto; -+ } dsa; - }; - }; - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -1619,6 +1619,21 @@ static struct devlink_port *dsa_slave_ge - return dp->ds->devlink ? &dp->devlink_port : NULL; - } - -+static int dsa_slave_fill_forward_path(struct net_device_path_ctx *ctx, -+ struct net_device_path *path) -+{ -+ struct dsa_port *dp = dsa_slave_to_port(ctx->dev); -+ struct dsa_port *cpu_dp = dp->cpu_dp; -+ -+ path->dev = ctx->dev; -+ path->type = DEV_PATH_DSA; -+ path->dsa.proto = cpu_dp->tag_ops->proto; -+ path->dsa.port = dp->index; -+ ctx->dev = cpu_dp->master; -+ -+ return 0; -+} -+ - static const struct net_device_ops dsa_slave_netdev_ops = { - .ndo_open = dsa_slave_open, - .ndo_stop = dsa_slave_close, -@@ -1644,6 +1659,7 @@ static const struct net_device_ops dsa_s - .ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid, - .ndo_get_devlink_port = dsa_slave_get_devlink_port, - .ndo_change_mtu = dsa_slave_change_mtu, -+ .ndo_fill_forward_path = dsa_slave_fill_forward_path, - }; - - static struct device_type dsa_type = { diff --git a/target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch b/target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch deleted file mode 100644 index 6052f67faa..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-17-netfilter-flowtable-add-xmit-path-types.patch +++ /dev/null @@ -1,147 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:38 +0100 -Subject: [PATCH] netfilter: flowtable: add xmit path types - -Add the xmit_type field that defines the two supported xmit paths in the -flowtable data plane, which are the neighbour and the xfrm xmit paths. -This patch prepares for new flowtable xmit path types to come. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -89,6 +89,11 @@ enum flow_offload_tuple_dir { - }; - #define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX - -+enum flow_offload_xmit_type { -+ FLOW_OFFLOAD_XMIT_NEIGH = 0, -+ FLOW_OFFLOAD_XMIT_XFRM, -+}; -+ - struct flow_offload_tuple { - union { - struct in_addr src_v4; -@@ -111,7 +116,8 @@ struct flow_offload_tuple { - /* All members above are keys for lookups, see flow_offload_hash(). */ - struct { } __hash; - -- u8 dir; -+ u8 dir:6, -+ xmit_type:2; - - u16 mtu; - -@@ -157,7 +163,8 @@ static inline __s32 nf_flow_timeout_delt - - struct nf_flow_route { - struct { -- struct dst_entry *dst; -+ struct dst_entry *dst; -+ enum flow_offload_xmit_type xmit_type; - } tuple[FLOW_OFFLOAD_DIR_MAX]; - }; - ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -95,6 +95,7 @@ static int flow_offload_fill_route(struc - } - - flow_tuple->iifidx = other_dst->dev->ifindex; -+ flow_tuple->xmit_type = route->tuple[dir].xmit_type; - flow_tuple->dst_cache = dst; - - return 0; ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -235,8 +235,6 @@ nf_flow_offload_ip_hook(void *priv, stru - - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); -- rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache; -- outdev = rt->dst.dev; - - if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) - return NF_ACCEPT; -@@ -265,13 +263,16 @@ nf_flow_offload_ip_hook(void *priv, stru - if (flow_table->flags & NF_FLOWTABLE_COUNTER) - nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); - -- if (unlikely(dst_xfrm(&rt->dst))) { -+ rt = (struct rtable *)tuplehash->tuple.dst_cache; -+ -+ if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { - memset(skb->cb, 0, sizeof(struct inet_skb_parm)); - IPCB(skb)->iif = skb->dev->ifindex; - IPCB(skb)->flags = IPSKB_FORWARDED; - return nf_flow_xmit_xfrm(skb, state, &rt->dst); - } - -+ outdev = rt->dst.dev; - skb->dev = outdev; - nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); - skb_dst_set_noref(skb, &rt->dst); -@@ -456,8 +457,6 @@ nf_flow_offload_ipv6_hook(void *priv, st - - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); -- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; -- outdev = rt->dst.dev; - - if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) - return NF_ACCEPT; -@@ -485,13 +484,16 @@ nf_flow_offload_ipv6_hook(void *priv, st - if (flow_table->flags & NF_FLOWTABLE_COUNTER) - nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); - -- if (unlikely(dst_xfrm(&rt->dst))) { -+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; -+ -+ if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { - memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); - IP6CB(skb)->iif = skb->dev->ifindex; - IP6CB(skb)->flags = IP6SKB_FORWARDED; - return nf_flow_xmit_xfrm(skb, state, &rt->dst); - } - -+ outdev = rt->dst.dev; - skb->dev = outdev; - nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); - skb_dst_set_noref(skb, &rt->dst); ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -19,6 +19,22 @@ struct nft_flow_offload { - struct nft_flowtable *flowtable; - }; - -+static enum flow_offload_xmit_type nft_xmit_type(struct dst_entry *dst) -+{ -+ if (dst_xfrm(dst)) -+ return FLOW_OFFLOAD_XMIT_XFRM; -+ -+ return FLOW_OFFLOAD_XMIT_NEIGH; -+} -+ -+static void nft_default_forward_path(struct nf_flow_route *route, -+ struct dst_entry *dst_cache, -+ enum ip_conntrack_dir dir) -+{ -+ route->tuple[dir].dst = dst_cache; -+ route->tuple[dir].xmit_type = nft_xmit_type(dst_cache); -+} -+ - static int nft_flow_route(const struct nft_pktinfo *pkt, - const struct nf_conn *ct, - struct nf_flow_route *route, -@@ -44,8 +60,8 @@ static int nft_flow_route(const struct n - if (!other_dst) - return -ENOENT; - -- route->tuple[dir].dst = this_dst; -- route->tuple[!dir].dst = other_dst; -+ nft_default_forward_path(route, this_dst, dir); -+ nft_default_forward_path(route, other_dst, !dir); - - return 0; - } diff --git a/target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch b/target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch deleted file mode 100644 index 9541ce8867..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-18-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch +++ /dev/null @@ -1,191 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:39 +0100 -Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to - obtain ingress device - -Obtain the ingress device in the tuple from the route in the reply -direction. Use dev_fill_forward_path() instead to get the real ingress -device for this flow. - -Fall back to use the ingress device that the IP forwarding route -provides if: - -- dev_fill_forward_path() finds no real ingress device. -- the ingress device that is obtained is not part of the flowtable - devices. -- this route has a xfrm policy. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -164,6 +164,9 @@ static inline __s32 nf_flow_timeout_delt - struct nf_flow_route { - struct { - struct dst_entry *dst; -+ struct { -+ u32 ifindex; -+ } in; - enum flow_offload_xmit_type xmit_type; - } tuple[FLOW_OFFLOAD_DIR_MAX]; - }; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -79,7 +79,6 @@ static int flow_offload_fill_route(struc - enum flow_offload_tuple_dir dir) - { - struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; -- struct dst_entry *other_dst = route->tuple[!dir].dst; - struct dst_entry *dst = route->tuple[dir].dst; - - if (!dst_hold_safe(route->tuple[dir].dst)) -@@ -94,7 +93,7 @@ static int flow_offload_fill_route(struc - break; - } - -- flow_tuple->iifidx = other_dst->dev->ifindex; -+ flow_tuple->iifidx = route->tuple[dir].in.ifindex; - flow_tuple->xmit_type = route->tuple[dir].xmit_type; - flow_tuple->dst_cache = dst; - ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -31,14 +31,104 @@ static void nft_default_forward_path(str - struct dst_entry *dst_cache, - enum ip_conntrack_dir dir) - { -+ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex; - route->tuple[dir].dst = dst_cache; - route->tuple[dir].xmit_type = nft_xmit_type(dst_cache); - } - -+static int nft_dev_fill_forward_path(const struct nf_flow_route *route, -+ const struct dst_entry *dst_cache, -+ const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ struct net_device_path_stack *stack) -+{ -+ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; -+ struct net_device *dev = dst_cache->dev; -+ unsigned char ha[ETH_ALEN]; -+ struct neighbour *n; -+ u8 nud_state; -+ -+ n = dst_neigh_lookup(dst_cache, daddr); -+ if (!n) -+ return -1; -+ -+ read_lock_bh(&n->lock); -+ nud_state = n->nud_state; -+ ether_addr_copy(ha, n->ha); -+ read_unlock_bh(&n->lock); -+ neigh_release(n); -+ -+ if (!(nud_state & NUD_VALID)) -+ return -1; -+ -+ return dev_fill_forward_path(dev, ha, stack); -+} -+ -+struct nft_forward_info { -+ const struct net_device *indev; -+}; -+ -+static void nft_dev_path_info(const struct net_device_path_stack *stack, -+ struct nft_forward_info *info) -+{ -+ const struct net_device_path *path; -+ int i; -+ -+ for (i = 0; i < stack->num_paths; i++) { -+ path = &stack->path[i]; -+ switch (path->type) { -+ case DEV_PATH_ETHERNET: -+ info->indev = path->dev; -+ break; -+ case DEV_PATH_VLAN: -+ case DEV_PATH_BRIDGE: -+ default: -+ info->indev = NULL; -+ break; -+ } -+ } -+} -+ -+static bool nft_flowtable_find_dev(const struct net_device *dev, -+ struct nft_flowtable *ft) -+{ -+ struct nft_hook *hook; -+ bool found = false; -+ -+ list_for_each_entry_rcu(hook, &ft->hook_list, list) { -+ if (hook->ops.dev != dev) -+ continue; -+ -+ found = true; -+ break; -+ } -+ -+ return found; -+} -+ -+static void nft_dev_forward_path(struct nf_flow_route *route, -+ const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ struct nft_flowtable *ft) -+{ -+ const struct dst_entry *dst = route->tuple[dir].dst; -+ struct net_device_path_stack stack; -+ struct nft_forward_info info = {}; -+ -+ if (nft_dev_fill_forward_path(route, dst, ct, dir, &stack) >= 0) -+ nft_dev_path_info(&stack, &info); -+ -+ if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) -+ return; -+ -+ route->tuple[!dir].in.ifindex = info.indev->ifindex; -+} -+ - static int nft_flow_route(const struct nft_pktinfo *pkt, - const struct nf_conn *ct, - struct nf_flow_route *route, -- enum ip_conntrack_dir dir) -+ enum ip_conntrack_dir dir, -+ struct nft_flowtable *ft) - { - struct dst_entry *this_dst = skb_dst(pkt->skb); - struct dst_entry *other_dst = NULL; -@@ -63,6 +153,12 @@ static int nft_flow_route(const struct n - nft_default_forward_path(route, this_dst, dir); - nft_default_forward_path(route, other_dst, !dir); - -+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH && -+ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) { -+ nft_dev_forward_path(route, ct, dir, ft); -+ nft_dev_forward_path(route, ct, !dir, ft); -+ } -+ - return 0; - } - -@@ -90,8 +186,8 @@ static void nft_flow_offload_eval(const - struct nft_flow_offload *priv = nft_expr_priv(expr); - struct nf_flowtable *flowtable = &priv->flowtable->data; - struct tcphdr _tcph, *tcph = NULL; -+ struct nf_flow_route route = {}; - enum ip_conntrack_info ctinfo; -- struct nf_flow_route route; - struct flow_offload *flow; - enum ip_conntrack_dir dir; - struct nf_conn *ct; -@@ -128,7 +224,7 @@ static void nft_flow_offload_eval(const - goto out; - - dir = CTINFO2DIR(ctinfo); -- if (nft_flow_route(pkt, ct, &route, dir) < 0) -+ if (nft_flow_route(pkt, ct, &route, dir, priv->flowtable) < 0) - goto err_flow_route; - - flow = flow_offload_alloc(ct); diff --git a/target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch b/target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch deleted file mode 100644 index 457e218d9b..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-19-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch +++ /dev/null @@ -1,374 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:40 +0100 -Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to - obtain egress device - -The egress device in the tuple is obtained from route. Use -dev_fill_forward_path() instead to provide the real egress device for -this flow whenever this is available. - -The new FLOW_OFFLOAD_XMIT_DIRECT type uses dev_queue_xmit() to transmit -ethernet frames. Cache the source and destination hardware address to -use dev_queue_xmit() to transfer packets. - -The FLOW_OFFLOAD_XMIT_DIRECT replaces FLOW_OFFLOAD_XMIT_NEIGH if -dev_fill_forward_path() finds a direct transmit path. - -In case of topology updates, if peer is moved to different bridge port, -the connection will time out, reconnect will result in a new entry with -the correct path. Snooping fdb updates would allow for cleaning up stale -flowtable entries. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -92,6 +92,7 @@ enum flow_offload_tuple_dir { - enum flow_offload_xmit_type { - FLOW_OFFLOAD_XMIT_NEIGH = 0, - FLOW_OFFLOAD_XMIT_XFRM, -+ FLOW_OFFLOAD_XMIT_DIRECT, - }; - - struct flow_offload_tuple { -@@ -120,8 +121,14 @@ struct flow_offload_tuple { - xmit_type:2; - - u16 mtu; -- -- struct dst_entry *dst_cache; -+ union { -+ struct dst_entry *dst_cache; -+ struct { -+ u32 ifidx; -+ u8 h_source[ETH_ALEN]; -+ u8 h_dest[ETH_ALEN]; -+ } out; -+ }; - }; - - struct flow_offload_tuple_rhash { -@@ -167,6 +174,11 @@ struct nf_flow_route { - struct { - u32 ifindex; - } in; -+ struct { -+ u32 ifindex; -+ u8 h_source[ETH_ALEN]; -+ u8 h_dest[ETH_ALEN]; -+ } out; - enum flow_offload_xmit_type xmit_type; - } tuple[FLOW_OFFLOAD_DIR_MAX]; - }; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -81,9 +81,6 @@ static int flow_offload_fill_route(struc - struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; - struct dst_entry *dst = route->tuple[dir].dst; - -- if (!dst_hold_safe(route->tuple[dir].dst)) -- return -1; -- - switch (flow_tuple->l3proto) { - case NFPROTO_IPV4: - flow_tuple->mtu = ip_dst_mtu_maybe_forward(dst, true); -@@ -94,12 +91,36 @@ static int flow_offload_fill_route(struc - } - - flow_tuple->iifidx = route->tuple[dir].in.ifindex; -+ -+ switch (route->tuple[dir].xmit_type) { -+ case FLOW_OFFLOAD_XMIT_DIRECT: -+ memcpy(flow_tuple->out.h_dest, route->tuple[dir].out.h_dest, -+ ETH_ALEN); -+ memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source, -+ ETH_ALEN); -+ flow_tuple->out.ifidx = route->tuple[dir].out.ifindex; -+ break; -+ case FLOW_OFFLOAD_XMIT_XFRM: -+ case FLOW_OFFLOAD_XMIT_NEIGH: -+ if (!dst_hold_safe(route->tuple[dir].dst)) -+ return -1; -+ -+ flow_tuple->dst_cache = dst; -+ break; -+ } - flow_tuple->xmit_type = route->tuple[dir].xmit_type; -- flow_tuple->dst_cache = dst; - - return 0; - } - -+static void nft_flow_dst_release(struct flow_offload *flow, -+ enum flow_offload_tuple_dir dir) -+{ -+ if (flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -+ flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) -+ dst_release(flow->tuplehash[dir].tuple.dst_cache); -+} -+ - int flow_offload_route_init(struct flow_offload *flow, - const struct nf_flow_route *route) - { -@@ -118,7 +139,7 @@ int flow_offload_route_init(struct flow_ - return 0; - - err_route_reply: -- dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); -+ nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_ORIGINAL); - - return err; - } -@@ -169,8 +190,8 @@ static void flow_offload_fixup_ct(struct - - static void flow_offload_route_release(struct flow_offload *flow) - { -- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); -- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); -+ nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_ORIGINAL); -+ nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_REPLY); - } - - void flow_offload_free(struct flow_offload *flow) ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -207,6 +207,24 @@ static unsigned int nf_flow_xmit_xfrm(st - return NF_STOLEN; - } - -+static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, -+ const struct flow_offload_tuple_rhash *tuplehash, -+ unsigned short type) -+{ -+ struct net_device *outdev; -+ -+ outdev = dev_get_by_index_rcu(net, tuplehash->tuple.out.ifidx); -+ if (!outdev) -+ return NF_DROP; -+ -+ skb->dev = outdev; -+ dev_hard_header(skb, skb->dev, type, tuplehash->tuple.out.h_dest, -+ tuplehash->tuple.out.h_source, skb->len); -+ dev_queue_xmit(skb); -+ -+ return NF_STOLEN; -+} -+ - unsigned int - nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state) -@@ -222,6 +240,7 @@ nf_flow_offload_ip_hook(void *priv, stru - struct iphdr *iph; - __be32 nexthop; - u32 hdrsize; -+ int ret; - - if (skb->protocol != htons(ETH_P_IP)) - return NF_ACCEPT; -@@ -244,9 +263,13 @@ nf_flow_offload_ip_hook(void *priv, stru - if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) - return NF_ACCEPT; - -- if (!dst_check(&rt->dst, 0)) { -- flow_offload_teardown(flow); -- return NF_ACCEPT; -+ if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -+ tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { -+ rt = (struct rtable *)tuplehash->tuple.dst_cache; -+ if (!dst_check(&rt->dst, 0)) { -+ flow_offload_teardown(flow); -+ return NF_ACCEPT; -+ } - } - - if (skb_try_make_writable(skb, thoff + hdrsize)) -@@ -263,8 +286,6 @@ nf_flow_offload_ip_hook(void *priv, stru - if (flow_table->flags & NF_FLOWTABLE_COUNTER) - nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); - -- rt = (struct rtable *)tuplehash->tuple.dst_cache; -- - if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { - memset(skb->cb, 0, sizeof(struct inet_skb_parm)); - IPCB(skb)->iif = skb->dev->ifindex; -@@ -272,13 +293,23 @@ nf_flow_offload_ip_hook(void *priv, stru - return nf_flow_xmit_xfrm(skb, state, &rt->dst); - } - -- outdev = rt->dst.dev; -- skb->dev = outdev; -- nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); -- skb_dst_set_noref(skb, &rt->dst); -- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); -+ switch (tuplehash->tuple.xmit_type) { -+ case FLOW_OFFLOAD_XMIT_NEIGH: -+ outdev = rt->dst.dev; -+ skb->dev = outdev; -+ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); -+ skb_dst_set_noref(skb, &rt->dst); -+ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); -+ ret = NF_STOLEN; -+ break; -+ case FLOW_OFFLOAD_XMIT_DIRECT: -+ ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IP); -+ if (ret == NF_DROP) -+ flow_offload_teardown(flow); -+ break; -+ } - -- return NF_STOLEN; -+ return ret; - } - EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); - -@@ -444,6 +475,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - struct ipv6hdr *ip6h; - struct rt6_info *rt; - u32 hdrsize; -+ int ret; - - if (skb->protocol != htons(ETH_P_IPV6)) - return NF_ACCEPT; -@@ -465,9 +497,13 @@ nf_flow_offload_ipv6_hook(void *priv, st - sizeof(*ip6h))) - return NF_ACCEPT; - -- if (!dst_check(&rt->dst, 0)) { -- flow_offload_teardown(flow); -- return NF_ACCEPT; -+ if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -+ tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { -+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; -+ if (!dst_check(&rt->dst, 0)) { -+ flow_offload_teardown(flow); -+ return NF_ACCEPT; -+ } - } - - if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) -@@ -484,8 +520,6 @@ nf_flow_offload_ipv6_hook(void *priv, st - if (flow_table->flags & NF_FLOWTABLE_COUNTER) - nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); - -- rt = (struct rt6_info *)tuplehash->tuple.dst_cache; -- - if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { - memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); - IP6CB(skb)->iif = skb->dev->ifindex; -@@ -493,12 +527,22 @@ nf_flow_offload_ipv6_hook(void *priv, st - return nf_flow_xmit_xfrm(skb, state, &rt->dst); - } - -- outdev = rt->dst.dev; -- skb->dev = outdev; -- nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); -- skb_dst_set_noref(skb, &rt->dst); -- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); -+ switch (tuplehash->tuple.xmit_type) { -+ case FLOW_OFFLOAD_XMIT_NEIGH: -+ outdev = rt->dst.dev; -+ skb->dev = outdev; -+ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); -+ skb_dst_set_noref(skb, &rt->dst); -+ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); -+ ret = NF_STOLEN; -+ break; -+ case FLOW_OFFLOAD_XMIT_DIRECT: -+ ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IPV6); -+ if (ret == NF_DROP) -+ flow_offload_teardown(flow); -+ break; -+ } - -- return NF_STOLEN; -+ return ret; - } - EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -39,12 +39,11 @@ static void nft_default_forward_path(str - static int nft_dev_fill_forward_path(const struct nf_flow_route *route, - const struct dst_entry *dst_cache, - const struct nf_conn *ct, -- enum ip_conntrack_dir dir, -+ enum ip_conntrack_dir dir, u8 *ha, - struct net_device_path_stack *stack) - { - const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; - struct net_device *dev = dst_cache->dev; -- unsigned char ha[ETH_ALEN]; - struct neighbour *n; - u8 nud_state; - -@@ -66,27 +65,43 @@ static int nft_dev_fill_forward_path(con - - struct nft_forward_info { - const struct net_device *indev; -+ const struct net_device *outdev; -+ u8 h_source[ETH_ALEN]; -+ u8 h_dest[ETH_ALEN]; -+ enum flow_offload_xmit_type xmit_type; - }; - - static void nft_dev_path_info(const struct net_device_path_stack *stack, -- struct nft_forward_info *info) -+ struct nft_forward_info *info, -+ unsigned char *ha) - { - const struct net_device_path *path; - int i; - -+ memcpy(info->h_dest, ha, ETH_ALEN); -+ - for (i = 0; i < stack->num_paths; i++) { - path = &stack->path[i]; - switch (path->type) { - case DEV_PATH_ETHERNET: - info->indev = path->dev; -+ if (is_zero_ether_addr(info->h_source)) -+ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); - break; -- case DEV_PATH_VLAN: - case DEV_PATH_BRIDGE: -+ if (is_zero_ether_addr(info->h_source)) -+ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); -+ -+ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; -+ break; -+ case DEV_PATH_VLAN: - default: - info->indev = NULL; - break; - } - } -+ if (!info->outdev) -+ info->outdev = info->indev; - } - - static bool nft_flowtable_find_dev(const struct net_device *dev, -@@ -114,14 +129,22 @@ static void nft_dev_forward_path(struct - const struct dst_entry *dst = route->tuple[dir].dst; - struct net_device_path_stack stack; - struct nft_forward_info info = {}; -+ unsigned char ha[ETH_ALEN]; - -- if (nft_dev_fill_forward_path(route, dst, ct, dir, &stack) >= 0) -- nft_dev_path_info(&stack, &info); -+ if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) -+ nft_dev_path_info(&stack, &info, ha); - - if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) - return; - - route->tuple[!dir].in.ifindex = info.indev->ifindex; -+ -+ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { -+ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); -+ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); -+ route->tuple[dir].out.ifindex = info.outdev->ifindex; -+ route->tuple[dir].xmit_type = info.xmit_type; -+ } - } - - static int nft_flow_route(const struct nft_pktinfo *pkt, diff --git a/target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch b/target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch deleted file mode 100644 index 86a1129880..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-20-netfilter-flowtable-add-vlan-support.patch +++ /dev/null @@ -1,410 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:41 +0100 -Subject: [PATCH] netfilter: flowtable: add vlan support - -Add the vlan id and protocol to the flow tuple to uniquely identify -flows from the receive path. For the transmit path, dev_hard_header() on -the vlan device push the headers. This patch includes support for two -vlan headers (QinQ) from the ingress path. - -Add a generic encap field to the flowtable entry which stores the -protocol and the tag id. This allows to reuse these fields in the PPPoE -support coming in a later patch. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -95,6 +95,8 @@ enum flow_offload_xmit_type { - FLOW_OFFLOAD_XMIT_DIRECT, - }; - -+#define NF_FLOW_TABLE_ENCAP_MAX 2 -+ - struct flow_offload_tuple { - union { - struct in_addr src_v4; -@@ -113,13 +115,17 @@ struct flow_offload_tuple { - - u8 l3proto; - u8 l4proto; -+ struct { -+ u16 id; -+ __be16 proto; -+ } encap[NF_FLOW_TABLE_ENCAP_MAX]; - - /* All members above are keys for lookups, see flow_offload_hash(). */ - struct { } __hash; - -- u8 dir:6, -- xmit_type:2; -- -+ u8 dir:4, -+ xmit_type:2, -+ encap_num:2; - u16 mtu; - union { - struct dst_entry *dst_cache; -@@ -173,6 +179,11 @@ struct nf_flow_route { - struct dst_entry *dst; - struct { - u32 ifindex; -+ struct { -+ u16 id; -+ __be16 proto; -+ } encap[NF_FLOW_TABLE_ENCAP_MAX]; -+ u8 num_encaps; - } in; - struct { - u32 ifindex; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -80,6 +80,7 @@ static int flow_offload_fill_route(struc - { - struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; - struct dst_entry *dst = route->tuple[dir].dst; -+ int i, j = 0; - - switch (flow_tuple->l3proto) { - case NFPROTO_IPV4: -@@ -91,6 +92,12 @@ static int flow_offload_fill_route(struc - } - - flow_tuple->iifidx = route->tuple[dir].in.ifindex; -+ for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) { -+ flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id; -+ flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto; -+ j++; -+ } -+ flow_tuple->encap_num = route->tuple[dir].in.num_encaps; - - switch (route->tuple[dir].xmit_type) { - case FLOW_OFFLOAD_XMIT_DIRECT: ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -136,23 +136,44 @@ static bool ip_has_options(unsigned int - return thoff != sizeof(struct iphdr); - } - -+static void nf_flow_tuple_encap(struct sk_buff *skb, -+ struct flow_offload_tuple *tuple) -+{ -+ int i = 0; -+ -+ if (skb_vlan_tag_present(skb)) { -+ tuple->encap[i].id = skb_vlan_tag_get(skb); -+ tuple->encap[i].proto = skb->vlan_proto; -+ i++; -+ } -+ if (skb->protocol == htons(ETH_P_8021Q)) { -+ struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); -+ -+ tuple->encap[i].id = ntohs(veth->h_vlan_TCI); -+ tuple->encap[i].proto = skb->protocol; -+ } -+} -+ - static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, -- struct flow_offload_tuple *tuple, u32 *hdrsize) -+ struct flow_offload_tuple *tuple, u32 *hdrsize, -+ u32 offset) - { - struct flow_ports *ports; - unsigned int thoff; - struct iphdr *iph; - -- if (!pskb_may_pull(skb, sizeof(*iph))) -+ if (!pskb_may_pull(skb, sizeof(*iph) + offset)) - return -1; - -- iph = ip_hdr(skb); -- thoff = iph->ihl * 4; -+ iph = (struct iphdr *)(skb_network_header(skb) + offset); -+ thoff = (iph->ihl * 4); - - if (ip_is_fragment(iph) || - unlikely(ip_has_options(thoff))) - return -1; - -+ thoff += offset; -+ - switch (iph->protocol) { - case IPPROTO_TCP: - *hdrsize = sizeof(struct tcphdr); -@@ -167,11 +188,10 @@ static int nf_flow_tuple_ip(struct sk_bu - if (iph->ttl <= 1) - return -1; - -- thoff = iph->ihl * 4; - if (!pskb_may_pull(skb, thoff + *hdrsize)) - return -1; - -- iph = ip_hdr(skb); -+ iph = (struct iphdr *)(skb_network_header(skb) + offset); - ports = (struct flow_ports *)(skb_network_header(skb) + thoff); - - tuple->src_v4.s_addr = iph->saddr; -@@ -181,6 +201,7 @@ static int nf_flow_tuple_ip(struct sk_bu - tuple->l3proto = AF_INET; - tuple->l4proto = iph->protocol; - tuple->iifidx = dev->ifindex; -+ nf_flow_tuple_encap(skb, tuple); - - return 0; - } -@@ -207,6 +228,43 @@ static unsigned int nf_flow_xmit_xfrm(st - return NF_STOLEN; - } - -+static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto, -+ u32 *offset) -+{ -+ if (skb->protocol == htons(ETH_P_8021Q)) { -+ struct vlan_ethhdr *veth; -+ -+ veth = (struct vlan_ethhdr *)skb_mac_header(skb); -+ if (veth->h_vlan_encapsulated_proto == proto) { -+ *offset += VLAN_HLEN; -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static void nf_flow_encap_pop(struct sk_buff *skb, -+ struct flow_offload_tuple_rhash *tuplehash) -+{ -+ struct vlan_hdr *vlan_hdr; -+ int i; -+ -+ for (i = 0; i < tuplehash->tuple.encap_num; i++) { -+ if (skb_vlan_tag_present(skb)) { -+ __vlan_hwaccel_clear_tag(skb); -+ continue; -+ } -+ if (skb->protocol == htons(ETH_P_8021Q)) { -+ vlan_hdr = (struct vlan_hdr *)skb->data; -+ __skb_pull(skb, VLAN_HLEN); -+ vlan_set_encap_proto(skb, vlan_hdr); -+ skb_reset_network_header(skb); -+ break; -+ } -+ } -+} -+ - static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, - const struct flow_offload_tuple_rhash *tuplehash, - unsigned short type) -@@ -235,17 +293,18 @@ nf_flow_offload_ip_hook(void *priv, stru - enum flow_offload_tuple_dir dir; - struct flow_offload *flow; - struct net_device *outdev; -+ u32 hdrsize, offset = 0; -+ unsigned int thoff, mtu; - struct rtable *rt; -- unsigned int thoff; - struct iphdr *iph; - __be32 nexthop; -- u32 hdrsize; - int ret; - -- if (skb->protocol != htons(ETH_P_IP)) -+ if (skb->protocol != htons(ETH_P_IP) && -+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP), &offset)) - return NF_ACCEPT; - -- if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize) < 0) -+ if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize, offset) < 0) - return NF_ACCEPT; - - tuplehash = flow_offload_lookup(flow_table, &tuple); -@@ -255,11 +314,12 @@ nf_flow_offload_ip_hook(void *priv, stru - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - -- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) -+ mtu = flow->tuplehash[dir].tuple.mtu + offset; -+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) - return NF_ACCEPT; - -- iph = ip_hdr(skb); -- thoff = iph->ihl * 4; -+ iph = (struct iphdr *)(skb_network_header(skb) + offset); -+ thoff = (iph->ihl * 4) + offset; - if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) - return NF_ACCEPT; - -@@ -277,6 +337,9 @@ nf_flow_offload_ip_hook(void *priv, stru - - flow_offload_refresh(flow_table, flow); - -+ nf_flow_encap_pop(skb, tuplehash); -+ thoff -= offset; -+ - iph = ip_hdr(skb); - nf_flow_nat_ip(flow, skb, thoff, dir, iph); - -@@ -418,16 +481,18 @@ static void nf_flow_nat_ipv6(const struc - } - - static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, -- struct flow_offload_tuple *tuple, u32 *hdrsize) -+ struct flow_offload_tuple *tuple, u32 *hdrsize, -+ u32 offset) - { - struct flow_ports *ports; - struct ipv6hdr *ip6h; - unsigned int thoff; - -- if (!pskb_may_pull(skb, sizeof(*ip6h))) -+ thoff = sizeof(*ip6h) + offset; -+ if (!pskb_may_pull(skb, thoff)) - return -1; - -- ip6h = ipv6_hdr(skb); -+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); - - switch (ip6h->nexthdr) { - case IPPROTO_TCP: -@@ -443,11 +508,10 @@ static int nf_flow_tuple_ipv6(struct sk_ - if (ip6h->hop_limit <= 1) - return -1; - -- thoff = sizeof(*ip6h); - if (!pskb_may_pull(skb, thoff + *hdrsize)) - return -1; - -- ip6h = ipv6_hdr(skb); -+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); - ports = (struct flow_ports *)(skb_network_header(skb) + thoff); - - tuple->src_v6 = ip6h->saddr; -@@ -457,6 +521,7 @@ static int nf_flow_tuple_ipv6(struct sk_ - tuple->l3proto = AF_INET6; - tuple->l4proto = ip6h->nexthdr; - tuple->iifidx = dev->ifindex; -+ nf_flow_tuple_encap(skb, tuple); - - return 0; - } -@@ -472,15 +537,17 @@ nf_flow_offload_ipv6_hook(void *priv, st - const struct in6_addr *nexthop; - struct flow_offload *flow; - struct net_device *outdev; -+ unsigned int thoff, mtu; -+ u32 hdrsize, offset = 0; - struct ipv6hdr *ip6h; - struct rt6_info *rt; -- u32 hdrsize; - int ret; - -- if (skb->protocol != htons(ETH_P_IPV6)) -+ if (skb->protocol != htons(ETH_P_IPV6) && -+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6), &offset)) - return NF_ACCEPT; - -- if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize) < 0) -+ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize, offset) < 0) - return NF_ACCEPT; - - tuplehash = flow_offload_lookup(flow_table, &tuple); -@@ -490,11 +557,13 @@ nf_flow_offload_ipv6_hook(void *priv, st - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - -- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) -+ mtu = flow->tuplehash[dir].tuple.mtu + offset; -+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) - return NF_ACCEPT; - -- if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb, -- sizeof(*ip6h))) -+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); -+ thoff = sizeof(*ip6h) + offset; -+ if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff)) - return NF_ACCEPT; - - if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -@@ -506,11 +575,13 @@ nf_flow_offload_ipv6_hook(void *priv, st - } - } - -- if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize)) -+ if (skb_try_make_writable(skb, thoff + hdrsize)) - return NF_DROP; - - flow_offload_refresh(flow_table, flow); - -+ nf_flow_encap_pop(skb, tuplehash); -+ - ip6h = ipv6_hdr(skb); - nf_flow_nat_ipv6(flow, skb, dir, ip6h); - ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -66,6 +66,11 @@ static int nft_dev_fill_forward_path(con - struct nft_forward_info { - const struct net_device *indev; - const struct net_device *outdev; -+ struct id { -+ __u16 id; -+ __be16 proto; -+ } encap[NF_FLOW_TABLE_ENCAP_MAX]; -+ u8 num_encaps; - u8 h_source[ETH_ALEN]; - u8 h_dest[ETH_ALEN]; - enum flow_offload_xmit_type xmit_type; -@@ -84,9 +89,23 @@ static void nft_dev_path_info(const stru - path = &stack->path[i]; - switch (path->type) { - case DEV_PATH_ETHERNET: -+ case DEV_PATH_VLAN: - info->indev = path->dev; - if (is_zero_ether_addr(info->h_source)) - memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); -+ -+ if (path->type == DEV_PATH_ETHERNET) -+ break; -+ -+ /* DEV_PATH_VLAN */ -+ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { -+ info->indev = NULL; -+ break; -+ } -+ info->outdev = path->dev; -+ info->encap[info->num_encaps].id = path->encap.id; -+ info->encap[info->num_encaps].proto = path->encap.proto; -+ info->num_encaps++; - break; - case DEV_PATH_BRIDGE: - if (is_zero_ether_addr(info->h_source)) -@@ -94,7 +113,6 @@ static void nft_dev_path_info(const stru - - info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; - break; -- case DEV_PATH_VLAN: - default: - info->indev = NULL; - break; -@@ -130,6 +148,7 @@ static void nft_dev_forward_path(struct - struct net_device_path_stack stack; - struct nft_forward_info info = {}; - unsigned char ha[ETH_ALEN]; -+ int i; - - if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) - nft_dev_path_info(&stack, &info, ha); -@@ -138,6 +157,11 @@ static void nft_dev_forward_path(struct - return; - - route->tuple[!dir].in.ifindex = info.indev->ifindex; -+ for (i = 0; i < info.num_encaps; i++) { -+ route->tuple[!dir].in.encap[i].id = info.encap[i].id; -+ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; -+ } -+ route->tuple[!dir].in.num_encaps = info.num_encaps; - - if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { - memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); diff --git a/target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch b/target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch deleted file mode 100644 index cb3ef99029..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-21-netfilter-flowtable-add-bridge-vlan-filtering-suppor.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:42 +0100 -Subject: [PATCH] netfilter: flowtable: add bridge vlan filtering support - -Add the vlan tag based when PVID is set on. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -111,6 +111,18 @@ static void nft_dev_path_info(const stru - if (is_zero_ether_addr(info->h_source)) - memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); - -+ switch (path->bridge.vlan_mode) { -+ case DEV_PATH_BR_VLAN_TAG: -+ info->encap[info->num_encaps].id = path->bridge.vlan_id; -+ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; -+ info->num_encaps++; -+ break; -+ case DEV_PATH_BR_VLAN_UNTAG: -+ info->num_encaps--; -+ break; -+ case DEV_PATH_BR_VLAN_KEEP: -+ break; -+ } - info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; - break; - default: diff --git a/target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch b/target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch deleted file mode 100644 index d5789cbad2..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-22-netfilter-flowtable-add-pppoe-support.patch +++ /dev/null @@ -1,145 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:43 +0100 -Subject: [PATCH] netfilter: flowtable: add pppoe support - -Add the PPPoE protocol and session id to the flow tuple using the encap -fields to uniquely identify flows from the receive path. For the -transmit path, dev_hard_header() on the vlan device push the headers. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -7,6 +7,9 @@ - #include - #include - #include -+#include -+#include -+#include - #include - #include - #include -@@ -139,6 +142,8 @@ static bool ip_has_options(unsigned int - static void nf_flow_tuple_encap(struct sk_buff *skb, - struct flow_offload_tuple *tuple) - { -+ struct vlan_ethhdr *veth; -+ struct pppoe_hdr *phdr; - int i = 0; - - if (skb_vlan_tag_present(skb)) { -@@ -146,11 +151,17 @@ static void nf_flow_tuple_encap(struct s - tuple->encap[i].proto = skb->vlan_proto; - i++; - } -- if (skb->protocol == htons(ETH_P_8021Q)) { -- struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); -- -+ switch (skb->protocol) { -+ case htons(ETH_P_8021Q): -+ veth = (struct vlan_ethhdr *)skb_mac_header(skb); - tuple->encap[i].id = ntohs(veth->h_vlan_TCI); - tuple->encap[i].proto = skb->protocol; -+ break; -+ case htons(ETH_P_PPP_SES): -+ phdr = (struct pppoe_hdr *)skb_mac_header(skb); -+ tuple->encap[i].id = ntohs(phdr->sid); -+ tuple->encap[i].proto = skb->protocol; -+ break; - } - } - -@@ -228,17 +239,41 @@ static unsigned int nf_flow_xmit_xfrm(st - return NF_STOLEN; - } - -+static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) -+{ -+ __be16 proto; -+ -+ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN + -+ sizeof(struct pppoe_hdr))); -+ switch (proto) { -+ case htons(PPP_IP): -+ return htons(ETH_P_IP); -+ case htons(PPP_IPV6): -+ return htons(ETH_P_IPV6); -+ } -+ -+ return 0; -+} -+ - static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto, - u32 *offset) - { -- if (skb->protocol == htons(ETH_P_8021Q)) { -- struct vlan_ethhdr *veth; -+ struct vlan_ethhdr *veth; - -+ switch (skb->protocol) { -+ case htons(ETH_P_8021Q): - veth = (struct vlan_ethhdr *)skb_mac_header(skb); - if (veth->h_vlan_encapsulated_proto == proto) { - *offset += VLAN_HLEN; - return true; - } -+ break; -+ case htons(ETH_P_PPP_SES): -+ if (nf_flow_pppoe_proto(skb) == proto) { -+ *offset += PPPOE_SES_HLEN; -+ return true; -+ } -+ break; - } - - return false; -@@ -255,12 +290,18 @@ static void nf_flow_encap_pop(struct sk_ - __vlan_hwaccel_clear_tag(skb); - continue; - } -- if (skb->protocol == htons(ETH_P_8021Q)) { -+ switch (skb->protocol) { -+ case htons(ETH_P_8021Q): - vlan_hdr = (struct vlan_hdr *)skb->data; - __skb_pull(skb, VLAN_HLEN); - vlan_set_encap_proto(skb, vlan_hdr); - skb_reset_network_header(skb); - break; -+ case htons(ETH_P_PPP_SES): -+ skb->protocol = nf_flow_pppoe_proto(skb); -+ skb_pull(skb, PPPOE_SES_HLEN); -+ skb_reset_network_header(skb); -+ break; - } - } - } ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -90,6 +90,7 @@ static void nft_dev_path_info(const stru - switch (path->type) { - case DEV_PATH_ETHERNET: - case DEV_PATH_VLAN: -+ case DEV_PATH_PPPOE: - info->indev = path->dev; - if (is_zero_ether_addr(info->h_source)) - memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); -@@ -97,7 +98,7 @@ static void nft_dev_path_info(const stru - if (path->type == DEV_PATH_ETHERNET) - break; - -- /* DEV_PATH_VLAN */ -+ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ - if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { - info->indev = NULL; - break; -@@ -106,6 +107,8 @@ static void nft_dev_path_info(const stru - info->encap[info->num_encaps].id = path->encap.id; - info->encap[info->num_encaps].proto = path->encap.proto; - info->num_encaps++; -+ if (path->type == DEV_PATH_PPPOE) -+ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); - break; - case DEV_PATH_BRIDGE: - if (is_zero_ether_addr(info->h_source)) diff --git a/target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch b/target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch deleted file mode 100644 index b4931830d3..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-23-netfilter-flowtable-add-dsa-support.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:44 +0100 -Subject: [PATCH] netfilter: flowtable: add dsa support - -Replace the master ethernet device by the dsa slave port. Packets coming -in from the software ingress path use the dsa slave port as input -device. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -89,6 +89,7 @@ static void nft_dev_path_info(const stru - path = &stack->path[i]; - switch (path->type) { - case DEV_PATH_ETHERNET: -+ case DEV_PATH_DSA: - case DEV_PATH_VLAN: - case DEV_PATH_PPPOE: - info->indev = path->dev; -@@ -97,6 +98,10 @@ static void nft_dev_path_info(const stru - - if (path->type == DEV_PATH_ETHERNET) - break; -+ if (path->type == DEV_PATH_DSA) { -+ i = stack->num_paths; -+ break; -+ } - - /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ - if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { diff --git a/target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch b/target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch deleted file mode 100644 index 3f332c70d3..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-24-selftests-netfilter-flowtable-bridge-and-vlan-suppor.patch +++ /dev/null @@ -1,107 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:45 +0100 -Subject: [PATCH] selftests: netfilter: flowtable bridge and vlan support - -This patch adds two new tests to cover bridge and vlan support: - -- Add a bridge device to the Router1 (nsr1) container and attach the - veth0 device to the bridge. Set the IP address to the bridge device - to exercise the bridge forwarding path. - -- Add vlan encapsulation between to the bridge device in the Router1 and - one of the sender containers (ns1). - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/tools/testing/selftests/netfilter/nft_flowtable.sh -+++ b/tools/testing/selftests/netfilter/nft_flowtable.sh -@@ -370,6 +370,88 @@ else - ip netns exec nsr1 nft list ruleset - fi - -+# Another test: -+# Add bridge interface br0 to Router1, with NAT enabled. -+ip -net nsr1 link add name br0 type bridge -+ip -net nsr1 addr flush dev veth0 -+ip -net nsr1 link set up dev veth0 -+ip -net nsr1 link set veth0 master br0 -+ip -net nsr1 addr add 10.0.1.1/24 dev br0 -+ip -net nsr1 addr add dead:1::1/64 dev br0 -+ip -net nsr1 link set up dev br0 -+ -+ip netns exec nsr1 sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null -+ -+# br0 with NAT enabled. -+ip netns exec nsr1 nft -f - <&2 -+ ip netns exec nsr1 nft list ruleset -+ ret=1 -+fi -+ -+# Another test: -+# Add bridge interface br0 to Router1, with NAT and VLAN. -+ip -net nsr1 link set veth0 nomaster -+ip -net nsr1 link set down dev veth0 -+ip -net nsr1 link add link veth0 name veth0.10 type vlan id 10 -+ip -net nsr1 link set up dev veth0 -+ip -net nsr1 link set up dev veth0.10 -+ip -net nsr1 link set veth0.10 master br0 -+ -+ip -net ns1 addr flush dev eth0 -+ip -net ns1 link add link eth0 name eth0.10 type vlan id 10 -+ip -net ns1 link set eth0 up -+ip -net ns1 link set eth0.10 up -+ip -net ns1 addr add 10.0.1.99/24 dev eth0.10 -+ip -net ns1 route add default via 10.0.1.1 -+ip -net ns1 addr add dead:1::99/64 dev eth0.10 -+ -+if test_tcp_forwarding_nat ns1 ns2; then -+ echo "PASS: flow offloaded for ns1/ns2 with bridge NAT and VLAN" -+else -+ echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2 -+ ip netns exec nsr1 nft list ruleset -+ ret=1 -+fi -+ -+# restore test topology (remove bridge and VLAN) -+ip -net nsr1 link set veth0 nomaster -+ip -net nsr1 link set veth0 down -+ip -net nsr1 link set veth0.10 down -+ip -net nsr1 link delete veth0.10 type vlan -+ip -net nsr1 link delete br0 type bridge -+ip -net ns1 addr flush dev eth0.10 -+ip -net ns1 link set eth0.10 down -+ip -net ns1 link set eth0 down -+ip -net ns1 link delete eth0.10 type vlan -+ -+# restore address in ns1 and nsr1 -+ip -net ns1 link set eth0 up -+ip -net ns1 addr add 10.0.1.99/24 dev eth0 -+ip -net ns1 route add default via 10.0.1.1 -+ip -net ns1 addr add dead:1::99/64 dev eth0 -+ip -net ns1 route add default via dead:1::1 -+ip -net nsr1 addr add 10.0.1.1/24 dev veth0 -+ip -net nsr1 addr add dead:1::1/64 dev veth0 -+ip -net nsr1 link set up dev veth0 -+ - KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1) - KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1) - SPI1=$RANDOM diff --git a/target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch b/target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch deleted file mode 100644 index 7b6ec68d55..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-25-netfilter-flowtable-add-offload-support-for-xmit-pat.patch +++ /dev/null @@ -1,310 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:46 +0100 -Subject: [PATCH] netfilter: flowtable: add offload support for xmit path - types - -When the flow tuple xmit_type is set to FLOW_OFFLOAD_XMIT_DIRECT, the -dst_cache pointer is not valid, and the h_source/h_dest/ifidx out fields -need to be used. - -This patch also adds the FLOW_ACTION_VLAN_PUSH action to pass the VLAN -tag to the driver. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -177,28 +177,45 @@ static int flow_offload_eth_src(struct n - enum flow_offload_tuple_dir dir, - struct nf_flow_rule *flow_rule) - { -- const struct flow_offload_tuple *tuple = &flow->tuplehash[!dir].tuple; - struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule); - struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule); -- struct net_device *dev; -+ const struct flow_offload_tuple *other_tuple, *this_tuple; -+ struct net_device *dev = NULL; -+ const unsigned char *addr; - u32 mask, val; - u16 val16; - -- dev = dev_get_by_index(net, tuple->iifidx); -- if (!dev) -- return -ENOENT; -+ this_tuple = &flow->tuplehash[dir].tuple; -+ -+ switch (this_tuple->xmit_type) { -+ case FLOW_OFFLOAD_XMIT_DIRECT: -+ addr = this_tuple->out.h_source; -+ break; -+ case FLOW_OFFLOAD_XMIT_NEIGH: -+ other_tuple = &flow->tuplehash[!dir].tuple; -+ dev = dev_get_by_index(net, other_tuple->iifidx); -+ if (!dev) -+ return -ENOENT; -+ -+ addr = dev->dev_addr; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } - - mask = ~0xffff0000; -- memcpy(&val16, dev->dev_addr, 2); -+ memcpy(&val16, addr, 2); - val = val16 << 16; - flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4, - &val, &mask); - - mask = ~0xffffffff; -- memcpy(&val, dev->dev_addr + 2, 4); -+ memcpy(&val, addr + 2, 4); - flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 8, - &val, &mask); -- dev_put(dev); -+ -+ if (dev) -+ dev_put(dev); - - return 0; - } -@@ -210,27 +227,40 @@ static int flow_offload_eth_dst(struct n - { - struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule); - struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule); -- const void *daddr = &flow->tuplehash[!dir].tuple.src_v4; -+ const struct flow_offload_tuple *other_tuple, *this_tuple; - const struct dst_entry *dst_cache; - unsigned char ha[ETH_ALEN]; - struct neighbour *n; -+ const void *daddr; - u32 mask, val; - u8 nud_state; - u16 val16; - -- dst_cache = flow->tuplehash[dir].tuple.dst_cache; -- n = dst_neigh_lookup(dst_cache, daddr); -- if (!n) -- return -ENOENT; -- -- read_lock_bh(&n->lock); -- nud_state = n->nud_state; -- ether_addr_copy(ha, n->ha); -- read_unlock_bh(&n->lock); -+ this_tuple = &flow->tuplehash[dir].tuple; - -- if (!(nud_state & NUD_VALID)) { -+ switch (this_tuple->xmit_type) { -+ case FLOW_OFFLOAD_XMIT_DIRECT: -+ ether_addr_copy(ha, this_tuple->out.h_dest); -+ break; -+ case FLOW_OFFLOAD_XMIT_NEIGH: -+ other_tuple = &flow->tuplehash[!dir].tuple; -+ daddr = &other_tuple->src_v4; -+ dst_cache = this_tuple->dst_cache; -+ n = dst_neigh_lookup(dst_cache, daddr); -+ if (!n) -+ return -ENOENT; -+ -+ read_lock_bh(&n->lock); -+ nud_state = n->nud_state; -+ ether_addr_copy(ha, n->ha); -+ read_unlock_bh(&n->lock); - neigh_release(n); -- return -ENOENT; -+ -+ if (!(nud_state & NUD_VALID)) -+ return -ENOENT; -+ break; -+ default: -+ return -EOPNOTSUPP; - } - - mask = ~0xffffffff; -@@ -243,7 +273,6 @@ static int flow_offload_eth_dst(struct n - val = val16; - flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4, - &val, &mask); -- neigh_release(n); - - return 0; - } -@@ -465,27 +494,52 @@ static void flow_offload_ipv4_checksum(s - } - } - --static void flow_offload_redirect(const struct flow_offload *flow, -+static void flow_offload_redirect(struct net *net, -+ const struct flow_offload *flow, - enum flow_offload_tuple_dir dir, - struct nf_flow_rule *flow_rule) - { -- struct flow_action_entry *entry = flow_action_entry_next(flow_rule); -- struct rtable *rt; -+ const struct flow_offload_tuple *this_tuple, *other_tuple; -+ struct flow_action_entry *entry; -+ struct net_device *dev; -+ int ifindex; -+ -+ this_tuple = &flow->tuplehash[dir].tuple; -+ switch (this_tuple->xmit_type) { -+ case FLOW_OFFLOAD_XMIT_DIRECT: -+ this_tuple = &flow->tuplehash[dir].tuple; -+ ifindex = this_tuple->out.ifidx; -+ break; -+ case FLOW_OFFLOAD_XMIT_NEIGH: -+ other_tuple = &flow->tuplehash[!dir].tuple; -+ ifindex = other_tuple->iifidx; -+ break; -+ default: -+ return; -+ } - -- rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache; -+ dev = dev_get_by_index(net, ifindex); -+ if (!dev) -+ return; -+ -+ entry = flow_action_entry_next(flow_rule); - entry->id = FLOW_ACTION_REDIRECT; -- entry->dev = rt->dst.dev; -- dev_hold(rt->dst.dev); -+ entry->dev = dev; - } - - static void flow_offload_encap_tunnel(const struct flow_offload *flow, - enum flow_offload_tuple_dir dir, - struct nf_flow_rule *flow_rule) - { -+ const struct flow_offload_tuple *this_tuple; - struct flow_action_entry *entry; - struct dst_entry *dst; - -- dst = flow->tuplehash[dir].tuple.dst_cache; -+ this_tuple = &flow->tuplehash[dir].tuple; -+ if (this_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) -+ return; -+ -+ dst = this_tuple->dst_cache; - if (dst && dst->lwtstate) { - struct ip_tunnel_info *tun_info; - -@@ -502,10 +556,15 @@ static void flow_offload_decap_tunnel(co - enum flow_offload_tuple_dir dir, - struct nf_flow_rule *flow_rule) - { -+ const struct flow_offload_tuple *other_tuple; - struct flow_action_entry *entry; - struct dst_entry *dst; - -- dst = flow->tuplehash[!dir].tuple.dst_cache; -+ other_tuple = &flow->tuplehash[!dir].tuple; -+ if (other_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) -+ return; -+ -+ dst = other_tuple->dst_cache; - if (dst && dst->lwtstate) { - struct ip_tunnel_info *tun_info; - -@@ -517,10 +576,14 @@ static void flow_offload_decap_tunnel(co - } - } - --int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow, -- enum flow_offload_tuple_dir dir, -- struct nf_flow_rule *flow_rule) -+static int -+nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow, -+ enum flow_offload_tuple_dir dir, -+ struct nf_flow_rule *flow_rule) - { -+ const struct flow_offload_tuple *other_tuple; -+ int i; -+ - flow_offload_decap_tunnel(flow, dir, flow_rule); - flow_offload_encap_tunnel(flow, dir, flow_rule); - -@@ -528,6 +591,26 @@ int nf_flow_rule_route_ipv4(struct net * - flow_offload_eth_dst(net, flow, dir, flow_rule) < 0) - return -1; - -+ other_tuple = &flow->tuplehash[!dir].tuple; -+ -+ for (i = 0; i < other_tuple->encap_num; i++) { -+ struct flow_action_entry *entry = flow_action_entry_next(flow_rule); -+ -+ entry->id = FLOW_ACTION_VLAN_PUSH; -+ entry->vlan.vid = other_tuple->encap[i].id; -+ entry->vlan.proto = other_tuple->encap[i].proto; -+ } -+ -+ return 0; -+} -+ -+int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow, -+ enum flow_offload_tuple_dir dir, -+ struct nf_flow_rule *flow_rule) -+{ -+ if (nf_flow_rule_route_common(net, flow, dir, flow_rule) < 0) -+ return -1; -+ - if (test_bit(NF_FLOW_SNAT, &flow->flags)) { - flow_offload_ipv4_snat(net, flow, dir, flow_rule); - flow_offload_port_snat(net, flow, dir, flow_rule); -@@ -540,7 +623,7 @@ int nf_flow_rule_route_ipv4(struct net * - test_bit(NF_FLOW_DNAT, &flow->flags)) - flow_offload_ipv4_checksum(net, flow, flow_rule); - -- flow_offload_redirect(flow, dir, flow_rule); -+ flow_offload_redirect(net, flow, dir, flow_rule); - - return 0; - } -@@ -550,11 +633,7 @@ int nf_flow_rule_route_ipv6(struct net * - enum flow_offload_tuple_dir dir, - struct nf_flow_rule *flow_rule) - { -- flow_offload_decap_tunnel(flow, dir, flow_rule); -- flow_offload_encap_tunnel(flow, dir, flow_rule); -- -- if (flow_offload_eth_src(net, flow, dir, flow_rule) < 0 || -- flow_offload_eth_dst(net, flow, dir, flow_rule) < 0) -+ if (nf_flow_rule_route_common(net, flow, dir, flow_rule) < 0) - return -1; - - if (test_bit(NF_FLOW_SNAT, &flow->flags)) { -@@ -566,7 +645,7 @@ int nf_flow_rule_route_ipv6(struct net * - flow_offload_port_dnat(net, flow, dir, flow_rule); - } - -- flow_offload_redirect(flow, dir, flow_rule); -+ flow_offload_redirect(net, flow, dir, flow_rule); - - return 0; - } -@@ -580,10 +659,10 @@ nf_flow_offload_rule_alloc(struct net *n - enum flow_offload_tuple_dir dir) - { - const struct nf_flowtable *flowtable = offload->flowtable; -+ const struct flow_offload_tuple *tuple, *other_tuple; - const struct flow_offload *flow = offload->flow; -- const struct flow_offload_tuple *tuple; -+ struct dst_entry *other_dst = NULL; - struct nf_flow_rule *flow_rule; -- struct dst_entry *other_dst; - int err = -ENOMEM; - - flow_rule = kzalloc(sizeof(*flow_rule), GFP_KERNEL); -@@ -599,7 +678,10 @@ nf_flow_offload_rule_alloc(struct net *n - flow_rule->rule->match.key = &flow_rule->match.key; - - tuple = &flow->tuplehash[dir].tuple; -- other_dst = flow->tuplehash[!dir].tuple.dst_cache; -+ other_tuple = &flow->tuplehash[!dir].tuple; -+ if (other_tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) -+ other_dst = other_tuple->dst_cache; -+ - err = nf_flow_rule_match(&flow_rule->match, tuple, other_dst); - if (err < 0) - goto err_flow_match; diff --git a/target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch b/target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch deleted file mode 100644 index 56bb9fd56b..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-26-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch +++ /dev/null @@ -1,114 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:47 +0100 -Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if - hardware offload is enabled - -If there is a forward path to reach an ethernet device and hardware -offload is enabled, then use the direct xmit path. - -Moreover, store the real device in the direct xmit path info since -software datapath uses dev_hard_header() to push the layer encapsulation -headers while hardware offload refers to the real device. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -131,6 +131,7 @@ struct flow_offload_tuple { - struct dst_entry *dst_cache; - struct { - u32 ifidx; -+ u32 hw_ifidx; - u8 h_source[ETH_ALEN]; - u8 h_dest[ETH_ALEN]; - } out; -@@ -187,6 +188,7 @@ struct nf_flow_route { - } in; - struct { - u32 ifindex; -+ u32 hw_ifindex; - u8 h_source[ETH_ALEN]; - u8 h_dest[ETH_ALEN]; - } out; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -106,6 +106,7 @@ static int flow_offload_fill_route(struc - memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source, - ETH_ALEN); - flow_tuple->out.ifidx = route->tuple[dir].out.ifindex; -+ flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex; - break; - case FLOW_OFFLOAD_XMIT_XFRM: - case FLOW_OFFLOAD_XMIT_NEIGH: ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -508,7 +508,7 @@ static void flow_offload_redirect(struct - switch (this_tuple->xmit_type) { - case FLOW_OFFLOAD_XMIT_DIRECT: - this_tuple = &flow->tuplehash[dir].tuple; -- ifindex = this_tuple->out.ifidx; -+ ifindex = this_tuple->out.hw_ifidx; - break; - case FLOW_OFFLOAD_XMIT_NEIGH: - other_tuple = &flow->tuplehash[!dir].tuple; ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -66,6 +66,7 @@ static int nft_dev_fill_forward_path(con - struct nft_forward_info { - const struct net_device *indev; - const struct net_device *outdev; -+ const struct net_device *hw_outdev; - struct id { - __u16 id; - __be16 proto; -@@ -76,9 +77,18 @@ struct nft_forward_info { - enum flow_offload_xmit_type xmit_type; - }; - -+static bool nft_is_valid_ether_device(const struct net_device *dev) -+{ -+ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || -+ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) -+ return false; -+ -+ return true; -+} -+ - static void nft_dev_path_info(const struct net_device_path_stack *stack, - struct nft_forward_info *info, -- unsigned char *ha) -+ unsigned char *ha, struct nf_flowtable *flowtable) - { - const struct net_device_path *path; - int i; -@@ -140,6 +150,12 @@ static void nft_dev_path_info(const stru - } - if (!info->outdev) - info->outdev = info->indev; -+ -+ info->hw_outdev = info->indev; -+ -+ if (nf_flowtable_hw_offload(flowtable) && -+ nft_is_valid_ether_device(info->indev)) -+ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; - } - - static bool nft_flowtable_find_dev(const struct net_device *dev, -@@ -171,7 +187,7 @@ static void nft_dev_forward_path(struct - int i; - - if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) -- nft_dev_path_info(&stack, &info, ha); -+ nft_dev_path_info(&stack, &info, ha, &ft->data); - - if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) - return; -@@ -187,6 +203,7 @@ static void nft_dev_forward_path(struct - memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); - memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); - route->tuple[dir].out.ifindex = info.outdev->ifindex; -+ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; - route->tuple[dir].xmit_type = info.xmit_type; - } - } diff --git a/target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch b/target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch deleted file mode 100644 index 7fa58ba844..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-27-netfilter-flowtable-bridge-vlan-hardware-offload-and.patch +++ /dev/null @@ -1,123 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:48 +0100 -Subject: [PATCH] netfilter: flowtable: bridge vlan hardware offload and - switchdev - -The switch might have already added the VLAN tag through PVID hardware -offload. Keep this extra VLAN in the flowtable but skip it on egress. - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -849,6 +849,7 @@ struct net_device_path { - DEV_PATH_BR_VLAN_KEEP, - DEV_PATH_BR_VLAN_TAG, - DEV_PATH_BR_VLAN_UNTAG, -+ DEV_PATH_BR_VLAN_UNTAG_HW, - } vlan_mode; - u16 vlan_id; - __be16 vlan_proto; ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -123,9 +123,10 @@ struct flow_offload_tuple { - /* All members above are keys for lookups, see flow_offload_hash(). */ - struct { } __hash; - -- u8 dir:4, -+ u8 dir:2, - xmit_type:2, -- encap_num:2; -+ encap_num:2, -+ in_vlan_ingress:2; - u16 mtu; - union { - struct dst_entry *dst_cache; -@@ -184,7 +185,8 @@ struct nf_flow_route { - u16 id; - __be16 proto; - } encap[NF_FLOW_TABLE_ENCAP_MAX]; -- u8 num_encaps; -+ u8 num_encaps:2, -+ ingress_vlans:2; - } in; - struct { - u32 ifindex; ---- a/net/bridge/br_device.c -+++ b/net/bridge/br_device.c -@@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n - ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto; - ctx->num_vlans++; - break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: - case DEV_PATH_BR_VLAN_UNTAG: - ctx->num_vlans--; - break; ---- a/net/bridge/br_vlan.c -+++ b/net/bridge/br_vlan.c -@@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc - - if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) - path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; -+ else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV) -+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW; - else - path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; - ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -95,6 +95,8 @@ static int flow_offload_fill_route(struc - for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) { - flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id; - flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto; -+ if (route->tuple[dir].in.ingress_vlans & BIT(i)) -+ flow_tuple->in_vlan_ingress |= BIT(j); - j++; - } - flow_tuple->encap_num = route->tuple[dir].in.num_encaps; ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -594,8 +594,12 @@ nf_flow_rule_route_common(struct net *ne - other_tuple = &flow->tuplehash[!dir].tuple; - - for (i = 0; i < other_tuple->encap_num; i++) { -- struct flow_action_entry *entry = flow_action_entry_next(flow_rule); -+ struct flow_action_entry *entry; - -+ if (other_tuple->in_vlan_ingress & BIT(i)) -+ continue; -+ -+ entry = flow_action_entry_next(flow_rule); - entry->id = FLOW_ACTION_VLAN_PUSH; - entry->vlan.vid = other_tuple->encap[i].id; - entry->vlan.proto = other_tuple->encap[i].proto; ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -72,6 +72,7 @@ struct nft_forward_info { - __be16 proto; - } encap[NF_FLOW_TABLE_ENCAP_MAX]; - u8 num_encaps; -+ u8 ingress_vlans; - u8 h_source[ETH_ALEN]; - u8 h_dest[ETH_ALEN]; - enum flow_offload_xmit_type xmit_type; -@@ -130,6 +131,9 @@ static void nft_dev_path_info(const stru - memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); - - switch (path->bridge.vlan_mode) { -+ case DEV_PATH_BR_VLAN_UNTAG_HW: -+ info->ingress_vlans |= BIT(info->num_encaps - 1); -+ break; - case DEV_PATH_BR_VLAN_TAG: - info->encap[info->num_encaps].id = path->bridge.vlan_id; - info->encap[info->num_encaps].proto = path->bridge.vlan_proto; -@@ -198,6 +202,7 @@ static void nft_dev_forward_path(struct - route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; - } - route->tuple[!dir].in.num_encaps = info.num_encaps; -+ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; - - if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { - memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); diff --git a/target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch b/target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch deleted file mode 100644 index 64eae6871f..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-28-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:49 +0100 -Subject: [PATCH] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH - -Add an action to represent the PPPoE hardware offload support that -includes the session ID. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/flow_offload.h -+++ b/include/net/flow_offload.h -@@ -147,6 +147,7 @@ enum flow_action_id { - FLOW_ACTION_MPLS_POP, - FLOW_ACTION_MPLS_MANGLE, - FLOW_ACTION_GATE, -+ FLOW_ACTION_PPPOE_PUSH, - NUM_FLOW_ACTIONS, - }; - -@@ -271,6 +272,9 @@ struct flow_action_entry { - u32 num_entries; - struct action_gate_entry *entries; - } gate; -+ struct { /* FLOW_ACTION_PPPOE_PUSH */ -+ u16 sid; -+ } pppoe; - }; - struct flow_action_cookie *cookie; /* user defined action cookie */ - }; diff --git a/target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch b/target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch deleted file mode 100644 index ed7346a61a..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-29-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:50 +0100 -Subject: [PATCH] netfilter: flowtable: support for - FLOW_ACTION_PPPOE_PUSH - -Add a PPPoE push action if layer 2 protocol is ETH_P_PPP_SES to add -PPPoE flowtable hardware offload support. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -600,9 +600,18 @@ nf_flow_rule_route_common(struct net *ne - continue; - - entry = flow_action_entry_next(flow_rule); -- entry->id = FLOW_ACTION_VLAN_PUSH; -- entry->vlan.vid = other_tuple->encap[i].id; -- entry->vlan.proto = other_tuple->encap[i].proto; -+ -+ switch (other_tuple->encap[i].proto) { -+ case htons(ETH_P_PPP_SES): -+ entry->id = FLOW_ACTION_PPPOE_PUSH; -+ entry->pppoe.sid = other_tuple->encap[i].id; -+ break; -+ case htons(ETH_P_8021Q): -+ entry->id = FLOW_ACTION_VLAN_PUSH; -+ entry->vlan.vid = other_tuple->encap[i].id; -+ entry->vlan.proto = other_tuple->encap[i].proto; -+ break; -+ } - } - - return 0; diff --git a/target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch b/target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch deleted file mode 100644 index 72675dc294..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-30-dsa-slave-add-support-for-TC_SETUP_FT.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:51 +0100 -Subject: [PATCH] dsa: slave: add support for TC_SETUP_FT - -The dsa infrastructure provides a well-defined hierarchy of devices, -pass up the call to set up the flow block to the master device. From the -software dataplane, the netfilter infrastructure uses the dsa slave -devices to refer to the input and output device for the given skbuff. -Similarly, the flowtable definition in the ruleset refers to the dsa -slave port devices. - -This patch adds the glue code to call ndo_setup_tc with TC_SETUP_FT -with the master device via the dsa slave devices. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -1239,14 +1239,32 @@ static int dsa_slave_setup_tc_block(stru - } - } - -+static int dsa_slave_setup_ft_block(struct dsa_switch *ds, int port, -+ void *type_data) -+{ -+ struct dsa_port *cpu_dp = dsa_to_port(ds, port)->cpu_dp; -+ struct net_device *master = cpu_dp->master; -+ -+ if (!master->netdev_ops->ndo_setup_tc) -+ return -EOPNOTSUPP; -+ -+ return master->netdev_ops->ndo_setup_tc(master, TC_SETUP_FT, type_data); -+} -+ - static int dsa_slave_setup_tc(struct net_device *dev, enum tc_setup_type type, - void *type_data) - { - struct dsa_port *dp = dsa_slave_to_port(dev); - struct dsa_switch *ds = dp->ds; - -- if (type == TC_SETUP_BLOCK) -+ switch (type) { -+ case TC_SETUP_BLOCK: - return dsa_slave_setup_tc_block(dev, type_data); -+ case TC_SETUP_FT: -+ return dsa_slave_setup_ft_block(ds, dp->index, type_data); -+ default: -+ break; -+ } - - if (!ds->ops->port_setup_tc) - return -EOPNOTSUPP; diff --git a/target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch b/target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch deleted file mode 100644 index b763984732..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-31-net-ethernet-mtk_eth_soc-fix-parsing-packets-in-GDM.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:52 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix parsing packets in GDM - -When using DSA, set the special tag in GDM ingress control to allow the MAC -to parse packets properly earlier. This affects rx DMA source port reporting. - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include "mtk_eth_soc.h" - -@@ -1285,13 +1286,12 @@ static int mtk_poll_rx(struct napi_struc - break; - - /* find out which mac the packet come from. values start at 1 */ -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) || -+ (trxd.rxd4 & RX_DMA_SPECIAL_TAG)) - mac = 0; -- } else { -- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & -- RX_DMA_FPORT_MASK; -- mac--; -- } -+ else -+ mac = ((trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & -+ RX_DMA_FPORT_MASK) - 1; - - if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || - !eth->netdev[mac])) -@@ -2254,6 +2254,9 @@ static void mtk_gdm_config(struct mtk_et - - val |= config; - -+ if (!i && eth->netdev[0] && netdev_uses_dsa(eth->netdev[0])) -+ val |= MTK_GDMA_SPECIAL_TAG; -+ - mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); - } - /* Reset and enable PSE */ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -81,6 +81,7 @@ - - /* GDM Exgress Control Register */ - #define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) -+#define MTK_GDMA_SPECIAL_TAG BIT(24) - #define MTK_GDMA_ICS_EN BIT(22) - #define MTK_GDMA_TCS_EN BIT(21) - #define MTK_GDMA_UCS_EN BIT(20) -@@ -318,6 +319,7 @@ - #define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */ - #define RX_DMA_FPORT_SHIFT 19 - #define RX_DMA_FPORT_MASK 0x7 -+#define RX_DMA_SPECIAL_TAG BIT(22) - - /* PHY Indirect Access Control registers */ - #define MTK_PHY_IAC 0x10004 diff --git a/target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch b/target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch deleted file mode 100644 index 4fd6f8a36b..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-32-net-ethernet-mtk_eth_soc-add-support-for-initializin.patch +++ /dev/null @@ -1,1308 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:53 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for - initializing the PPE - -The PPE (packet processing engine) is used to offload NAT/routed or even -bridged flows. This patch brings up the PPE and uses it to get a packet -hash. It also contains some functionality that will be used to bring up -flow offloading. - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.c - create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.h - create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c - create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_regs.h - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -4,5 +4,5 @@ - # - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o --mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o -+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o - obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2279,12 +2279,17 @@ static int mtk_open(struct net_device *d - - /* we run 2 netdevs on the same dma ring so we only bring it up once */ - if (!refcount_read(ð->dma_refcnt)) { -- int err = mtk_start_dma(eth); -+ u32 gdm_config = MTK_GDMA_TO_PDMA; -+ int err; - -+ err = mtk_start_dma(eth); - if (err) - return err; - -- mtk_gdm_config(eth, MTK_GDMA_TO_PDMA); -+ if (eth->soc->offload_version && mtk_ppe_start(ð->ppe) == 0) -+ gdm_config = MTK_GDMA_TO_PPE; -+ -+ mtk_gdm_config(eth, gdm_config); - - napi_enable(ð->tx_napi); - napi_enable(ð->rx_napi); -@@ -2351,6 +2356,9 @@ static int mtk_stop(struct net_device *d - - mtk_dma_free(eth); - -+ if (eth->soc->offload_version) -+ mtk_ppe_stop(ð->ppe); -+ - return 0; - } - -@@ -3079,6 +3087,13 @@ static int mtk_probe(struct platform_dev - goto err_free_dev; - } - -+ if (eth->soc->offload_version) { -+ err = mtk_ppe_init(ð->ppe, eth->dev, -+ eth->base + MTK_ETH_PPE_BASE, 2); -+ if (err) -+ goto err_free_dev; -+ } -+ - for (i = 0; i < MTK_MAX_DEVS; i++) { - if (!eth->netdev[i]) - continue; -@@ -3153,6 +3168,7 @@ static const struct mtk_soc_data mt7621_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7621_CLKS_BITMAP, - .required_pctl = false, -+ .offload_version = 2, - }; - - static const struct mtk_soc_data mt7622_data = { -@@ -3161,6 +3177,7 @@ static const struct mtk_soc_data mt7622_ - .hw_features = MTK_HW_FEATURES, - .required_clks = MT7622_CLKS_BITMAP, - .required_pctl = false, -+ .offload_version = 2, - }; - - static const struct mtk_soc_data mt7623_data = { ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include "mtk_ppe.h" - - #define MTK_QDMA_PAGE_SIZE 2048 - #define MTK_MAX_RX_LENGTH 1536 -@@ -86,6 +87,7 @@ - #define MTK_GDMA_TCS_EN BIT(21) - #define MTK_GDMA_UCS_EN BIT(20) - #define MTK_GDMA_TO_PDMA 0x0 -+#define MTK_GDMA_TO_PPE 0x4444 - #define MTK_GDMA_DROP_ALL 0x7777 - - /* Unicast Filter MAC Address Register - Low */ -@@ -315,6 +317,12 @@ - #define RX_DMA_VID(_x) ((_x) & 0xfff) - - /* QDMA descriptor rxd4 */ -+#define MTK_RXD4_FOE_ENTRY GENMASK(13, 0) -+#define MTK_RXD4_PPE_CPU_REASON GENMASK(18, 14) -+#define MTK_RXD4_SRC_PORT GENMASK(21, 19) -+#define MTK_RXD4_ALG GENMASK(31, 22) -+ -+/* QDMA descriptor rxd4 */ - #define RX_DMA_L4_VALID BIT(24) - #define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */ - #define RX_DMA_FPORT_SHIFT 19 -@@ -819,6 +827,7 @@ struct mtk_soc_data { - u32 caps; - u32 required_clks; - bool required_pctl; -+ u8 offload_version; - netdev_features_t hw_features; - }; - -@@ -918,6 +927,8 @@ struct mtk_eth { - u32 tx_int_status_reg; - u32 rx_dma_l4_valid; - int ip_align; -+ -+ struct mtk_ppe ppe; - }; - - /* struct mtk_mac - the structure that holds the info about the MACs of the ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -0,0 +1,511 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2020 Felix Fietkau */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mtk_ppe.h" -+#include "mtk_ppe_regs.h" -+ -+static void ppe_w32(struct mtk_ppe *ppe, u32 reg, u32 val) -+{ -+ writel(val, ppe->base + reg); -+} -+ -+static u32 ppe_r32(struct mtk_ppe *ppe, u32 reg) -+{ -+ return readl(ppe->base + reg); -+} -+ -+static u32 ppe_m32(struct mtk_ppe *ppe, u32 reg, u32 mask, u32 set) -+{ -+ u32 val; -+ -+ val = ppe_r32(ppe, reg); -+ val &= ~mask; -+ val |= set; -+ ppe_w32(ppe, reg, val); -+ -+ return val; -+} -+ -+static u32 ppe_set(struct mtk_ppe *ppe, u32 reg, u32 val) -+{ -+ return ppe_m32(ppe, reg, 0, val); -+} -+ -+static u32 ppe_clear(struct mtk_ppe *ppe, u32 reg, u32 val) -+{ -+ return ppe_m32(ppe, reg, val, 0); -+} -+ -+static int mtk_ppe_wait_busy(struct mtk_ppe *ppe) -+{ -+ unsigned long timeout = jiffies + HZ; -+ -+ while (time_is_before_jiffies(timeout)) { -+ if (!(ppe_r32(ppe, MTK_PPE_GLO_CFG) & MTK_PPE_GLO_CFG_BUSY)) -+ return 0; -+ -+ usleep_range(10, 20); -+ } -+ -+ dev_err(ppe->dev, "PPE table busy"); -+ -+ return -ETIMEDOUT; -+} -+ -+static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) -+{ -+ ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); -+ ppe_clear(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); -+} -+ -+static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable) -+{ -+ mtk_ppe_cache_clear(ppe); -+ -+ ppe_m32(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_EN, -+ enable * MTK_PPE_CACHE_CTL_EN); -+} -+ -+static u32 mtk_ppe_hash_entry(struct mtk_foe_entry *e) -+{ -+ u32 hv1, hv2, hv3; -+ u32 hash; -+ -+ switch (FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, e->ib1)) { -+ case MTK_PPE_PKT_TYPE_BRIDGE: -+ hv1 = e->bridge.src_mac_lo; -+ hv1 ^= ((e->bridge.src_mac_hi & 0xffff) << 16); -+ hv2 = e->bridge.src_mac_hi >> 16; -+ hv2 ^= e->bridge.dest_mac_lo; -+ hv3 = e->bridge.dest_mac_hi; -+ break; -+ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: -+ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: -+ hv1 = e->ipv4.orig.ports; -+ hv2 = e->ipv4.orig.dest_ip; -+ hv3 = e->ipv4.orig.src_ip; -+ break; -+ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T: -+ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T: -+ hv1 = e->ipv6.src_ip[3] ^ e->ipv6.dest_ip[3]; -+ hv1 ^= e->ipv6.ports; -+ -+ hv2 = e->ipv6.src_ip[2] ^ e->ipv6.dest_ip[2]; -+ hv2 ^= e->ipv6.dest_ip[0]; -+ -+ hv3 = e->ipv6.src_ip[1] ^ e->ipv6.dest_ip[1]; -+ hv3 ^= e->ipv6.src_ip[0]; -+ break; -+ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: -+ case MTK_PPE_PKT_TYPE_IPV6_6RD: -+ default: -+ WARN_ON_ONCE(1); -+ return MTK_PPE_HASH_MASK; -+ } -+ -+ hash = (hv1 & hv2) | ((~hv1) & hv3); -+ hash = (hash >> 24) | ((hash & 0xffffff) << 8); -+ hash ^= hv1 ^ hv2 ^ hv3; -+ hash ^= hash >> 16; -+ hash <<= 1; -+ hash &= MTK_PPE_ENTRIES - 1; -+ -+ return hash; -+} -+ -+static inline struct mtk_foe_mac_info * -+mtk_foe_entry_l2(struct mtk_foe_entry *entry) -+{ -+ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ -+ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) -+ return &entry->ipv6.l2; -+ -+ return &entry->ipv4.l2; -+} -+ -+static inline u32 * -+mtk_foe_entry_ib2(struct mtk_foe_entry *entry) -+{ -+ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ -+ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) -+ return &entry->ipv6.ib2; -+ -+ return &entry->ipv4.ib2; -+} -+ -+int mtk_foe_entry_prepare(struct mtk_foe_entry *entry, int type, int l4proto, -+ u8 pse_port, u8 *src_mac, u8 *dest_mac) -+{ -+ struct mtk_foe_mac_info *l2; -+ u32 ports_pad, val; -+ -+ memset(entry, 0, sizeof(*entry)); -+ -+ val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) | -+ FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) | -+ FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) | -+ MTK_FOE_IB1_BIND_TTL | -+ MTK_FOE_IB1_BIND_CACHE; -+ entry->ib1 = val; -+ -+ val = FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) | -+ FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f) | -+ FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port); -+ -+ if (is_multicast_ether_addr(dest_mac)) -+ val |= MTK_FOE_IB2_MULTICAST; -+ -+ ports_pad = 0xa5a5a500 | (l4proto & 0xff); -+ if (type == MTK_PPE_PKT_TYPE_IPV4_ROUTE) -+ entry->ipv4.orig.ports = ports_pad; -+ if (type == MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T) -+ entry->ipv6.ports = ports_pad; -+ -+ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { -+ entry->ipv6.ib2 = val; -+ l2 = &entry->ipv6.l2; -+ } else { -+ entry->ipv4.ib2 = val; -+ l2 = &entry->ipv4.l2; -+ } -+ -+ l2->dest_mac_hi = get_unaligned_be32(dest_mac); -+ l2->dest_mac_lo = get_unaligned_be16(dest_mac + 4); -+ l2->src_mac_hi = get_unaligned_be32(src_mac); -+ l2->src_mac_lo = get_unaligned_be16(src_mac + 4); -+ -+ if (type >= MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T) -+ l2->etype = ETH_P_IPV6; -+ else -+ l2->etype = ETH_P_IP; -+ -+ return 0; -+} -+ -+int mtk_foe_entry_set_pse_port(struct mtk_foe_entry *entry, u8 port) -+{ -+ u32 *ib2 = mtk_foe_entry_ib2(entry); -+ u32 val; -+ -+ val = *ib2; -+ val &= ~MTK_FOE_IB2_DEST_PORT; -+ val |= FIELD_PREP(MTK_FOE_IB2_DEST_PORT, port); -+ *ib2 = val; -+ -+ return 0; -+} -+ -+int mtk_foe_entry_set_ipv4_tuple(struct mtk_foe_entry *entry, bool egress, -+ __be32 src_addr, __be16 src_port, -+ __be32 dest_addr, __be16 dest_port) -+{ -+ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ struct mtk_ipv4_tuple *t; -+ -+ switch (type) { -+ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: -+ if (egress) { -+ t = &entry->ipv4.new; -+ break; -+ } -+ fallthrough; -+ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: -+ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: -+ t = &entry->ipv4.orig; -+ break; -+ case MTK_PPE_PKT_TYPE_IPV6_6RD: -+ entry->ipv6_6rd.tunnel_src_ip = be32_to_cpu(src_addr); -+ entry->ipv6_6rd.tunnel_dest_ip = be32_to_cpu(dest_addr); -+ return 0; -+ default: -+ WARN_ON_ONCE(1); -+ return -EINVAL; -+ } -+ -+ t->src_ip = be32_to_cpu(src_addr); -+ t->dest_ip = be32_to_cpu(dest_addr); -+ -+ if (type == MTK_PPE_PKT_TYPE_IPV4_ROUTE) -+ return 0; -+ -+ t->src_port = be16_to_cpu(src_port); -+ t->dest_port = be16_to_cpu(dest_port); -+ -+ return 0; -+} -+ -+int mtk_foe_entry_set_ipv6_tuple(struct mtk_foe_entry *entry, -+ __be32 *src_addr, __be16 src_port, -+ __be32 *dest_addr, __be16 dest_port) -+{ -+ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ u32 *src, *dest; -+ int i; -+ -+ switch (type) { -+ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: -+ src = entry->dslite.tunnel_src_ip; -+ dest = entry->dslite.tunnel_dest_ip; -+ break; -+ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T: -+ case MTK_PPE_PKT_TYPE_IPV6_6RD: -+ entry->ipv6.src_port = be16_to_cpu(src_port); -+ entry->ipv6.dest_port = be16_to_cpu(dest_port); -+ fallthrough; -+ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T: -+ src = entry->ipv6.src_ip; -+ dest = entry->ipv6.dest_ip; -+ break; -+ default: -+ WARN_ON_ONCE(1); -+ return -EINVAL; -+ }; -+ -+ for (i = 0; i < 4; i++) -+ src[i] = be32_to_cpu(src_addr[i]); -+ for (i = 0; i < 4; i++) -+ dest[i] = be32_to_cpu(dest_addr[i]); -+ -+ return 0; -+} -+ -+int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port) -+{ -+ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); -+ -+ l2->etype = BIT(port); -+ -+ if (!(entry->ib1 & MTK_FOE_IB1_BIND_VLAN_LAYER)) -+ entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, 1); -+ else -+ l2->etype |= BIT(8); -+ -+ entry->ib1 &= ~MTK_FOE_IB1_BIND_VLAN_TAG; -+ -+ return 0; -+} -+ -+int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid) -+{ -+ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); -+ -+ switch (FIELD_GET(MTK_FOE_IB1_BIND_VLAN_LAYER, entry->ib1)) { -+ case 0: -+ entry->ib1 |= MTK_FOE_IB1_BIND_VLAN_TAG | -+ FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, 1); -+ l2->vlan1 = vid; -+ return 0; -+ case 1: -+ if (!(entry->ib1 & MTK_FOE_IB1_BIND_VLAN_TAG)) { -+ l2->vlan1 = vid; -+ l2->etype |= BIT(8); -+ } else { -+ l2->vlan2 = vid; -+ entry->ib1 += FIELD_PREP(MTK_FOE_IB1_BIND_VLAN_LAYER, 1); -+ } -+ return 0; -+ default: -+ return -ENOSPC; -+ } -+} -+ -+int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid) -+{ -+ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); -+ -+ if (!(entry->ib1 & MTK_FOE_IB1_BIND_VLAN_LAYER) || -+ (entry->ib1 & MTK_FOE_IB1_BIND_VLAN_TAG)) -+ l2->etype = ETH_P_PPP_SES; -+ -+ entry->ib1 |= MTK_FOE_IB1_BIND_PPPOE; -+ l2->pppoe_id = sid; -+ -+ return 0; -+} -+ -+static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry) -+{ -+ return !(entry->ib1 & MTK_FOE_IB1_STATIC) && -+ FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1) != MTK_FOE_STATE_BIND; -+} -+ -+int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, -+ u16 timestamp) -+{ -+ struct mtk_foe_entry *hwe; -+ u32 hash; -+ -+ timestamp &= MTK_FOE_IB1_BIND_TIMESTAMP; -+ entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP; -+ entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP, timestamp); -+ -+ hash = mtk_ppe_hash_entry(entry); -+ hwe = &ppe->foe_table[hash]; -+ if (!mtk_foe_entry_usable(hwe)) { -+ hwe++; -+ hash++; -+ -+ if (!mtk_foe_entry_usable(hwe)) -+ return -ENOSPC; -+ } -+ -+ memcpy(&hwe->data, &entry->data, sizeof(hwe->data)); -+ wmb(); -+ hwe->ib1 = entry->ib1; -+ -+ dma_wmb(); -+ -+ mtk_ppe_cache_clear(ppe); -+ -+ return hash; -+} -+ -+int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, -+ int version) -+{ -+ struct mtk_foe_entry *foe; -+ -+ /* need to allocate a separate device, since it PPE DMA access is -+ * not coherent. -+ */ -+ ppe->base = base; -+ ppe->dev = dev; -+ ppe->version = version; -+ -+ foe = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*foe), -+ &ppe->foe_phys, GFP_KERNEL); -+ if (!foe) -+ return -ENOMEM; -+ -+ ppe->foe_table = foe; -+ -+ mtk_ppe_debugfs_init(ppe); -+ -+ return 0; -+} -+ -+static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) -+{ -+ static const u8 skip[] = { 12, 25, 38, 51, 76, 89, 102 }; -+ int i, k; -+ -+ memset(ppe->foe_table, 0, MTK_PPE_ENTRIES * sizeof(ppe->foe_table)); -+ -+ if (!IS_ENABLED(CONFIG_SOC_MT7621)) -+ return; -+ -+ /* skip all entries that cross the 1024 byte boundary */ -+ for (i = 0; i < MTK_PPE_ENTRIES; i += 128) -+ for (k = 0; k < ARRAY_SIZE(skip); k++) -+ ppe->foe_table[i + skip[k]].ib1 |= MTK_FOE_IB1_STATIC; -+} -+ -+int mtk_ppe_start(struct mtk_ppe *ppe) -+{ -+ u32 val; -+ -+ mtk_ppe_init_foe_table(ppe); -+ ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); -+ -+ val = MTK_PPE_TB_CFG_ENTRY_80B | -+ MTK_PPE_TB_CFG_AGE_NON_L4 | -+ MTK_PPE_TB_CFG_AGE_UNBIND | -+ MTK_PPE_TB_CFG_AGE_TCP | -+ MTK_PPE_TB_CFG_AGE_UDP | -+ MTK_PPE_TB_CFG_AGE_TCP_FIN | -+ FIELD_PREP(MTK_PPE_TB_CFG_SEARCH_MISS, -+ MTK_PPE_SEARCH_MISS_ACTION_FORWARD_BUILD) | -+ FIELD_PREP(MTK_PPE_TB_CFG_KEEPALIVE, -+ MTK_PPE_KEEPALIVE_DISABLE) | -+ FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) | -+ FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE, -+ MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) | -+ FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM, -+ MTK_PPE_ENTRIES_SHIFT); -+ ppe_w32(ppe, MTK_PPE_TB_CFG, val); -+ -+ ppe_w32(ppe, MTK_PPE_IP_PROTO_CHK, -+ MTK_PPE_IP_PROTO_CHK_IPV4 | MTK_PPE_IP_PROTO_CHK_IPV6); -+ -+ mtk_ppe_cache_enable(ppe, true); -+ -+ val = MTK_PPE_FLOW_CFG_IP4_TCP_FRAG | -+ MTK_PPE_FLOW_CFG_IP4_UDP_FRAG | -+ MTK_PPE_FLOW_CFG_IP6_3T_ROUTE | -+ MTK_PPE_FLOW_CFG_IP6_5T_ROUTE | -+ MTK_PPE_FLOW_CFG_IP6_6RD | -+ MTK_PPE_FLOW_CFG_IP4_NAT | -+ MTK_PPE_FLOW_CFG_IP4_NAPT | -+ MTK_PPE_FLOW_CFG_IP4_DSLITE | -+ MTK_PPE_FLOW_CFG_L2_BRIDGE | -+ MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; -+ ppe_w32(ppe, MTK_PPE_FLOW_CFG, val); -+ -+ val = FIELD_PREP(MTK_PPE_UNBIND_AGE_MIN_PACKETS, 1000) | -+ FIELD_PREP(MTK_PPE_UNBIND_AGE_DELTA, 3); -+ ppe_w32(ppe, MTK_PPE_UNBIND_AGE, val); -+ -+ val = FIELD_PREP(MTK_PPE_BIND_AGE0_DELTA_UDP, 12) | -+ FIELD_PREP(MTK_PPE_BIND_AGE0_DELTA_NON_L4, 1); -+ ppe_w32(ppe, MTK_PPE_BIND_AGE0, val); -+ -+ val = FIELD_PREP(MTK_PPE_BIND_AGE1_DELTA_TCP_FIN, 1) | -+ FIELD_PREP(MTK_PPE_BIND_AGE1_DELTA_TCP, 7); -+ ppe_w32(ppe, MTK_PPE_BIND_AGE1, val); -+ -+ val = MTK_PPE_BIND_LIMIT0_QUARTER | MTK_PPE_BIND_LIMIT0_HALF; -+ ppe_w32(ppe, MTK_PPE_BIND_LIMIT0, val); -+ -+ val = MTK_PPE_BIND_LIMIT1_FULL | -+ FIELD_PREP(MTK_PPE_BIND_LIMIT1_NON_L4, 1); -+ ppe_w32(ppe, MTK_PPE_BIND_LIMIT1, val); -+ -+ val = FIELD_PREP(MTK_PPE_BIND_RATE_BIND, 30) | -+ FIELD_PREP(MTK_PPE_BIND_RATE_PREBIND, 1); -+ ppe_w32(ppe, MTK_PPE_BIND_RATE, val); -+ -+ /* enable PPE */ -+ val = MTK_PPE_GLO_CFG_EN | -+ MTK_PPE_GLO_CFG_IP4_L4_CS_DROP | -+ MTK_PPE_GLO_CFG_IP4_CS_DROP | -+ MTK_PPE_GLO_CFG_FLOW_DROP_UPDATE; -+ ppe_w32(ppe, MTK_PPE_GLO_CFG, val); -+ -+ ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); -+ -+ return 0; -+} -+ -+int mtk_ppe_stop(struct mtk_ppe *ppe) -+{ -+ u32 val; -+ int i; -+ -+ for (i = 0; i < MTK_PPE_ENTRIES; i++) -+ ppe->foe_table[i].ib1 = FIELD_PREP(MTK_FOE_IB1_STATE, -+ MTK_FOE_STATE_INVALID); -+ -+ mtk_ppe_cache_enable(ppe, false); -+ -+ /* disable offload engine */ -+ ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN); -+ ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0); -+ -+ /* disable aging */ -+ val = MTK_PPE_TB_CFG_AGE_NON_L4 | -+ MTK_PPE_TB_CFG_AGE_UNBIND | -+ MTK_PPE_TB_CFG_AGE_TCP | -+ MTK_PPE_TB_CFG_AGE_UDP | -+ MTK_PPE_TB_CFG_AGE_TCP_FIN; -+ ppe_clear(ppe, MTK_PPE_TB_CFG, val); -+ -+ return mtk_ppe_wait_busy(ppe); -+} ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -0,0 +1,287 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2020 Felix Fietkau */ -+ -+#ifndef __MTK_PPE_H -+#define __MTK_PPE_H -+ -+#include -+#include -+ -+#define MTK_ETH_PPE_BASE 0xc00 -+ -+#define MTK_PPE_ENTRIES_SHIFT 3 -+#define MTK_PPE_ENTRIES (1024 << MTK_PPE_ENTRIES_SHIFT) -+#define MTK_PPE_HASH_MASK (MTK_PPE_ENTRIES - 1) -+ -+#define MTK_FOE_IB1_UNBIND_TIMESTAMP GENMASK(7, 0) -+#define MTK_FOE_IB1_UNBIND_PACKETS GENMASK(23, 8) -+#define MTK_FOE_IB1_UNBIND_PREBIND BIT(24) -+ -+#define MTK_FOE_IB1_BIND_TIMESTAMP GENMASK(14, 0) -+#define MTK_FOE_IB1_BIND_KEEPALIVE BIT(15) -+#define MTK_FOE_IB1_BIND_VLAN_LAYER GENMASK(18, 16) -+#define MTK_FOE_IB1_BIND_PPPOE BIT(19) -+#define MTK_FOE_IB1_BIND_VLAN_TAG BIT(20) -+#define MTK_FOE_IB1_BIND_PKT_SAMPLE BIT(21) -+#define MTK_FOE_IB1_BIND_CACHE BIT(22) -+#define MTK_FOE_IB1_BIND_TUNNEL_DECAP BIT(23) -+#define MTK_FOE_IB1_BIND_TTL BIT(24) -+ -+#define MTK_FOE_IB1_PACKET_TYPE GENMASK(27, 25) -+#define MTK_FOE_IB1_STATE GENMASK(29, 28) -+#define MTK_FOE_IB1_UDP BIT(30) -+#define MTK_FOE_IB1_STATIC BIT(31) -+ -+enum { -+ MTK_PPE_PKT_TYPE_IPV4_HNAPT = 0, -+ MTK_PPE_PKT_TYPE_IPV4_ROUTE = 1, -+ MTK_PPE_PKT_TYPE_BRIDGE = 2, -+ MTK_PPE_PKT_TYPE_IPV4_DSLITE = 3, -+ MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T = 4, -+ MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T = 5, -+ MTK_PPE_PKT_TYPE_IPV6_6RD = 7, -+}; -+ -+#define MTK_FOE_IB2_QID GENMASK(3, 0) -+#define MTK_FOE_IB2_PSE_QOS BIT(4) -+#define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) -+#define MTK_FOE_IB2_MULTICAST BIT(8) -+ -+#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12) -+#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16) -+#define MTK_FOE_IB2_WHNAT_NAT BIT(17) -+ -+#define MTK_FOE_IB2_PORT_MG GENMASK(17, 12) -+ -+#define MTK_FOE_IB2_PORT_AG GENMASK(23, 18) -+ -+#define MTK_FOE_IB2_DSCP GENMASK(31, 24) -+ -+#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0) -+#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6) -+#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14) -+ -+enum { -+ MTK_FOE_STATE_INVALID, -+ MTK_FOE_STATE_UNBIND, -+ MTK_FOE_STATE_BIND, -+ MTK_FOE_STATE_FIN -+}; -+ -+struct mtk_foe_mac_info { -+ u16 vlan1; -+ u16 etype; -+ -+ u32 dest_mac_hi; -+ -+ u16 vlan2; -+ u16 dest_mac_lo; -+ -+ u32 src_mac_hi; -+ -+ u16 pppoe_id; -+ u16 src_mac_lo; -+}; -+ -+struct mtk_foe_bridge { -+ u32 dest_mac_hi; -+ -+ u16 src_mac_lo; -+ u16 dest_mac_lo; -+ -+ u32 src_mac_hi; -+ -+ u32 ib2; -+ -+ u32 _rsv[5]; -+ -+ u32 udf_tsid; -+ struct mtk_foe_mac_info l2; -+}; -+ -+struct mtk_ipv4_tuple { -+ u32 src_ip; -+ u32 dest_ip; -+ union { -+ struct { -+ u16 dest_port; -+ u16 src_port; -+ }; -+ struct { -+ u8 protocol; -+ u8 _pad[3]; /* fill with 0xa5a5a5 */ -+ }; -+ u32 ports; -+ }; -+}; -+ -+struct mtk_foe_ipv4 { -+ struct mtk_ipv4_tuple orig; -+ -+ u32 ib2; -+ -+ struct mtk_ipv4_tuple new; -+ -+ u16 timestamp; -+ u16 _rsv0[3]; -+ -+ u32 udf_tsid; -+ -+ struct mtk_foe_mac_info l2; -+}; -+ -+struct mtk_foe_ipv4_dslite { -+ struct mtk_ipv4_tuple ip4; -+ -+ u32 tunnel_src_ip[4]; -+ u32 tunnel_dest_ip[4]; -+ -+ u8 flow_label[3]; -+ u8 priority; -+ -+ u32 udf_tsid; -+ -+ u32 ib2; -+ -+ struct mtk_foe_mac_info l2; -+}; -+ -+struct mtk_foe_ipv6 { -+ u32 src_ip[4]; -+ u32 dest_ip[4]; -+ -+ union { -+ struct { -+ u8 protocol; -+ u8 _pad[3]; /* fill with 0xa5a5a5 */ -+ }; /* 3-tuple */ -+ struct { -+ u16 dest_port; -+ u16 src_port; -+ }; /* 5-tuple */ -+ u32 ports; -+ }; -+ -+ u32 _rsv[3]; -+ -+ u32 udf; -+ -+ u32 ib2; -+ struct mtk_foe_mac_info l2; -+}; -+ -+struct mtk_foe_ipv6_6rd { -+ u32 src_ip[4]; -+ u32 dest_ip[4]; -+ u16 dest_port; -+ u16 src_port; -+ -+ u32 tunnel_src_ip; -+ u32 tunnel_dest_ip; -+ -+ u16 hdr_csum; -+ u8 dscp; -+ u8 ttl; -+ -+ u8 flag; -+ u8 pad; -+ u8 per_flow_6rd_id; -+ u8 pad2; -+ -+ u32 ib2; -+ struct mtk_foe_mac_info l2; -+}; -+ -+struct mtk_foe_entry { -+ u32 ib1; -+ -+ union { -+ struct mtk_foe_bridge bridge; -+ struct mtk_foe_ipv4 ipv4; -+ struct mtk_foe_ipv4_dslite dslite; -+ struct mtk_foe_ipv6 ipv6; -+ struct mtk_foe_ipv6_6rd ipv6_6rd; -+ u32 data[19]; -+ }; -+}; -+ -+enum { -+ MTK_PPE_CPU_REASON_TTL_EXCEEDED = 0x02, -+ MTK_PPE_CPU_REASON_OPTION_HEADER = 0x03, -+ MTK_PPE_CPU_REASON_NO_FLOW = 0x07, -+ MTK_PPE_CPU_REASON_IPV4_FRAG = 0x08, -+ MTK_PPE_CPU_REASON_IPV4_DSLITE_FRAG = 0x09, -+ MTK_PPE_CPU_REASON_IPV4_DSLITE_NO_TCP_UDP = 0x0a, -+ MTK_PPE_CPU_REASON_IPV6_6RD_NO_TCP_UDP = 0x0b, -+ MTK_PPE_CPU_REASON_TCP_FIN_SYN_RST = 0x0c, -+ MTK_PPE_CPU_REASON_UN_HIT = 0x0d, -+ MTK_PPE_CPU_REASON_HIT_UNBIND = 0x0e, -+ MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, -+ MTK_PPE_CPU_REASON_HIT_BIND_TCP_FIN = 0x10, -+ MTK_PPE_CPU_REASON_HIT_TTL_1 = 0x11, -+ MTK_PPE_CPU_REASON_HIT_BIND_VLAN_VIOLATION = 0x12, -+ MTK_PPE_CPU_REASON_KEEPALIVE_UC_OLD_HDR = 0x13, -+ MTK_PPE_CPU_REASON_KEEPALIVE_MC_NEW_HDR = 0x14, -+ MTK_PPE_CPU_REASON_KEEPALIVE_DUP_OLD_HDR = 0x15, -+ MTK_PPE_CPU_REASON_HIT_BIND_FORCE_CPU = 0x16, -+ MTK_PPE_CPU_REASON_TUNNEL_OPTION_HEADER = 0x17, -+ MTK_PPE_CPU_REASON_MULTICAST_TO_CPU = 0x18, -+ MTK_PPE_CPU_REASON_MULTICAST_TO_GMAC1_CPU = 0x19, -+ MTK_PPE_CPU_REASON_HIT_PRE_BIND = 0x1a, -+ MTK_PPE_CPU_REASON_PACKET_SAMPLING = 0x1b, -+ MTK_PPE_CPU_REASON_EXCEED_MTU = 0x1c, -+ MTK_PPE_CPU_REASON_PPE_BYPASS = 0x1e, -+ MTK_PPE_CPU_REASON_INVALID = 0x1f, -+}; -+ -+struct mtk_ppe { -+ struct device *dev; -+ void __iomem *base; -+ int version; -+ -+ struct mtk_foe_entry *foe_table; -+ dma_addr_t foe_phys; -+ -+ void *acct_table; -+}; -+ -+int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, -+ int version); -+int mtk_ppe_start(struct mtk_ppe *ppe); -+int mtk_ppe_stop(struct mtk_ppe *ppe); -+ -+static inline void -+mtk_foe_entry_clear(struct mtk_ppe *ppe, u16 hash) -+{ -+ ppe->foe_table[hash].ib1 = 0; -+ dma_wmb(); -+} -+ -+static inline int -+mtk_foe_entry_timestamp(struct mtk_ppe *ppe, u16 hash) -+{ -+ u32 ib1 = READ_ONCE(ppe->foe_table[hash].ib1); -+ -+ if (FIELD_GET(MTK_FOE_IB1_STATE, ib1) != MTK_FOE_STATE_BIND) -+ return -1; -+ -+ return FIELD_GET(MTK_FOE_IB1_BIND_TIMESTAMP, ib1); -+} -+ -+int mtk_foe_entry_prepare(struct mtk_foe_entry *entry, int type, int l4proto, -+ u8 pse_port, u8 *src_mac, u8 *dest_mac); -+int mtk_foe_entry_set_pse_port(struct mtk_foe_entry *entry, u8 port); -+int mtk_foe_entry_set_ipv4_tuple(struct mtk_foe_entry *entry, bool orig, -+ __be32 src_addr, __be16 src_port, -+ __be32 dest_addr, __be16 dest_port); -+int mtk_foe_entry_set_ipv6_tuple(struct mtk_foe_entry *entry, -+ __be32 *src_addr, __be16 src_port, -+ __be32 *dest_addr, __be16 dest_port); -+int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port); -+int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); -+int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); -+int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, -+ u16 timestamp); -+int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); -+ -+#endif ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c -@@ -0,0 +1,217 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2020 Felix Fietkau */ -+ -+#include -+#include -+#include "mtk_eth_soc.h" -+ -+struct mtk_flow_addr_info -+{ -+ void *src, *dest; -+ u16 *src_port, *dest_port; -+ bool ipv6; -+}; -+ -+static const char *mtk_foe_entry_state_str(int state) -+{ -+ static const char * const state_str[] = { -+ [MTK_FOE_STATE_INVALID] = "INV", -+ [MTK_FOE_STATE_UNBIND] = "UNB", -+ [MTK_FOE_STATE_BIND] = "BND", -+ [MTK_FOE_STATE_FIN] = "FIN", -+ }; -+ -+ if (state >= ARRAY_SIZE(state_str) || !state_str[state]) -+ return "UNK"; -+ -+ return state_str[state]; -+} -+ -+static const char *mtk_foe_pkt_type_str(int type) -+{ -+ static const char * const type_str[] = { -+ [MTK_PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T", -+ [MTK_PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T", -+ [MTK_PPE_PKT_TYPE_BRIDGE] = "L2", -+ [MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE", -+ [MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T", -+ [MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T", -+ [MTK_PPE_PKT_TYPE_IPV6_6RD] = "6RD", -+ }; -+ -+ if (type >= ARRAY_SIZE(type_str) || !type_str[type]) -+ return "UNKNOWN"; -+ -+ return type_str[type]; -+} -+ -+static void -+mtk_print_addr(struct seq_file *m, u32 *addr, bool ipv6) -+{ -+ u32 n_addr[4]; -+ int i; -+ -+ if (!ipv6) { -+ seq_printf(m, "%pI4h", addr); -+ return; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(n_addr); i++) -+ n_addr[i] = htonl(addr[i]); -+ seq_printf(m, "%pI6", n_addr); -+} -+ -+static void -+mtk_print_addr_info(struct seq_file *m, struct mtk_flow_addr_info *ai) -+{ -+ mtk_print_addr(m, ai->src, ai->ipv6); -+ if (ai->src_port) -+ seq_printf(m, ":%d", *ai->src_port); -+ seq_printf(m, "->"); -+ mtk_print_addr(m, ai->dest, ai->ipv6); -+ if (ai->dest_port) -+ seq_printf(m, ":%d", *ai->dest_port); -+} -+ -+static int -+mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind) -+{ -+ struct mtk_ppe *ppe = m->private; -+ int i, count; -+ -+ for (i = 0, count = 0; i < MTK_PPE_ENTRIES; i++) { -+ struct mtk_foe_entry *entry = &ppe->foe_table[i]; -+ struct mtk_foe_mac_info *l2; -+ struct mtk_flow_addr_info ai = {}; -+ unsigned char h_source[ETH_ALEN]; -+ unsigned char h_dest[ETH_ALEN]; -+ int type, state; -+ u32 ib2; -+ -+ -+ state = FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1); -+ if (!state) -+ continue; -+ -+ if (bind && state != MTK_FOE_STATE_BIND) -+ continue; -+ -+ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); -+ seq_printf(m, "%05x %s %7s", i, -+ mtk_foe_entry_state_str(state), -+ mtk_foe_pkt_type_str(type)); -+ -+ switch (type) { -+ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: -+ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: -+ ai.src_port = &entry->ipv4.orig.src_port; -+ ai.dest_port = &entry->ipv4.orig.dest_port; -+ fallthrough; -+ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: -+ ai.src = &entry->ipv4.orig.src_ip; -+ ai.dest = &entry->ipv4.orig.dest_ip; -+ break; -+ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T: -+ ai.src_port = &entry->ipv6.src_port; -+ ai.dest_port = &entry->ipv6.dest_port; -+ fallthrough; -+ case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T: -+ case MTK_PPE_PKT_TYPE_IPV6_6RD: -+ ai.src = &entry->ipv6.src_ip; -+ ai.dest = &entry->ipv6.dest_ip; -+ ai.ipv6 = true; -+ break; -+ } -+ -+ seq_printf(m, " orig="); -+ mtk_print_addr_info(m, &ai); -+ -+ switch (type) { -+ case MTK_PPE_PKT_TYPE_IPV4_HNAPT: -+ case MTK_PPE_PKT_TYPE_IPV4_DSLITE: -+ ai.src_port = &entry->ipv4.new.src_port; -+ ai.dest_port = &entry->ipv4.new.dest_port; -+ fallthrough; -+ case MTK_PPE_PKT_TYPE_IPV4_ROUTE: -+ ai.src = &entry->ipv4.new.src_ip; -+ ai.dest = &entry->ipv4.new.dest_ip; -+ seq_printf(m, " new="); -+ mtk_print_addr_info(m, &ai); -+ break; -+ } -+ -+ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { -+ l2 = &entry->ipv6.l2; -+ ib2 = entry->ipv6.ib2; -+ } else { -+ l2 = &entry->ipv4.l2; -+ ib2 = entry->ipv4.ib2; -+ } -+ -+ *((__be32 *)h_source) = htonl(l2->src_mac_hi); -+ *((__be16 *)&h_source[4]) = htons(l2->src_mac_lo); -+ *((__be32 *)h_dest) = htonl(l2->dest_mac_hi); -+ *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); -+ -+ seq_printf(m, " eth=%pM->%pM etype=%04x" -+ " vlan=%d,%d ib1=%08x ib2=%08x\n", -+ h_source, h_dest, ntohs(l2->etype), -+ l2->vlan1, l2->vlan2, entry->ib1, ib2); -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_ppe_debugfs_foe_show_all(struct seq_file *m, void *private) -+{ -+ return mtk_ppe_debugfs_foe_show(m, private, false); -+} -+ -+static int -+mtk_ppe_debugfs_foe_show_bind(struct seq_file *m, void *private) -+{ -+ return mtk_ppe_debugfs_foe_show(m, private, true); -+} -+ -+static int -+mtk_ppe_debugfs_foe_open_all(struct inode *inode, struct file *file) -+{ -+ return single_open(file, mtk_ppe_debugfs_foe_show_all, -+ inode->i_private); -+} -+ -+static int -+mtk_ppe_debugfs_foe_open_bind(struct inode *inode, struct file *file) -+{ -+ return single_open(file, mtk_ppe_debugfs_foe_show_bind, -+ inode->i_private); -+} -+ -+int mtk_ppe_debugfs_init(struct mtk_ppe *ppe) -+{ -+ static const struct file_operations fops_all = { -+ .open = mtk_ppe_debugfs_foe_open_all, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+ }; -+ -+ static const struct file_operations fops_bind = { -+ .open = mtk_ppe_debugfs_foe_open_bind, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+ }; -+ -+ struct dentry *root; -+ -+ root = debugfs_create_dir("mtk_ppe", NULL); -+ if (!root) -+ return -ENOMEM; -+ -+ debugfs_create_file("entries", S_IRUGO, root, ppe, &fops_all); -+ debugfs_create_file("bind", S_IRUGO, root, ppe, &fops_bind); -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h -@@ -0,0 +1,144 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (C) 2020 Felix Fietkau */ -+ -+#ifndef __MTK_PPE_REGS_H -+#define __MTK_PPE_REGS_H -+ -+#define MTK_PPE_GLO_CFG 0x200 -+#define MTK_PPE_GLO_CFG_EN BIT(0) -+#define MTK_PPE_GLO_CFG_TSID_EN BIT(1) -+#define MTK_PPE_GLO_CFG_IP4_L4_CS_DROP BIT(2) -+#define MTK_PPE_GLO_CFG_IP4_CS_DROP BIT(3) -+#define MTK_PPE_GLO_CFG_TTL0_DROP BIT(4) -+#define MTK_PPE_GLO_CFG_PPE_BSWAP BIT(5) -+#define MTK_PPE_GLO_CFG_PSE_HASH_OFS BIT(6) -+#define MTK_PPE_GLO_CFG_MCAST_TB_EN BIT(7) -+#define MTK_PPE_GLO_CFG_FLOW_DROP_KA BIT(8) -+#define MTK_PPE_GLO_CFG_FLOW_DROP_UPDATE BIT(9) -+#define MTK_PPE_GLO_CFG_UDP_LITE_EN BIT(10) -+#define MTK_PPE_GLO_CFG_UDP_LEN_DROP BIT(11) -+#define MTK_PPE_GLO_CFG_MCAST_ENTRIES GNEMASK(13, 12) -+#define MTK_PPE_GLO_CFG_BUSY BIT(31) -+ -+#define MTK_PPE_FLOW_CFG 0x204 -+#define MTK_PPE_FLOW_CFG_IP4_TCP_FRAG BIT(6) -+#define MTK_PPE_FLOW_CFG_IP4_UDP_FRAG BIT(7) -+#define MTK_PPE_FLOW_CFG_IP6_3T_ROUTE BIT(8) -+#define MTK_PPE_FLOW_CFG_IP6_5T_ROUTE BIT(9) -+#define MTK_PPE_FLOW_CFG_IP6_6RD BIT(10) -+#define MTK_PPE_FLOW_CFG_IP4_NAT BIT(12) -+#define MTK_PPE_FLOW_CFG_IP4_NAPT BIT(13) -+#define MTK_PPE_FLOW_CFG_IP4_DSLITE BIT(14) -+#define MTK_PPE_FLOW_CFG_L2_BRIDGE BIT(15) -+#define MTK_PPE_FLOW_CFG_IP_PROTO_BLACKLIST BIT(16) -+#define MTK_PPE_FLOW_CFG_IP4_NAT_FRAG BIT(17) -+#define MTK_PPE_FLOW_CFG_IP4_HASH_FLOW_LABEL BIT(18) -+#define MTK_PPE_FLOW_CFG_IP4_HASH_GRE_KEY BIT(19) -+#define MTK_PPE_FLOW_CFG_IP6_HASH_GRE_KEY BIT(20) -+ -+#define MTK_PPE_IP_PROTO_CHK 0x208 -+#define MTK_PPE_IP_PROTO_CHK_IPV4 GENMASK(15, 0) -+#define MTK_PPE_IP_PROTO_CHK_IPV6 GENMASK(31, 16) -+ -+#define MTK_PPE_TB_CFG 0x21c -+#define MTK_PPE_TB_CFG_ENTRY_NUM GENMASK(2, 0) -+#define MTK_PPE_TB_CFG_ENTRY_80B BIT(3) -+#define MTK_PPE_TB_CFG_SEARCH_MISS GENMASK(5, 4) -+#define MTK_PPE_TB_CFG_AGE_PREBIND BIT(6) -+#define MTK_PPE_TB_CFG_AGE_NON_L4 BIT(7) -+#define MTK_PPE_TB_CFG_AGE_UNBIND BIT(8) -+#define MTK_PPE_TB_CFG_AGE_TCP BIT(9) -+#define MTK_PPE_TB_CFG_AGE_UDP BIT(10) -+#define MTK_PPE_TB_CFG_AGE_TCP_FIN BIT(11) -+#define MTK_PPE_TB_CFG_KEEPALIVE GENMASK(13, 12) -+#define MTK_PPE_TB_CFG_HASH_MODE GENMASK(15, 14) -+#define MTK_PPE_TB_CFG_SCAN_MODE GENMASK(17, 16) -+#define MTK_PPE_TB_CFG_HASH_DEBUG GENMASK(19, 18) -+ -+enum { -+ MTK_PPE_SCAN_MODE_DISABLED, -+ MTK_PPE_SCAN_MODE_CHECK_AGE, -+ MTK_PPE_SCAN_MODE_KEEPALIVE_AGE, -+}; -+ -+enum { -+ MTK_PPE_KEEPALIVE_DISABLE, -+ MTK_PPE_KEEPALIVE_UNICAST_CPU, -+ MTK_PPE_KEEPALIVE_DUP_CPU = 3, -+}; -+ -+enum { -+ MTK_PPE_SEARCH_MISS_ACTION_DROP, -+ MTK_PPE_SEARCH_MISS_ACTION_FORWARD = 2, -+ MTK_PPE_SEARCH_MISS_ACTION_FORWARD_BUILD = 3, -+}; -+ -+#define MTK_PPE_TB_BASE 0x220 -+ -+#define MTK_PPE_TB_USED 0x224 -+#define MTK_PPE_TB_USED_NUM GENMASK(13, 0) -+ -+#define MTK_PPE_BIND_RATE 0x228 -+#define MTK_PPE_BIND_RATE_BIND GENMASK(15, 0) -+#define MTK_PPE_BIND_RATE_PREBIND GENMASK(31, 16) -+ -+#define MTK_PPE_BIND_LIMIT0 0x22c -+#define MTK_PPE_BIND_LIMIT0_QUARTER GENMASK(13, 0) -+#define MTK_PPE_BIND_LIMIT0_HALF GENMASK(29, 16) -+ -+#define MTK_PPE_BIND_LIMIT1 0x230 -+#define MTK_PPE_BIND_LIMIT1_FULL GENMASK(13, 0) -+#define MTK_PPE_BIND_LIMIT1_NON_L4 GENMASK(23, 16) -+ -+#define MTK_PPE_KEEPALIVE 0x234 -+#define MTK_PPE_KEEPALIVE_TIME GENMASK(15, 0) -+#define MTK_PPE_KEEPALIVE_TIME_TCP GENMASK(23, 16) -+#define MTK_PPE_KEEPALIVE_TIME_UDP GENMASK(31, 24) -+ -+#define MTK_PPE_UNBIND_AGE 0x238 -+#define MTK_PPE_UNBIND_AGE_MIN_PACKETS GENMASK(31, 16) -+#define MTK_PPE_UNBIND_AGE_DELTA GENMASK(7, 0) -+ -+#define MTK_PPE_BIND_AGE0 0x23c -+#define MTK_PPE_BIND_AGE0_DELTA_NON_L4 GENMASK(30, 16) -+#define MTK_PPE_BIND_AGE0_DELTA_UDP GENMASK(14, 0) -+ -+#define MTK_PPE_BIND_AGE1 0x240 -+#define MTK_PPE_BIND_AGE1_DELTA_TCP_FIN GENMASK(30, 16) -+#define MTK_PPE_BIND_AGE1_DELTA_TCP GENMASK(14, 0) -+ -+#define MTK_PPE_HASH_SEED 0x244 -+ -+#define MTK_PPE_DEFAULT_CPU_PORT 0x248 -+#define MTK_PPE_DEFAULT_CPU_PORT_MASK(_n) (GENMASK(2, 0) << ((_n) * 4)) -+ -+#define MTK_PPE_MTU_DROP 0x308 -+ -+#define MTK_PPE_VLAN_MTU0 0x30c -+#define MTK_PPE_VLAN_MTU0_NONE GENMASK(13, 0) -+#define MTK_PPE_VLAN_MTU0_1TAG GENMASK(29, 16) -+ -+#define MTK_PPE_VLAN_MTU1 0x310 -+#define MTK_PPE_VLAN_MTU1_2TAG GENMASK(13, 0) -+#define MTK_PPE_VLAN_MTU1_3TAG GENMASK(29, 16) -+ -+#define MTK_PPE_VPM_TPID 0x318 -+ -+#define MTK_PPE_CACHE_CTL 0x320 -+#define MTK_PPE_CACHE_CTL_EN BIT(0) -+#define MTK_PPE_CACHE_CTL_LOCK_CLR BIT(4) -+#define MTK_PPE_CACHE_CTL_REQ BIT(8) -+#define MTK_PPE_CACHE_CTL_CLEAR BIT(9) -+#define MTK_PPE_CACHE_CTL_CMD GENMASK(13, 12) -+ -+#define MTK_PPE_MIB_CFG 0x334 -+#define MTK_PPE_MIB_CFG_EN BIT(0) -+#define MTK_PPE_MIB_CFG_RD_CLR BIT(1) -+ -+#define MTK_PPE_MIB_TB_BASE 0x338 -+ -+#define MTK_PPE_MIB_CACHE_CTL 0x350 -+#define MTK_PPE_MIB_CACHE_CTL_EN BIT(0) -+#define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2) -+ -+#endif diff --git a/target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch b/target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch deleted file mode 100644 index 599757d413..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-33-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch +++ /dev/null @@ -1,568 +0,0 @@ -From: Felix Fietkau -Date: Wed, 24 Mar 2021 02:30:54 +0100 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add flow offloading support - -This adds support for offloading IPv4 routed flows, including SNAT/DNAT, -one VLAN, PPPoE and DSA. - -Signed-off-by: Felix Fietkau -Signed-off-by: Pablo Neira Ayuso ---- - create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_offload.c - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -4,5 +4,5 @@ - # - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o --mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o -+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o - obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2834,6 +2834,7 @@ static const struct net_device_ops mtk_n - #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = mtk_poll_controller, - #endif -+ .ndo_setup_tc = mtk_eth_setup_tc, - }; - - static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) -@@ -3092,6 +3093,10 @@ static int mtk_probe(struct platform_dev - eth->base + MTK_ETH_PPE_BASE, 2); - if (err) - goto err_free_dev; -+ -+ err = mtk_eth_offload_init(eth); -+ if (err) -+ goto err_free_dev; - } - - for (i = 0; i < MTK_MAX_DEVS; i++) { ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include "mtk_ppe.h" - - #define MTK_QDMA_PAGE_SIZE 2048 -@@ -40,7 +41,8 @@ - NETIF_F_HW_VLAN_CTAG_RX | \ - NETIF_F_SG | NETIF_F_TSO | \ - NETIF_F_TSO6 | \ -- NETIF_F_IPV6_CSUM) -+ NETIF_F_IPV6_CSUM |\ -+ NETIF_F_HW_TC) - #define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM) - #define NEXT_DESP_IDX(X, Y) (((X) + 1) & ((Y) - 1)) - -@@ -929,6 +931,7 @@ struct mtk_eth { - int ip_align; - - struct mtk_ppe ppe; -+ struct rhashtable flow_table; - }; - - /* struct mtk_mac - the structure that holds the info about the MACs of the -@@ -973,4 +976,9 @@ int mtk_gmac_sgmii_path_setup(struct mtk - int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); - int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id); - -+int mtk_eth_offload_init(struct mtk_eth *eth); -+int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, -+ void *type_data); -+ -+ - #endif /* MTK_ETH_H */ ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -0,0 +1,485 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2020 Felix Fietkau -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mtk_eth_soc.h" -+ -+struct mtk_flow_data { -+ struct ethhdr eth; -+ -+ union { -+ struct { -+ __be32 src_addr; -+ __be32 dst_addr; -+ } v4; -+ }; -+ -+ __be16 src_port; -+ __be16 dst_port; -+ -+ struct { -+ u16 id; -+ __be16 proto; -+ u8 num; -+ } vlan; -+ struct { -+ u16 sid; -+ u8 num; -+ } pppoe; -+}; -+ -+struct mtk_flow_entry { -+ struct rhash_head node; -+ unsigned long cookie; -+ u16 hash; -+}; -+ -+static const struct rhashtable_params mtk_flow_ht_params = { -+ .head_offset = offsetof(struct mtk_flow_entry, node), -+ .head_offset = offsetof(struct mtk_flow_entry, cookie), -+ .key_len = sizeof(unsigned long), -+ .automatic_shrinking = true, -+}; -+ -+static u32 -+mtk_eth_timestamp(struct mtk_eth *eth) -+{ -+ return mtk_r32(eth, 0x0010) & MTK_FOE_IB1_BIND_TIMESTAMP; -+} -+ -+static int -+mtk_flow_set_ipv4_addr(struct mtk_foe_entry *foe, struct mtk_flow_data *data, -+ bool egress) -+{ -+ return mtk_foe_entry_set_ipv4_tuple(foe, egress, -+ data->v4.src_addr, data->src_port, -+ data->v4.dst_addr, data->dst_port); -+} -+ -+static void -+mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth) -+{ -+ void *dest = eth + act->mangle.offset; -+ const void *src = &act->mangle.val; -+ -+ if (act->mangle.offset > 8) -+ return; -+ -+ if (act->mangle.mask == 0xffff) { -+ src += 2; -+ dest += 2; -+ } -+ -+ memcpy(dest, src, act->mangle.mask ? 2 : 4); -+} -+ -+ -+static int -+mtk_flow_mangle_ports(const struct flow_action_entry *act, -+ struct mtk_flow_data *data) -+{ -+ u32 val = ntohl(act->mangle.val); -+ -+ switch (act->mangle.offset) { -+ case 0: -+ if (act->mangle.mask == ~htonl(0xffff)) -+ data->dst_port = cpu_to_be16(val); -+ else -+ data->src_port = cpu_to_be16(val >> 16); -+ break; -+ case 2: -+ data->dst_port = cpu_to_be16(val); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_flow_mangle_ipv4(const struct flow_action_entry *act, -+ struct mtk_flow_data *data) -+{ -+ __be32 *dest; -+ -+ switch (act->mangle.offset) { -+ case offsetof(struct iphdr, saddr): -+ dest = &data->v4.src_addr; -+ break; -+ case offsetof(struct iphdr, daddr): -+ dest = &data->v4.dst_addr; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ memcpy(dest, &act->mangle.val, sizeof(u32)); -+ -+ return 0; -+} -+ -+static int -+mtk_flow_get_dsa_port(struct net_device **dev) -+{ -+#if IS_ENABLED(CONFIG_NET_DSA) -+ struct dsa_port *dp; -+ -+ dp = dsa_port_from_netdev(*dev); -+ if (IS_ERR(dp)) -+ return -ENODEV; -+ -+ if (dp->cpu_dp->tag_ops->proto != DSA_TAG_PROTO_MTK) -+ return -ENODEV; -+ -+ *dev = dp->cpu_dp->master; -+ -+ return dp->index; -+#else -+ return -ENODEV; -+#endif -+} -+ -+static int -+mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, -+ struct net_device *dev) -+{ -+ int pse_port, dsa_port; -+ -+ dsa_port = mtk_flow_get_dsa_port(&dev); -+ if (dsa_port >= 0) -+ mtk_foe_entry_set_dsa(foe, dsa_port); -+ -+ if (dev == eth->netdev[0]) -+ pse_port = 1; -+ else if (dev == eth->netdev[1]) -+ pse_port = 2; -+ else -+ return -EOPNOTSUPP; -+ -+ mtk_foe_entry_set_pse_port(foe, pse_port); -+ -+ return 0; -+} -+ -+static int -+mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) -+{ -+ struct flow_rule *rule = flow_cls_offload_flow_rule(f); -+ struct flow_action_entry *act; -+ struct mtk_flow_data data = {}; -+ struct mtk_foe_entry foe; -+ struct net_device *odev = NULL; -+ struct mtk_flow_entry *entry; -+ int offload_type = 0; -+ u16 addr_type = 0; -+ u32 timestamp; -+ u8 l4proto = 0; -+ int err = 0; -+ int hash; -+ int i; -+ -+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { -+ struct flow_match_meta match; -+ -+ flow_rule_match_meta(rule, &match); -+ } else { -+ return -EOPNOTSUPP; -+ } -+ -+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { -+ struct flow_match_control match; -+ -+ flow_rule_match_control(rule, &match); -+ addr_type = match.key->addr_type; -+ } else { -+ return -EOPNOTSUPP; -+ } -+ -+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { -+ struct flow_match_basic match; -+ -+ flow_rule_match_basic(rule, &match); -+ l4proto = match.key->ip_proto; -+ } else { -+ return -EOPNOTSUPP; -+ } -+ -+ flow_action_for_each(i, act, &rule->action) { -+ switch (act->id) { -+ case FLOW_ACTION_MANGLE: -+ if (act->mangle.htype == FLOW_ACT_MANGLE_HDR_TYPE_ETH) -+ mtk_flow_offload_mangle_eth(act, &data.eth); -+ break; -+ case FLOW_ACTION_REDIRECT: -+ odev = act->dev; -+ break; -+ case FLOW_ACTION_CSUM: -+ break; -+ case FLOW_ACTION_VLAN_PUSH: -+ if (data.vlan.num == 1 || -+ act->vlan.proto != htons(ETH_P_8021Q)) -+ return -EOPNOTSUPP; -+ -+ data.vlan.id = act->vlan.vid; -+ data.vlan.proto = act->vlan.proto; -+ data.vlan.num++; -+ break; -+ case FLOW_ACTION_PPPOE_PUSH: -+ if (data.pppoe.num == 1) -+ return -EOPNOTSUPP; -+ -+ data.pppoe.sid = act->pppoe.sid; -+ data.pppoe.num++; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ } -+ -+ switch (addr_type) { -+ case FLOW_DISSECTOR_KEY_IPV4_ADDRS: -+ offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ if (!is_valid_ether_addr(data.eth.h_source) || -+ !is_valid_ether_addr(data.eth.h_dest)) -+ return -EINVAL; -+ -+ err = mtk_foe_entry_prepare(&foe, offload_type, l4proto, 0, -+ data.eth.h_source, -+ data.eth.h_dest); -+ if (err) -+ return err; -+ -+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { -+ struct flow_match_ports ports; -+ -+ flow_rule_match_ports(rule, &ports); -+ data.src_port = ports.key->src; -+ data.dst_port = ports.key->dst; -+ } else { -+ return -EOPNOTSUPP; -+ } -+ -+ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { -+ struct flow_match_ipv4_addrs addrs; -+ -+ flow_rule_match_ipv4_addrs(rule, &addrs); -+ -+ data.v4.src_addr = addrs.key->src; -+ data.v4.dst_addr = addrs.key->dst; -+ -+ mtk_flow_set_ipv4_addr(&foe, &data, false); -+ } -+ -+ flow_action_for_each(i, act, &rule->action) { -+ if (act->id != FLOW_ACTION_MANGLE) -+ continue; -+ -+ switch (act->mangle.htype) { -+ case FLOW_ACT_MANGLE_HDR_TYPE_TCP: -+ case FLOW_ACT_MANGLE_HDR_TYPE_UDP: -+ err = mtk_flow_mangle_ports(act, &data); -+ break; -+ case FLOW_ACT_MANGLE_HDR_TYPE_IP4: -+ err = mtk_flow_mangle_ipv4(act, &data); -+ break; -+ case FLOW_ACT_MANGLE_HDR_TYPE_ETH: -+ /* handled earlier */ -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ if (err) -+ return err; -+ } -+ -+ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { -+ err = mtk_flow_set_ipv4_addr(&foe, &data, true); -+ if (err) -+ return err; -+ } -+ -+ if (data.vlan.num == 1) { -+ if (data.vlan.proto != htons(ETH_P_8021Q)) -+ return -EOPNOTSUPP; -+ -+ mtk_foe_entry_set_vlan(&foe, data.vlan.id); -+ } -+ if (data.pppoe.num == 1) -+ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); -+ -+ err = mtk_flow_set_output_device(eth, &foe, odev); -+ if (err) -+ return err; -+ -+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); -+ if (!entry) -+ return -ENOMEM; -+ -+ entry->cookie = f->cookie; -+ timestamp = mtk_eth_timestamp(eth); -+ hash = mtk_foe_entry_commit(ð->ppe, &foe, timestamp); -+ if (hash < 0) { -+ err = hash; -+ goto free; -+ } -+ -+ entry->hash = hash; -+ err = rhashtable_insert_fast(ð->flow_table, &entry->node, -+ mtk_flow_ht_params); -+ if (err < 0) -+ goto clear_flow; -+ -+ return 0; -+clear_flow: -+ mtk_foe_entry_clear(ð->ppe, hash); -+free: -+ kfree(entry); -+ return err; -+} -+ -+static int -+mtk_flow_offload_destroy(struct mtk_eth *eth, struct flow_cls_offload *f) -+{ -+ struct mtk_flow_entry *entry; -+ -+ entry = rhashtable_lookup(ð->flow_table, &f->cookie, -+ mtk_flow_ht_params); -+ if (!entry) -+ return -ENOENT; -+ -+ mtk_foe_entry_clear(ð->ppe, entry->hash); -+ rhashtable_remove_fast(ð->flow_table, &entry->node, -+ mtk_flow_ht_params); -+ kfree(entry); -+ -+ return 0; -+} -+ -+static int -+mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) -+{ -+ struct mtk_flow_entry *entry; -+ int timestamp; -+ u32 idle; -+ -+ entry = rhashtable_lookup(ð->flow_table, &f->cookie, -+ mtk_flow_ht_params); -+ if (!entry) -+ return -ENOENT; -+ -+ timestamp = mtk_foe_entry_timestamp(ð->ppe, entry->hash); -+ if (timestamp < 0) -+ return -ETIMEDOUT; -+ -+ idle = mtk_eth_timestamp(eth) - timestamp; -+ f->stats.lastused = jiffies - idle * HZ; -+ -+ return 0; -+} -+ -+static int -+mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) -+{ -+ struct flow_cls_offload *cls = type_data; -+ struct net_device *dev = cb_priv; -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ -+ if (!tc_can_offload(dev)) -+ return -EOPNOTSUPP; -+ -+ if (type != TC_SETUP_CLSFLOWER) -+ return -EOPNOTSUPP; -+ -+ switch (cls->command) { -+ case FLOW_CLS_REPLACE: -+ return mtk_flow_offload_replace(eth, cls); -+ case FLOW_CLS_DESTROY: -+ return mtk_flow_offload_destroy(eth, cls); -+ case FLOW_CLS_STATS: -+ return mtk_flow_offload_stats(eth, cls); -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f) -+{ -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ static LIST_HEAD(block_cb_list); -+ struct flow_block_cb *block_cb; -+ flow_setup_cb_t *cb; -+ -+ if (!eth->ppe.foe_table) -+ return -EOPNOTSUPP; -+ -+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) -+ return -EOPNOTSUPP; -+ -+ cb = mtk_eth_setup_tc_block_cb; -+ f->driver_block_list = &block_cb_list; -+ -+ switch (f->command) { -+ case FLOW_BLOCK_BIND: -+ block_cb = flow_block_cb_lookup(f->block, cb, dev); -+ if (block_cb) { -+ flow_block_cb_incref(block_cb); -+ return 0; -+ } -+ block_cb = flow_block_cb_alloc(cb, dev, dev, NULL); -+ if (IS_ERR(block_cb)) -+ return PTR_ERR(block_cb); -+ -+ flow_block_cb_add(block_cb, f); -+ list_add_tail(&block_cb->driver_list, &block_cb_list); -+ return 0; -+ case FLOW_BLOCK_UNBIND: -+ block_cb = flow_block_cb_lookup(f->block, cb, dev); -+ if (!block_cb) -+ return -ENOENT; -+ -+ if (flow_block_cb_decref(block_cb)) { -+ flow_block_cb_remove(block_cb, f); -+ list_del(&block_cb->driver_list); -+ } -+ return 0; -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, -+ void *type_data) -+{ -+ if (type == TC_SETUP_FT) -+ return mtk_eth_setup_tc_block(dev, type_data); -+ -+ return -EOPNOTSUPP; -+} -+ -+int mtk_eth_offload_init(struct mtk_eth *eth) -+{ -+ if (!eth->ppe.foe_table) -+ return 0; -+ -+ return rhashtable_init(ð->flow_table, &mtk_flow_ht_params); -+} diff --git a/target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch b/target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch deleted file mode 100644 index 2cea1ebe24..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-34-docs-nf_flowtable-update-documentation-with-enhancem.patch +++ /dev/null @@ -1,236 +0,0 @@ -From: Pablo Neira Ayuso -Date: Wed, 24 Mar 2021 02:30:55 +0100 -Subject: [PATCH] docs: nf_flowtable: update documentation with - enhancements - -This patch updates the flowtable documentation to describe recent -enhancements: - -- Offload action is available after the first packets go through the - classic forwarding path. -- IPv4 and IPv6 are supported. Only TCP and UDP layer 4 are supported at - this stage. -- Tuple has been augmented to track VLAN id and PPPoE session id. -- Bridge and IP forwarding integration, including bridge VLAN filtering - support. -- Hardware offload support. -- Describe the [OFFLOAD] and [HW_OFFLOAD] tags in the conntrack table - listing. -- Replace 'flow offload' by 'flow add' in example rulesets (preferred - syntax). -- Describe existing cache limitations. - -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/Documentation/networking/nf_flowtable.rst -+++ b/Documentation/networking/nf_flowtable.rst -@@ -4,35 +4,38 @@ - Netfilter's flowtable infrastructure - ==================================== - --This documentation describes the software flowtable infrastructure available in --Netfilter since Linux kernel 4.16. -+This documentation describes the Netfilter flowtable infrastructure which allows -+you to define a fastpath through the flowtable datapath. This infrastructure -+also provides hardware offload support. The flowtable supports for the layer 3 -+IPv4 and IPv6 and the layer 4 TCP and UDP protocols. - - Overview - -------- - --Initial packets follow the classic forwarding path, once the flow enters the --established state according to the conntrack semantics (ie. we have seen traffic --in both directions), then you can decide to offload the flow to the flowtable --from the forward chain via the 'flow offload' action available in nftables. -- --Packets that find an entry in the flowtable (ie. flowtable hit) are sent to the --output netdevice via neigh_xmit(), hence, they bypass the classic forwarding --path (the visible effect is that you do not see these packets from any of the --netfilter hooks coming after the ingress). In case of flowtable miss, the packet --follows the classic forward path. -- --The flowtable uses a resizable hashtable, lookups are based on the following --7-tuple selectors: source, destination, layer 3 and layer 4 protocols, source --and destination ports and the input interface (useful in case there are several --conntrack zones in place). -- --Flowtables are populated via the 'flow offload' nftables action, so the user can --selectively specify what flows are placed into the flow table. Hence, packets --follow the classic forwarding path unless the user explicitly instruct packets --to use this new alternative forwarding path via nftables policy. -+Once the first packet of the flow successfully goes through the IP forwarding -+path, from the second packet on, you might decide to offload the flow to the -+flowtable through your ruleset. The flowtable infrastructure provides a rule -+action that allows you to specify when to add a flow to the flowtable. -+ -+A packet that finds a matching entry in the flowtable (ie. flowtable hit) is -+transmitted to the output netdevice via neigh_xmit(), hence, packets bypass the -+classic IP forwarding path (the visible effect is that you do not see these -+packets from any of the Netfilter hooks coming after ingress). In case that -+there is no matching entry in the flowtable (ie. flowtable miss), the packet -+follows the classic IP forwarding path. -+ -+The flowtable uses a resizable hashtable. Lookups are based on the following -+n-tuple selectors: layer 2 protocol encapsulation (VLAN and PPPoE), layer 3 -+source and destination, layer 4 source and destination ports and the input -+interface (useful in case there are several conntrack zones in place). -+ -+The 'flow add' action allows you to populate the flowtable, the user selectively -+specifies what flows are placed into the flowtable. Hence, packets follow the -+classic IP forwarding path unless the user explicitly instruct flows to use this -+new alternative forwarding path via policy. - --This is represented in Fig.1, which describes the classic forwarding path --including the Netfilter hooks and the flowtable fastpath bypass. -+The flowtable datapath is represented in Fig.1, which describes the classic IP -+forwarding path including the Netfilter hooks and the flowtable fastpath bypass. - - :: - -@@ -67,11 +70,13 @@ including the Netfilter hooks and the fl - Fig.1 Netfilter hooks and flowtable interactions - - The flowtable entry also stores the NAT configuration, so all packets are --mangled according to the NAT policy that matches the initial packets that went --through the classic forwarding path. The TTL is decremented before calling --neigh_xmit(). Fragmented traffic is passed up to follow the classic forwarding --path given that the transport selectors are missing, therefore flowtable lookup --is not possible. -+mangled according to the NAT policy that is specified from the classic IP -+forwarding path. The TTL is decremented before calling neigh_xmit(). Fragmented -+traffic is passed up to follow the classic IP forwarding path given that the -+transport header is missing, in this case, flowtable lookups are not possible. -+TCP RST and FIN packets are also passed up to the classic IP forwarding path to -+release the flow gracefully. Packets that exceed the MTU are also passed up to -+the classic forwarding path to report packet-too-big ICMP errors to the sender. - - Example configuration - --------------------- -@@ -85,7 +90,7 @@ flowtable and add one rule to your forwa - } - chain y { - type filter hook forward priority 0; policy accept; -- ip protocol tcp flow offload @f -+ ip protocol tcp flow add @f - counter packets 0 bytes 0 - } - } -@@ -103,6 +108,117 @@ flow is offloaded, you will observe that - does not get updated for the packets that are being forwarded through the - forwarding bypass. - -+You can identify offloaded flows through the [OFFLOAD] tag when listing your -+connection tracking table. -+ -+:: -+ # conntrack -L -+ tcp 6 src=10.141.10.2 dst=192.168.10.2 sport=52728 dport=5201 src=192.168.10.2 dst=192.168.10.1 sport=5201 dport=52728 [OFFLOAD] mark=0 use=2 -+ -+ -+Layer 2 encapsulation -+--------------------- -+ -+Since Linux kernel 5.13, the flowtable infrastructure discovers the real -+netdevice behind VLAN and PPPoE netdevices. The flowtable software datapath -+parses the VLAN and PPPoE layer 2 headers to extract the ethertype and the -+VLAN ID / PPPoE session ID which are used for the flowtable lookups. The -+flowtable datapath also deals with layer 2 decapsulation. -+ -+You do not need to add the PPPoE and the VLAN devices to your flowtable, -+instead the real device is sufficient for the flowtable to track your flows. -+ -+Bridge and IP forwarding -+------------------------ -+ -+Since Linux kernel 5.13, you can add bridge ports to the flowtable. The -+flowtable infrastructure discovers the topology behind the bridge device. This -+allows the flowtable to define a fastpath bypass between the bridge ports -+(represented as eth1 and eth2 in the example figure below) and the gateway -+device (represented as eth0) in your switch/router. -+ -+:: -+ fastpath bypass -+ .-------------------------. -+ / \ -+ | IP forwarding | -+ | / \ \/ -+ | br0 eth0 ..... eth0 -+ . / \ *host B* -+ -> eth1 eth2 -+ . *switch/router* -+ . -+ . -+ eth0 -+ *host A* -+ -+The flowtable infrastructure also supports for bridge VLAN filtering actions -+such as PVID and untagged. You can also stack a classic VLAN device on top of -+your bridge port. -+ -+If you would like that your flowtable defines a fastpath between your bridge -+ports and your IP forwarding path, you have to add your bridge ports (as -+represented by the real netdevice) to your flowtable definition. -+ -+Counters -+-------- -+ -+The flowtable can synchronize packet and byte counters with the existing -+connection tracking entry by specifying the counter statement in your flowtable -+definition, e.g. -+ -+:: -+ table inet x { -+ flowtable f { -+ hook ingress priority 0; devices = { eth0, eth1 }; -+ counter -+ } -+ ... -+ } -+ -+Counter support is available since Linux kernel 5.7. -+ -+Hardware offload -+---------------- -+ -+If your network device provides hardware offload support, you can turn it on by -+means of the 'offload' flag in your flowtable definition, e.g. -+ -+:: -+ table inet x { -+ flowtable f { -+ hook ingress priority 0; devices = { eth0, eth1 }; -+ flags offload; -+ } -+ ... -+ } -+ -+There is a workqueue that adds the flows to the hardware. Note that a few -+packets might still run over the flowtable software path until the workqueue has -+a chance to offload the flow to the network device. -+ -+You can identify hardware offloaded flows through the [HW_OFFLOAD] tag when -+listing your connection tracking table. Please, note that the [OFFLOAD] tag -+refers to the software offload mode, so there is a distinction between [OFFLOAD] -+which refers to the software flowtable fastpath and [HW_OFFLOAD] which refers -+to the hardware offload datapath being used by the flow. -+ -+The flowtable hardware offload infrastructure also supports for the DSA -+(Distributed Switch Architecture). -+ -+Limitations -+----------- -+ -+The flowtable behaves like a cache. The flowtable entries might get stale if -+either the destination MAC address or the egress netdevice that is used for -+transmission changes. -+ -+This might be a problem if: -+ -+- You run the flowtable in software mode and you combine bridge and IP -+ forwarding in your setup. -+- Hardware offload is enabled. -+ - More reading - ------------ - diff --git a/target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch b/target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch deleted file mode 100644 index 66cd053cd1..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-35-net-ethernet-mediatek-ppe-fix-busy-wait-loop.patch +++ /dev/null @@ -1,72 +0,0 @@ -From c5d66587b8900201e1530b7c18d41e87bd5812f4 Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Thu, 15 Apr 2021 17:37:48 -0700 -Subject: [PATCH] net: ethernet: mediatek: ppe: fix busy wait loop - -The intention is for the loop to timeout if the body does not succeed. -The current logic calls time_is_before_jiffies(timeout) which is false -until after the timeout, so the loop body never executes. - -Fix by using readl_poll_timeout as a more standard and less error-prone -solution. - -Fixes: ba37b7caf1ed ("net: ethernet: mtk_eth_soc: add support for initializing the PPE") -Signed-off-by: Ilya Lipnitskiy -Cc: Felix Fietkau -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_ppe.c | 20 +++++++++----------- - drivers/net/ethernet/mediatek/mtk_ppe.h | 1 + - 2 files changed, 10 insertions(+), 11 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -2,9 +2,8 @@ - /* Copyright (C) 2020 Felix Fietkau */ - - #include --#include --#include - #include -+#include - #include - #include - #include "mtk_ppe.h" -@@ -44,18 +43,17 @@ static u32 ppe_clear(struct mtk_ppe *ppe - - static int mtk_ppe_wait_busy(struct mtk_ppe *ppe) - { -- unsigned long timeout = jiffies + HZ; -- -- while (time_is_before_jiffies(timeout)) { -- if (!(ppe_r32(ppe, MTK_PPE_GLO_CFG) & MTK_PPE_GLO_CFG_BUSY)) -- return 0; -+ int ret; -+ u32 val; - -- usleep_range(10, 20); -- } -+ ret = readl_poll_timeout(ppe->base + MTK_PPE_GLO_CFG, val, -+ !(val & MTK_PPE_GLO_CFG_BUSY), -+ 20, MTK_PPE_WAIT_TIMEOUT_US); - -- dev_err(ppe->dev, "PPE table busy"); -+ if (ret) -+ dev_err(ppe->dev, "PPE table busy"); - -- return -ETIMEDOUT; -+ return ret; - } - - static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) ---- a/drivers/net/ethernet/mediatek/mtk_ppe.h -+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -12,6 +12,7 @@ - #define MTK_PPE_ENTRIES_SHIFT 3 - #define MTK_PPE_ENTRIES (1024 << MTK_PPE_ENTRIES_SHIFT) - #define MTK_PPE_HASH_MASK (MTK_PPE_ENTRIES - 1) -+#define MTK_PPE_WAIT_TIMEOUT_US 1000000 - - #define MTK_FOE_IB1_UNBIND_TIMESTAMP GENMASK(7, 0) - #define MTK_FOE_IB1_UNBIND_PACKETS GENMASK(23, 8) diff --git a/target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch b/target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch deleted file mode 100644 index de376bf78d..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-36-net-ethernet-mediatek-fix-a-typo-bug-in-flow-offload.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 6ecaf81d4ac6365f9284f9d68d74f7c209e74f98 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Sat, 17 Apr 2021 15:29:04 +0800 -Subject: [PATCH] net: ethernet: mediatek: fix a typo bug in flow offloading - -Issue was traffic problems after a while with increased ping times if -flow offload is active. It turns out that key_offset with cookie is -needed in rhashtable_params but was re-assigned to head_offset. -Fix the assignment. - -Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support") -Signed-off-by: DENG Qingfang -Tested-by: Frank Wunderlich -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -44,7 +44,7 @@ struct mtk_flow_entry { - - static const struct rhashtable_params mtk_flow_ht_params = { - .head_offset = offsetof(struct mtk_flow_entry, node), -- .head_offset = offsetof(struct mtk_flow_entry, cookie), -+ .key_offset = offsetof(struct mtk_flow_entry, cookie), - .key_len = sizeof(unsigned long), - .automatic_shrinking = true, - }; diff --git a/target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch b/target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch deleted file mode 100644 index e99302ecda..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-38-net-ethernet-mtk_eth_soc-unmap-RX-data-before-callin.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 5196c417854942e218a59ec87bf7d414b3bd581e Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:20:55 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: unmap RX data before calling - build_skb - -Since build_skb accesses the data area (for initializing shinfo), dma unmap -needs to happen before that call - -Signed-off-by: Felix Fietkau -[Ilya: split build_skb cleanup fix into a separate commit] -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1319,6 +1319,9 @@ static int mtk_poll_rx(struct napi_struc - goto release_desc; - } - -+ dma_unmap_single(eth->dev, trxd.rxd1, -+ ring->buf_size, DMA_FROM_DEVICE); -+ - /* receive data */ - skb = build_skb(data, ring->frag_size); - if (unlikely(!skb)) { -@@ -1328,8 +1331,6 @@ static int mtk_poll_rx(struct napi_struc - } - skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); - -- dma_unmap_single(eth->dev, trxd.rxd1, -- ring->buf_size, DMA_FROM_DEVICE); - pktlen = RX_DMA_GET_PLEN0(trxd.rxd2); - skb->dev = netdev; - skb_put(skb, pktlen); diff --git a/target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch b/target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch deleted file mode 100644 index a82518882a..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-39-net-ethernet-mtk_eth_soc-fix-build_skb-cleanup.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 787082ab9f7be4711e52f67c388535eda74a1269 Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Thu, 22 Apr 2021 22:20:56 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: fix build_skb cleanup - -In case build_skb fails, call skb_free_frag on the correct pointer. Also -update the DMA structures with the new mapping before exiting, because -the mapping was successful - -Suggested-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1325,9 +1325,9 @@ static int mtk_poll_rx(struct napi_struc - /* receive data */ - skb = build_skb(data, ring->frag_size); - if (unlikely(!skb)) { -- skb_free_frag(new_data); -+ skb_free_frag(data); - netdev->stats.rx_dropped++; -- goto release_desc; -+ goto skip_rx; - } - skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); - -@@ -1347,6 +1347,7 @@ static int mtk_poll_rx(struct napi_struc - skb_record_rx_queue(skb, 0); - napi_gro_receive(napi, skb); - -+skip_rx: - ring->data[idx] = new_data; - rxd->rxd1 = (unsigned int)dma_addr; - diff --git a/target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch b/target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch deleted file mode 100644 index 5972b9afa7..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-40-net-ethernet-mtk_eth_soc-use-napi_consume_skb.patch +++ /dev/null @@ -1,77 +0,0 @@ -From c30c4a82739090a2de4a4e3f245355ea4fb3ec14 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:20:57 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: use napi_consume_skb - -Should improve performance, since it can use bulk free - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 19 ++++++++++++------- - 1 file changed, 12 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -879,7 +879,8 @@ static int txd_to_idx(struct mtk_tx_ring - return ((void *)dma - (void *)ring->dma) / sizeof(*dma); - } - --static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf) -+static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf, -+ bool napi) - { - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { - if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) { -@@ -911,8 +912,12 @@ static void mtk_tx_unmap(struct mtk_eth - - tx_buf->flags = 0; - if (tx_buf->skb && -- (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC)) -- dev_kfree_skb_any(tx_buf->skb); -+ (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC)) { -+ if (napi) -+ napi_consume_skb(tx_buf->skb, napi); -+ else -+ dev_kfree_skb_any(tx_buf->skb); -+ } - tx_buf->skb = NULL; - } - -@@ -1090,7 +1095,7 @@ err_dma: - tx_buf = mtk_desc_to_tx_buf(ring, itxd); - - /* unmap dma */ -- mtk_tx_unmap(eth, tx_buf); -+ mtk_tx_unmap(eth, tx_buf, false); - - itxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -@@ -1409,7 +1414,7 @@ static int mtk_poll_tx_qdma(struct mtk_e - done[mac]++; - budget--; - } -- mtk_tx_unmap(eth, tx_buf); -+ mtk_tx_unmap(eth, tx_buf, true); - - ring->last_free = desc; - atomic_inc(&ring->free_count); -@@ -1446,7 +1451,7 @@ static int mtk_poll_tx_pdma(struct mtk_e - budget--; - } - -- mtk_tx_unmap(eth, tx_buf); -+ mtk_tx_unmap(eth, tx_buf, true); - - desc = &ring->dma[cpu]; - ring->last_free = desc; -@@ -1648,7 +1653,7 @@ static void mtk_tx_clean(struct mtk_eth - - if (ring->buf) { - for (i = 0; i < MTK_DMA_SIZE; i++) -- mtk_tx_unmap(eth, &ring->buf[i]); -+ mtk_tx_unmap(eth, &ring->buf[i], false); - kfree(ring->buf); - ring->buf = NULL; - } diff --git a/target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch b/target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch deleted file mode 100644 index 7ebc3fa903..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-41-net-ethernet-mtk_eth_soc-reduce-MDIO-bus-access-late.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 3630d519d7c3eab92567658690e44ffe0517d109 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:20:58 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: reduce MDIO bus access latency - -usleep_range often ends up sleeping much longer than the 10-20us provided -as a range here. This causes significant latency in mdio bus acceses, -which easily adds multiple seconds to the boot time on MT7621 when polling -DSA slave ports. -Use cond_resched instead of usleep_range, since the MDIO access does not -take much time - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -86,7 +86,7 @@ static int mtk_mdio_busy_wait(struct mtk - return 0; - if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT)) - break; -- usleep_range(10, 20); -+ cond_resched(); - } - - dev_err(eth->dev, "mdio: MDIO timeout\n"); diff --git a/target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch b/target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch deleted file mode 100644 index 56d4a82824..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-42-net-ethernet-mtk_eth_soc-remove-unnecessary-TX-queue.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 16ef670789b252b221700adc413497ed2f941d8a Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:20:59 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: remove unnecessary TX queue stops - -When running short on descriptors, only stop the queue for the netdev that -tx was attempted for. By the time something tries to send on the other -netdev, the ring might have some more room already. - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 ++------------- - 1 file changed, 2 insertions(+), 13 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1152,17 +1152,6 @@ static void mtk_wake_queue(struct mtk_et - } - } - --static void mtk_stop_queue(struct mtk_eth *eth) --{ -- int i; -- -- for (i = 0; i < MTK_MAC_COUNT; i++) { -- if (!eth->netdev[i]) -- continue; -- netif_stop_queue(eth->netdev[i]); -- } --} -- - static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct mtk_mac *mac = netdev_priv(dev); -@@ -1183,7 +1172,7 @@ static netdev_tx_t mtk_start_xmit(struct - - tx_num = mtk_cal_txd_req(skb); - if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { -- mtk_stop_queue(eth); -+ netif_stop_queue(dev); - netif_err(eth, tx_queued, dev, - "Tx Ring full when queue awake!\n"); - spin_unlock(ð->page_lock); -@@ -1209,7 +1198,7 @@ static netdev_tx_t mtk_start_xmit(struct - goto drop; - - if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) -- mtk_stop_queue(eth); -+ netif_stop_queue(dev); - - spin_unlock(ð->page_lock); - diff --git a/target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch b/target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch deleted file mode 100644 index a192250e28..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-43-net-ethernet-mtk_eth_soc-use-larger-burst-size-for-Q.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 59555a8d0dd39bf60b7ca1ba5e7393d293f7398d Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:00 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: use larger burst size for QDMA TX - -Improves tx performance - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2214,7 +2214,7 @@ static int mtk_start_dma(struct mtk_eth - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { - mtk_w32(eth, - MTK_TX_WB_DDONE | MTK_TX_DMA_EN | -- MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO | -+ MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | - MTK_RX_DMA_EN | MTK_RX_2B_OFFSET | - MTK_RX_BT_32DWORDS, - MTK_QDMA_GLO_CFG); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -202,7 +202,7 @@ - #define MTK_RX_BT_32DWORDS (3 << 11) - #define MTK_NDP_CO_PRO BIT(10) - #define MTK_TX_WB_DDONE BIT(6) --#define MTK_DMA_SIZE_16DWORDS (2 << 4) -+#define MTK_TX_BT_32DWORDS (3 << 4) - #define MTK_RX_DMA_BUSY BIT(3) - #define MTK_TX_DMA_BUSY BIT(1) - #define MTK_RX_DMA_EN BIT(2) diff --git a/target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch b/target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch deleted file mode 100644 index d695f0fb8a..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-44-net-ethernet-mtk_eth_soc-increase-DMA-ring-sizes.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6b4423b258b91032c50a5efca15d3d9bb194ea1d Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:01 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: increase DMA ring sizes - -256 descriptors is not enough for multi-gigabit traffic under load on -MT7622. Bump it to 512 to improve performance. - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -21,7 +21,7 @@ - #define MTK_QDMA_PAGE_SIZE 2048 - #define MTK_MAX_RX_LENGTH 1536 - #define MTK_TX_DMA_BUF_LEN 0x3fff --#define MTK_DMA_SIZE 256 -+#define MTK_DMA_SIZE 512 - #define MTK_NAPI_WEIGHT 64 - #define MTK_MAC_COUNT 2 - #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) diff --git a/target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch b/target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch deleted file mode 100644 index 207d8397d8..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-45-net-ethernet-mtk_eth_soc-implement-dynamic-interrupt.patch +++ /dev/null @@ -1,313 +0,0 @@ -From e9229ffd550b2d8c4997c67a501dbc3919fd4e26 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:02 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: implement dynamic interrupt - moderation - -Reduces the number of interrupts under load - -Signed-off-by: Felix Fietkau -[Ilya: add documentation for new struct fields] -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/Kconfig | 1 + - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 96 +++++++++++++++++++-- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 41 +++++++-- - 3 files changed, 124 insertions(+), 14 deletions(-) - ---- a/drivers/net/ethernet/mediatek/Kconfig -+++ b/drivers/net/ethernet/mediatek/Kconfig -@@ -10,6 +10,7 @@ if NET_VENDOR_MEDIATEK - config NET_MEDIATEK_SOC - tristate "MediaTek SoC Gigabit Ethernet support" - select PHYLINK -+ select DIMLIB - help - This driver supports the gigabit ethernet MACs in the - MediaTek SoC family. ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1254,12 +1254,13 @@ static void mtk_update_rx_cpu_idx(struct - static int mtk_poll_rx(struct napi_struct *napi, int budget, - struct mtk_eth *eth) - { -+ struct dim_sample dim_sample = {}; - struct mtk_rx_ring *ring; - int idx; - struct sk_buff *skb; - u8 *data, *new_data; - struct mtk_rx_dma *rxd, trxd; -- int done = 0; -+ int done = 0, bytes = 0; - - while (done < budget) { - struct net_device *netdev; -@@ -1333,6 +1334,7 @@ static int mtk_poll_rx(struct napi_struc - else - skb_checksum_none_assert(skb); - skb->protocol = eth_type_trans(skb, netdev); -+ bytes += pktlen; - - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && - (trxd.rxd2 & RX_DMA_VTAG)) -@@ -1365,6 +1367,12 @@ rx_done: - mtk_update_rx_cpu_idx(eth); - } - -+ eth->rx_packets += done; -+ eth->rx_bytes += bytes; -+ dim_update_sample(eth->rx_events, eth->rx_packets, eth->rx_bytes, -+ &dim_sample); -+ net_dim(ð->rx_dim, dim_sample); -+ - return done; - } - -@@ -1457,6 +1465,7 @@ static int mtk_poll_tx_pdma(struct mtk_e - static int mtk_poll_tx(struct mtk_eth *eth, int budget) - { - struct mtk_tx_ring *ring = ð->tx_ring; -+ struct dim_sample dim_sample = {}; - unsigned int done[MTK_MAX_DEVS]; - unsigned int bytes[MTK_MAX_DEVS]; - int total = 0, i; -@@ -1474,8 +1483,14 @@ static int mtk_poll_tx(struct mtk_eth *e - continue; - netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); - total += done[i]; -+ eth->tx_packets += done[i]; -+ eth->tx_bytes += bytes[i]; - } - -+ dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, -+ &dim_sample); -+ net_dim(ð->tx_dim, dim_sample); -+ - if (mtk_queue_stopped(eth) && - (atomic_read(&ring->free_count) > ring->thresh)) - mtk_wake_queue(eth); -@@ -2150,6 +2165,7 @@ static irqreturn_t mtk_handle_irq_rx(int - { - struct mtk_eth *eth = _eth; - -+ eth->rx_events++; - if (likely(napi_schedule_prep(ð->rx_napi))) { - __napi_schedule(ð->rx_napi); - mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); -@@ -2162,6 +2178,7 @@ static irqreturn_t mtk_handle_irq_tx(int - { - struct mtk_eth *eth = _eth; - -+ eth->tx_events++; - if (likely(napi_schedule_prep(ð->tx_napi))) { - __napi_schedule(ð->tx_napi); - mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); -@@ -2346,6 +2363,9 @@ static int mtk_stop(struct net_device *d - napi_disable(ð->tx_napi); - napi_disable(ð->rx_napi); - -+ cancel_work_sync(ð->rx_dim.work); -+ cancel_work_sync(ð->tx_dim.work); -+ - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) - mtk_stop_dma(eth, MTK_QDMA_GLO_CFG); - mtk_stop_dma(eth, MTK_PDMA_GLO_CFG); -@@ -2398,6 +2418,64 @@ err_disable_clks: - return ret; - } - -+static void mtk_dim_rx(struct work_struct *work) -+{ -+ struct dim *dim = container_of(work, struct dim, work); -+ struct mtk_eth *eth = container_of(dim, struct mtk_eth, rx_dim); -+ struct dim_cq_moder cur_profile; -+ u32 val, cur; -+ -+ cur_profile = net_dim_get_rx_moderation(eth->rx_dim.mode, -+ dim->profile_ix); -+ spin_lock_bh(ð->dim_lock); -+ -+ val = mtk_r32(eth, MTK_PDMA_DELAY_INT); -+ val &= MTK_PDMA_DELAY_TX_MASK; -+ val |= MTK_PDMA_DELAY_RX_EN; -+ -+ cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK); -+ val |= cur << MTK_PDMA_DELAY_RX_PTIME_SHIFT; -+ -+ cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK); -+ val |= cur << MTK_PDMA_DELAY_RX_PINT_SHIFT; -+ -+ mtk_w32(eth, val, MTK_PDMA_DELAY_INT); -+ mtk_w32(eth, val, MTK_QDMA_DELAY_INT); -+ -+ spin_unlock_bh(ð->dim_lock); -+ -+ dim->state = DIM_START_MEASURE; -+} -+ -+static void mtk_dim_tx(struct work_struct *work) -+{ -+ struct dim *dim = container_of(work, struct dim, work); -+ struct mtk_eth *eth = container_of(dim, struct mtk_eth, tx_dim); -+ struct dim_cq_moder cur_profile; -+ u32 val, cur; -+ -+ cur_profile = net_dim_get_tx_moderation(eth->tx_dim.mode, -+ dim->profile_ix); -+ spin_lock_bh(ð->dim_lock); -+ -+ val = mtk_r32(eth, MTK_PDMA_DELAY_INT); -+ val &= MTK_PDMA_DELAY_RX_MASK; -+ val |= MTK_PDMA_DELAY_TX_EN; -+ -+ cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK); -+ val |= cur << MTK_PDMA_DELAY_TX_PTIME_SHIFT; -+ -+ cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK); -+ val |= cur << MTK_PDMA_DELAY_TX_PINT_SHIFT; -+ -+ mtk_w32(eth, val, MTK_PDMA_DELAY_INT); -+ mtk_w32(eth, val, MTK_QDMA_DELAY_INT); -+ -+ spin_unlock_bh(ð->dim_lock); -+ -+ dim->state = DIM_START_MEASURE; -+} -+ - static int mtk_hw_init(struct mtk_eth *eth) - { - int i, val, ret; -@@ -2419,9 +2497,6 @@ static int mtk_hw_init(struct mtk_eth *e - goto err_disable_pm; - } - -- /* enable interrupt delay for RX */ -- mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT); -- - /* disable delay and normal interrupt */ - mtk_tx_irq_disable(eth, ~0); - mtk_rx_irq_disable(eth, ~0); -@@ -2460,11 +2535,11 @@ static int mtk_hw_init(struct mtk_eth *e - /* Enable RX VLan Offloading */ - mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); - -- /* enable interrupt delay for RX */ -- mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT); -+ /* set interrupt delays based on current Net DIM sample */ -+ mtk_dim_rx(ð->rx_dim.work); -+ mtk_dim_tx(ð->tx_dim.work); - - /* disable delay and normal interrupt */ -- mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); - mtk_tx_irq_disable(eth, ~0); - mtk_rx_irq_disable(eth, ~0); - -@@ -2969,6 +3044,13 @@ static int mtk_probe(struct platform_dev - spin_lock_init(ð->page_lock); - spin_lock_init(ð->tx_irq_lock); - spin_lock_init(ð->rx_irq_lock); -+ spin_lock_init(ð->dim_lock); -+ -+ eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; -+ INIT_WORK(ð->rx_dim.work, mtk_dim_rx); -+ -+ eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; -+ INIT_WORK(ð->tx_dim.work, mtk_dim_tx); - - if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { - eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include "mtk_ppe.h" - - #define MTK_QDMA_PAGE_SIZE 2048 -@@ -136,13 +137,18 @@ - - /* PDMA Delay Interrupt Register */ - #define MTK_PDMA_DELAY_INT 0xa0c -+#define MTK_PDMA_DELAY_RX_MASK GENMASK(15, 0) - #define MTK_PDMA_DELAY_RX_EN BIT(15) --#define MTK_PDMA_DELAY_RX_PINT 4 - #define MTK_PDMA_DELAY_RX_PINT_SHIFT 8 --#define MTK_PDMA_DELAY_RX_PTIME 4 --#define MTK_PDMA_DELAY_RX_DELAY \ -- (MTK_PDMA_DELAY_RX_EN | MTK_PDMA_DELAY_RX_PTIME | \ -- (MTK_PDMA_DELAY_RX_PINT << MTK_PDMA_DELAY_RX_PINT_SHIFT)) -+#define MTK_PDMA_DELAY_RX_PTIME_SHIFT 0 -+ -+#define MTK_PDMA_DELAY_TX_MASK GENMASK(31, 16) -+#define MTK_PDMA_DELAY_TX_EN BIT(31) -+#define MTK_PDMA_DELAY_TX_PINT_SHIFT 24 -+#define MTK_PDMA_DELAY_TX_PTIME_SHIFT 16 -+ -+#define MTK_PDMA_DELAY_PINT_MASK 0x7f -+#define MTK_PDMA_DELAY_PTIME_MASK 0xff - - /* PDMA Interrupt Status Register */ - #define MTK_PDMA_INT_STATUS 0xa20 -@@ -224,6 +230,7 @@ - /* QDMA Interrupt Status Register */ - #define MTK_QDMA_INT_STATUS 0x1A18 - #define MTK_RX_DONE_DLY BIT(30) -+#define MTK_TX_DONE_DLY BIT(28) - #define MTK_RX_DONE_INT3 BIT(19) - #define MTK_RX_DONE_INT2 BIT(18) - #define MTK_RX_DONE_INT1 BIT(17) -@@ -233,8 +240,7 @@ - #define MTK_TX_DONE_INT1 BIT(1) - #define MTK_TX_DONE_INT0 BIT(0) - #define MTK_RX_DONE_INT MTK_RX_DONE_DLY --#define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \ -- MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3) -+#define MTK_TX_DONE_INT MTK_TX_DONE_DLY - - /* QDMA Interrupt grouping registers */ - #define MTK_QDMA_INT_GRP1 0x1a20 -@@ -863,6 +869,7 @@ struct mtk_sgmii { - * @page_lock: Make sure that register operations are atomic - * @tx_irq__lock: Make sure that IRQ register operations are atomic - * @rx_irq__lock: Make sure that IRQ register operations are atomic -+ * @dim_lock: Make sure that Net DIM operations are atomic - * @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a - * dummy for NAPI to work - * @netdev: The netdev instances -@@ -881,6 +888,14 @@ struct mtk_sgmii { - * @rx_ring_qdma: Pointer to the memory holding info about the QDMA RX ring - * @tx_napi: The TX NAPI struct - * @rx_napi: The RX NAPI struct -+ * @rx_events: Net DIM RX event counter -+ * @rx_packets: Net DIM RX packet counter -+ * @rx_bytes: Net DIM RX byte counter -+ * @rx_dim: Net DIM RX context -+ * @tx_events: Net DIM TX event counter -+ * @tx_packets: Net DIM TX packet counter -+ * @tx_bytes: Net DIM TX byte counter -+ * @tx_dim: Net DIM TX context - * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring - * @phy_scratch_ring: physical address of scratch_ring - * @scratch_head: The scratch memory that scratch_ring points to. -@@ -925,6 +940,18 @@ struct mtk_eth { - - const struct mtk_soc_data *soc; - -+ spinlock_t dim_lock; -+ -+ u32 rx_events; -+ u32 rx_packets; -+ u32 rx_bytes; -+ struct dim rx_dim; -+ -+ u32 tx_events; -+ u32 tx_packets; -+ u32 tx_bytes; -+ struct dim tx_dim; -+ - u32 tx_int_mask_reg; - u32 tx_int_status_reg; - u32 rx_dma_l4_valid; diff --git a/target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch b/target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch deleted file mode 100644 index c2252ed728..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-46-net-ethernet-mtk_eth_soc-cache-HW-pointer-of-last-fr.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 4e6bf609569c59b6bd6acf4a607c096cbd820d79 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:03 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: cache HW pointer of last freed TX - descriptor - -The value is only updated by the CPU, so it is cheaper to access from the -ring data structure than from a hardware register. - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++ - 2 files changed, 6 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1385,7 +1385,7 @@ static int mtk_poll_tx_qdma(struct mtk_e - struct mtk_tx_buf *tx_buf; - u32 cpu, dma; - -- cpu = mtk_r32(eth, MTK_QTX_CRX_PTR); -+ cpu = ring->last_free_ptr; - dma = mtk_r32(eth, MTK_QTX_DRX_PTR); - - desc = mtk_qdma_phys_to_virt(ring, cpu); -@@ -1419,6 +1419,7 @@ static int mtk_poll_tx_qdma(struct mtk_e - cpu = next_cpu; - } - -+ ring->last_free_ptr = cpu; - mtk_w32(eth, cpu, MTK_QTX_CRX_PTR); - - return budget; -@@ -1619,6 +1620,7 @@ static int mtk_tx_alloc(struct mtk_eth * - atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); - ring->next_free = &ring->dma[0]; - ring->last_free = &ring->dma[MTK_DMA_SIZE - 1]; -+ ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); - ring->thresh = MAX_SKB_FRAGS; - - /* make sure that all changes to the dma ring are flushed before we -@@ -1632,9 +1634,7 @@ static int mtk_tx_alloc(struct mtk_eth * - mtk_w32(eth, - ring->phys + ((MTK_DMA_SIZE - 1) * sz), - MTK_QTX_CRX_PTR); -- mtk_w32(eth, -- ring->phys + ((MTK_DMA_SIZE - 1) * sz), -- MTK_QTX_DRX_PTR); -+ mtk_w32(eth, ring->last_free_ptr, MTK_QTX_DRX_PTR); - mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, - MTK_QTX_CFG(0)); - } else { ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -656,6 +656,7 @@ struct mtk_tx_buf { - * @phys: The physical addr of tx_buf - * @next_free: Pointer to the next free descriptor - * @last_free: Pointer to the last free descriptor -+ * @last_free_ptr: Hardware pointer value of the last free descriptor - * @thresh: The threshold of minimum amount of free descriptors - * @free_count: QDMA uses a linked list. Track how many free descriptors - * are present -@@ -666,6 +667,7 @@ struct mtk_tx_ring { - dma_addr_t phys; - struct mtk_tx_dma *next_free; - struct mtk_tx_dma *last_free; -+ u32 last_free_ptr; - u16 thresh; - atomic_t free_count; - int dma_size; diff --git a/target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch b/target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch deleted file mode 100644 index 09b8b3afb9..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-47-net-ethernet-mtk_eth_soc-only-read-the-full-RX-descr.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 816ac3e6e67bdd78d86226c6eb53619780750e92 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:04 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: only read the full RX descriptor - if DMA is done - -Uncached memory access is expensive, and there is no need to access all -descriptor words if we can't process them anyway - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -798,13 +798,18 @@ static inline int mtk_max_buf_size(int f - return buf_size; - } - --static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd, -+static inline bool mtk_rx_get_desc(struct mtk_rx_dma *rxd, - struct mtk_rx_dma *dma_rxd) - { -- rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); - rxd->rxd2 = READ_ONCE(dma_rxd->rxd2); -+ if (!(rxd->rxd2 & RX_DMA_DONE)) -+ return false; -+ -+ rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); - rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); - rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); -+ -+ return true; - } - - /* the qdma core needs scratch memory to be setup */ -@@ -1276,8 +1281,7 @@ static int mtk_poll_rx(struct napi_struc - rxd = &ring->dma[idx]; - data = ring->data[idx]; - -- mtk_rx_get_desc(&trxd, rxd); -- if (!(trxd.rxd2 & RX_DMA_DONE)) -+ if (!mtk_rx_get_desc(&trxd, rxd)) - break; - - /* find out which mac the packet come from. values start at 1 */ diff --git a/target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch b/target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch deleted file mode 100644 index 411374c2e7..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-48-net-ethernet-mtk_eth_soc-reduce-unnecessary-interrup.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 16769a8923fad5a5377253bcd76b0e0d64976c73 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:05 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: reduce unnecessary interrupts - -Avoid rearming interrupt if napi_complete returns false - -Signed-off-by: Felix Fietkau -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1540,8 +1540,8 @@ static int mtk_napi_tx(struct napi_struc - if (status & MTK_TX_DONE_INT) - return budget; - -- napi_complete(napi); -- mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); -+ if (napi_complete(napi)) -+ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); - - return tx_done; - } -@@ -1574,8 +1574,9 @@ poll_again: - remain_budget -= rx_done; - goto poll_again; - } -- napi_complete(napi); -- mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); -+ -+ if (napi_complete(napi)) -+ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); - - return rx_done + budget - remain_budget; - } diff --git a/target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch b/target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch deleted file mode 100644 index d0926325d9..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-49-net-ethernet-mtk_eth_soc-rework-NAPI-callbacks.patch +++ /dev/null @@ -1,110 +0,0 @@ -From db2c7b353db3b3f71b55f9ff4627d8a786446fbe Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Thu, 22 Apr 2021 22:21:06 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: rework NAPI callbacks - -Use napi_complete_done to communicate total TX and RX work done to NAPI. -Count total RX work up instead of remaining work down for clarity. -Remove unneeded local variables for clarity. Use do {} while instead of -goto for clarity. - -Suggested-by: Jakub Kicinski -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 54 +++++++++------------ - 1 file changed, 24 insertions(+), 30 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1517,7 +1517,6 @@ static void mtk_handle_status_irq(struct - static int mtk_napi_tx(struct napi_struct *napi, int budget) - { - struct mtk_eth *eth = container_of(napi, struct mtk_eth, tx_napi); -- u32 status, mask; - int tx_done = 0; - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -@@ -1526,21 +1525,19 @@ static int mtk_napi_tx(struct napi_struc - tx_done = mtk_poll_tx(eth, budget); - - if (unlikely(netif_msg_intr(eth))) { -- status = mtk_r32(eth, eth->tx_int_status_reg); -- mask = mtk_r32(eth, eth->tx_int_mask_reg); - dev_info(eth->dev, -- "done tx %d, intr 0x%08x/0x%x\n", -- tx_done, status, mask); -+ "done tx %d, intr 0x%08x/0x%x\n", tx_done, -+ mtk_r32(eth, eth->tx_int_status_reg), -+ mtk_r32(eth, eth->tx_int_mask_reg)); - } - - if (tx_done == budget) - return budget; - -- status = mtk_r32(eth, eth->tx_int_status_reg); -- if (status & MTK_TX_DONE_INT) -+ if (mtk_r32(eth, eth->tx_int_status_reg) & MTK_TX_DONE_INT) - return budget; - -- if (napi_complete(napi)) -+ if (napi_complete_done(napi, tx_done)) - mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); - - return tx_done; -@@ -1549,36 +1546,33 @@ static int mtk_napi_tx(struct napi_struc - static int mtk_napi_rx(struct napi_struct *napi, int budget) - { - struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi); -- u32 status, mask; -- int rx_done = 0; -- int remain_budget = budget; -+ int rx_done_total = 0; - - mtk_handle_status_irq(eth); - --poll_again: -- mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS); -- rx_done = mtk_poll_rx(napi, remain_budget, eth); -+ do { -+ int rx_done; - -- if (unlikely(netif_msg_intr(eth))) { -- status = mtk_r32(eth, MTK_PDMA_INT_STATUS); -- mask = mtk_r32(eth, MTK_PDMA_INT_MASK); -- dev_info(eth->dev, -- "done rx %d, intr 0x%08x/0x%x\n", -- rx_done, status, mask); -- } -- if (rx_done == remain_budget) -- return budget; -+ mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS); -+ rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); -+ rx_done_total += rx_done; -+ -+ if (unlikely(netif_msg_intr(eth))) { -+ dev_info(eth->dev, -+ "done rx %d, intr 0x%08x/0x%x\n", rx_done, -+ mtk_r32(eth, MTK_PDMA_INT_STATUS), -+ mtk_r32(eth, MTK_PDMA_INT_MASK)); -+ } - -- status = mtk_r32(eth, MTK_PDMA_INT_STATUS); -- if (status & MTK_RX_DONE_INT) { -- remain_budget -= rx_done; -- goto poll_again; -- } -+ if (rx_done_total == budget) -+ return budget; -+ -+ } while (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT); - -- if (napi_complete(napi)) -+ if (napi_complete_done(napi, rx_done_total)) - mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); - -- return rx_done + budget - remain_budget; -+ return rx_done_total; - } - - static int mtk_tx_alloc(struct mtk_eth *eth) diff --git a/target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch b/target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch deleted file mode 100644 index ab298ec42b..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-50-net-ethernet-mtk_eth_soc-set-PPE-flow-hash-as-skb-ha.patch +++ /dev/null @@ -1,47 +0,0 @@ -From fa817272c37ef78e25dc14e4760ac78a7043a18a Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Thu, 22 Apr 2021 22:21:07 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: set PPE flow hash as skb hash if - present - -This improves GRO performance - -Signed-off-by: Felix Fietkau -[Ilya: Use MTK_RXD4_FOE_ENTRY instead of GENMASK(13, 0)] -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - - #include "mtk_eth_soc.h" -@@ -1271,6 +1272,7 @@ static int mtk_poll_rx(struct napi_struc - struct net_device *netdev; - unsigned int pktlen; - dma_addr_t dma_addr; -+ u32 hash; - int mac; - - ring = mtk_get_rx_ring(eth); -@@ -1340,6 +1342,12 @@ static int mtk_poll_rx(struct napi_struc - skb->protocol = eth_type_trans(skb, netdev); - bytes += pktlen; - -+ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; -+ if (hash != MTK_RXD4_FOE_ENTRY) { -+ hash = jhash_1word(hash, 0); -+ skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); -+ } -+ - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && - (trxd.rxd2 & RX_DMA_VTAG)) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), diff --git a/target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch b/target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch deleted file mode 100644 index 26bb33e42c..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-51-net-ethernet-mtk_eth_soc-use-iopoll.h-macro-for-DMA-.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 3bc8e0aff23be0526af0dbc7973a8866a08d73f1 Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Thu, 22 Apr 2021 22:21:08 -0700 -Subject: [PATCH] net: ethernet: mtk_eth_soc: use iopoll.h macro for DMA init - -Replace a tight busy-wait loop without a pause with a standard -readx_poll_timeout_atomic routine with a 5 us poll period. - -Tested by booting a MT7621 device to ensure the driver initializes -properly. - -Signed-off-by: Ilya Lipnitskiy -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 29 +++++++++------------ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- - 2 files changed, 14 insertions(+), 17 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2054,25 +2054,22 @@ static int mtk_set_features(struct net_d - /* wait for DMA to finish whatever it is doing before we start using it again */ - static int mtk_dma_busy_wait(struct mtk_eth *eth) - { -- unsigned long t_start = jiffies; -+ unsigned int reg; -+ int ret; -+ u32 val; - -- while (1) { -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { -- if (!(mtk_r32(eth, MTK_QDMA_GLO_CFG) & -- (MTK_RX_DMA_BUSY | MTK_TX_DMA_BUSY))) -- return 0; -- } else { -- if (!(mtk_r32(eth, MTK_PDMA_GLO_CFG) & -- (MTK_RX_DMA_BUSY | MTK_TX_DMA_BUSY))) -- return 0; -- } -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) -+ reg = MTK_QDMA_GLO_CFG; -+ else -+ reg = MTK_PDMA_GLO_CFG; - -- if (time_after(jiffies, t_start + MTK_DMA_BUSY_TIMEOUT)) -- break; -- } -+ ret = readx_poll_timeout_atomic(__raw_readl, eth->base + reg, val, -+ !(val & (MTK_RX_DMA_BUSY | MTK_TX_DMA_BUSY)), -+ 5, MTK_DMA_BUSY_TIMEOUT_US); -+ if (ret) -+ dev_err(eth->dev, "DMA init timeout\n"); - -- dev_err(eth->dev, "DMA init timeout\n"); -- return -1; -+ return ret; - } - - static int mtk_dma_init(struct mtk_eth *eth) ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -213,7 +213,7 @@ - #define MTK_TX_DMA_BUSY BIT(1) - #define MTK_RX_DMA_EN BIT(2) - #define MTK_TX_DMA_EN BIT(0) --#define MTK_DMA_BUSY_TIMEOUT HZ -+#define MTK_DMA_BUSY_TIMEOUT_US 1000000 - - /* QDMA Reset Index Register */ - #define MTK_QDMA_RST_IDX 0x1A08 diff --git a/target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch b/target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch deleted file mode 100644 index a846ce43e2..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-52-net-ethernet-mtk_eth_soc-missing-mutex.patch +++ /dev/null @@ -1,63 +0,0 @@ -From: Pablo Neira Ayuso -Date: Sun, 18 Apr 2021 23:11:44 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: missing mutex - -Patch 2ed37183abb7 ("netfilter: flowtable: separate replace, destroy and -stats to different workqueues") splits the workqueue per event type. Add -a mutex to serialize updates. - -Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support") -Reported-by: Frank Wunderlich -Signed-off-by: Pablo Neira Ayuso -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -392,6 +392,8 @@ mtk_flow_offload_stats(struct mtk_eth *e - return 0; - } - -+static DEFINE_MUTEX(mtk_flow_offload_mutex); -+ - static int - mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) - { -@@ -399,6 +401,7 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ - struct net_device *dev = cb_priv; - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; -+ int err; - - if (!tc_can_offload(dev)) - return -EOPNOTSUPP; -@@ -406,18 +409,24 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ - if (type != TC_SETUP_CLSFLOWER) - return -EOPNOTSUPP; - -+ mutex_lock(&mtk_flow_offload_mutex); - switch (cls->command) { - case FLOW_CLS_REPLACE: -- return mtk_flow_offload_replace(eth, cls); -+ err = mtk_flow_offload_replace(eth, cls); -+ break; - case FLOW_CLS_DESTROY: -- return mtk_flow_offload_destroy(eth, cls); -+ err = mtk_flow_offload_destroy(eth, cls); -+ break; - case FLOW_CLS_STATS: -- return mtk_flow_offload_stats(eth, cls); -+ err = mtk_flow_offload_stats(eth, cls); -+ break; - default: -- return -EOPNOTSUPP; -+ err = -EOPNOTSUPP; -+ break; - } -+ mutex_unlock(&mtk_flow_offload_mutex); - -- return 0; -+ return err; - } - - static int diff --git a/target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch b/target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch deleted file mode 100644 index 806fd0dcdf..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-53-net-ethernet-mtk_eth_soc-handle-VLAN-pop-action.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Pablo Neira Ayuso -Date: Sun, 18 Apr 2021 23:11:45 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: handle VLAN pop action - -Do not hit EOPNOTSUPP when flowtable offload provides a VLAN pop action. - -Fixes: efce49dfe6a8 ("netfilter: flowtable: add vlan pop action offload support") -Signed-off-by: Pablo Neira Ayuso -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -233,6 +233,8 @@ mtk_flow_offload_replace(struct mtk_eth - data.vlan.proto = act->vlan.proto; - data.vlan.num++; - break; -+ case FLOW_ACTION_VLAN_POP: -+ break; - case FLOW_ACTION_PPPOE_PUSH: - if (data.pppoe.num == 1) - return -EOPNOTSUPP; diff --git a/target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch b/target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch deleted file mode 100644 index 42b55f021a..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-54-netfilter-flowtable-dst_check-from-garbage-collector.patch +++ /dev/null @@ -1,159 +0,0 @@ -From: Pablo Neira Ayuso -Date: Sun, 28 Mar 2021 23:08:55 +0200 -Subject: [PATCH] netfilter: flowtable: dst_check() from garbage collector path - -Move dst_check() to the garbage collector path. Stale routes trigger the -flow entry teardown state which makes affected flows go back to the -classic forwarding path to re-evaluate flow offloading. - -IPv6 requires the dst cookie to work, store it in the flow_tuple, -otherwise dst_check() always fails. - -Fixes: e5075c0badaa ("netfilter: flowtable: call dst_check() to fall back to classic forwarding") -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -129,7 +129,10 @@ struct flow_offload_tuple { - in_vlan_ingress:2; - u16 mtu; - union { -- struct dst_entry *dst_cache; -+ struct { -+ struct dst_entry *dst_cache; -+ u32 dst_cookie; -+ }; - struct { - u32 ifidx; - u32 hw_ifidx; ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -74,6 +74,18 @@ err_ct_refcnt: - } - EXPORT_SYMBOL_GPL(flow_offload_alloc); - -+static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple) -+{ -+ const struct rt6_info *rt; -+ -+ if (flow_tuple->l3proto == NFPROTO_IPV6) { -+ rt = (const struct rt6_info *)flow_tuple->dst_cache; -+ return rt6_get_cookie(rt); -+ } -+ -+ return 0; -+} -+ - static int flow_offload_fill_route(struct flow_offload *flow, - const struct nf_flow_route *route, - enum flow_offload_tuple_dir dir) -@@ -116,6 +128,7 @@ static int flow_offload_fill_route(struc - return -1; - - flow_tuple->dst_cache = dst; -+ flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple); - break; - } - flow_tuple->xmit_type = route->tuple[dir].xmit_type; -@@ -389,11 +402,33 @@ nf_flow_table_iterate(struct nf_flowtabl - return err; - } - -+static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple) -+{ -+ struct dst_entry *dst; -+ -+ if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -+ tuple->xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { -+ dst = tuple->dst_cache; -+ if (!dst_check(dst, tuple->dst_cookie)) -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool nf_flow_has_stale_dst(struct flow_offload *flow) -+{ -+ return flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple) || -+ flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple); -+} -+ - static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data) - { - struct nf_flowtable *flow_table = data; - -- if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct)) -+ if (nf_flow_has_expired(flow) || -+ nf_ct_is_dying(flow->ct) || -+ nf_flow_has_stale_dst(flow)) - set_bit(NF_FLOW_TEARDOWN, &flow->flags); - - if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) { ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -364,15 +364,6 @@ nf_flow_offload_ip_hook(void *priv, stru - if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) - return NF_ACCEPT; - -- if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -- tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { -- rt = (struct rtable *)tuplehash->tuple.dst_cache; -- if (!dst_check(&rt->dst, 0)) { -- flow_offload_teardown(flow); -- return NF_ACCEPT; -- } -- } -- - if (skb_try_make_writable(skb, thoff + hdrsize)) - return NF_DROP; - -@@ -391,6 +382,7 @@ nf_flow_offload_ip_hook(void *priv, stru - nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); - - if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { -+ rt = (struct rtable *)tuplehash->tuple.dst_cache; - memset(skb->cb, 0, sizeof(struct inet_skb_parm)); - IPCB(skb)->iif = skb->dev->ifindex; - IPCB(skb)->flags = IPSKB_FORWARDED; -@@ -399,6 +391,7 @@ nf_flow_offload_ip_hook(void *priv, stru - - switch (tuplehash->tuple.xmit_type) { - case FLOW_OFFLOAD_XMIT_NEIGH: -+ rt = (struct rtable *)tuplehash->tuple.dst_cache; - outdev = rt->dst.dev; - skb->dev = outdev; - nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); -@@ -607,15 +600,6 @@ nf_flow_offload_ipv6_hook(void *priv, st - if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff)) - return NF_ACCEPT; - -- if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH || -- tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) { -- rt = (struct rt6_info *)tuplehash->tuple.dst_cache; -- if (!dst_check(&rt->dst, 0)) { -- flow_offload_teardown(flow); -- return NF_ACCEPT; -- } -- } -- - if (skb_try_make_writable(skb, thoff + hdrsize)) - return NF_DROP; - -@@ -633,6 +617,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); - - if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { -+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; - memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); - IP6CB(skb)->iif = skb->dev->ifindex; - IP6CB(skb)->flags = IP6SKB_FORWARDED; -@@ -641,6 +626,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - - switch (tuplehash->tuple.xmit_type) { - case FLOW_OFFLOAD_XMIT_NEIGH: -+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache; - outdev = rt->dst.dev; - skb->dev = outdev; - nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); diff --git a/target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch b/target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch deleted file mode 100644 index e5a346cac4..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-55-netfilter-conntrack-Introduce-tcp-offload-timeout-co.patch +++ /dev/null @@ -1,94 +0,0 @@ -From: Oz Shlomo -Date: Thu, 3 Jun 2021 15:12:33 +0300 -Subject: [PATCH] netfilter: conntrack: Introduce tcp offload timeout - configuration - -TCP connections may be offloaded from nf conntrack to nf flow table. -Offloaded connections are aged after 30 seconds of inactivity. -Once aged, ownership is returned to conntrack with a hard coded pickup -time of 120 seconds, after which the connection may be deleted. -eted. The current aging intervals may be too aggressive for some users. - -Provide users with the ability to control the nf flow table offload -aging and pickup time intervals via sysctl parameter as a pre-step for -configuring the nf flow table GC timeout intervals. - -Signed-off-by: Oz Shlomo -Reviewed-by: Paul Blakey -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netns/conntrack.h -+++ b/include/net/netns/conntrack.h -@@ -27,6 +27,10 @@ struct nf_tcp_net { - int tcp_loose; - int tcp_be_liberal; - int tcp_max_retrans; -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ unsigned int offload_timeout; -+ unsigned int offload_pickup; -+#endif - }; - - enum udp_conntrack { ---- a/net/netfilter/nf_conntrack_proto_tcp.c -+++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -1438,6 +1438,11 @@ void nf_conntrack_tcp_init_net(struct ne - tn->tcp_loose = nf_ct_tcp_loose; - tn->tcp_be_liberal = nf_ct_tcp_be_liberal; - tn->tcp_max_retrans = nf_ct_tcp_max_retrans; -+ -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ tn->offload_timeout = 30 * HZ; -+ tn->offload_pickup = 120 * HZ; -+#endif - } - - const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp = ---- a/net/netfilter/nf_conntrack_standalone.c -+++ b/net/netfilter/nf_conntrack_standalone.c -@@ -567,6 +567,10 @@ enum nf_ct_sysctl_index { - NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE, - NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_RETRANS, - NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK, -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD, -+ NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP, -+#endif - NF_SYSCTL_CT_PROTO_TCP_LOOSE, - NF_SYSCTL_CT_PROTO_TCP_LIBERAL, - NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS, -@@ -758,6 +762,20 @@ static struct ctl_table nf_ct_sysctl_tab - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD] = { -+ .procname = "nf_flowtable_tcp_timeout", -+ .maxlen = sizeof(unsigned int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_jiffies, -+ }, -+ [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP] = { -+ .procname = "nf_flowtable_tcp_pickup", -+ .maxlen = sizeof(unsigned int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_jiffies, -+ }, -+#endif - [NF_SYSCTL_CT_PROTO_TCP_LOOSE] = { - .procname = "nf_conntrack_tcp_loose", - .maxlen = sizeof(int), -@@ -967,6 +985,12 @@ static void nf_conntrack_standalone_init - XASSIGN(LIBERAL, &tn->tcp_be_liberal); - XASSIGN(MAX_RETRANS, &tn->tcp_max_retrans); - #undef XASSIGN -+ -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD].data = &tn->offload_timeout; -+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP].data = &tn->offload_pickup; -+#endif -+ - } - - static void nf_conntrack_standalone_init_sctp_sysctl(struct net *net, diff --git a/target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch b/target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch deleted file mode 100644 index 416e20356d..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-56-netfilter-conntrack-Introduce-udp-offload-timeout-co.patch +++ /dev/null @@ -1,92 +0,0 @@ -From: Oz Shlomo -Date: Thu, 3 Jun 2021 15:12:34 +0300 -Subject: [PATCH] netfilter: conntrack: Introduce udp offload timeout - configuration - -UDP connections may be offloaded from nf conntrack to nf flow table. -Offloaded connections are aged after 30 seconds of inactivity. -Once aged, ownership is returned to conntrack with a hard coded pickup -time of 30 seconds, after which the connection may be deleted. -eted. The current aging intervals may be too aggressive for some users. - -Provide users with the ability to control the nf flow table offload -aging and pickup time intervals via sysctl parameter as a pre-step for -configuring the nf flow table GC timeout intervals. - -Signed-off-by: Oz Shlomo -Reviewed-by: Paul Blakey -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netns/conntrack.h -+++ b/include/net/netns/conntrack.h -@@ -41,6 +41,10 @@ enum udp_conntrack { - - struct nf_udp_net { - unsigned int timeouts[UDP_CT_MAX]; -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ unsigned int offload_timeout; -+ unsigned int offload_pickup; -+#endif - }; - - struct nf_icmp_net { ---- a/net/netfilter/nf_conntrack_proto_udp.c -+++ b/net/netfilter/nf_conntrack_proto_udp.c -@@ -273,6 +273,11 @@ void nf_conntrack_udp_init_net(struct ne - - for (i = 0; i < UDP_CT_MAX; i++) - un->timeouts[i] = udp_timeouts[i]; -+ -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ un->offload_timeout = 30 * HZ; -+ un->offload_pickup = 30 * HZ; -+#endif - } - - const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp = ---- a/net/netfilter/nf_conntrack_standalone.c -+++ b/net/netfilter/nf_conntrack_standalone.c -@@ -576,6 +576,10 @@ enum nf_ct_sysctl_index { - NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS, - NF_SYSCTL_CT_PROTO_TIMEOUT_UDP, - NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM, -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD, -+ NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP, -+#endif - NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP, - NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6, - #ifdef CONFIG_NF_CT_PROTO_SCTP -@@ -810,6 +814,20 @@ static struct ctl_table nf_ct_sysctl_tab - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, -+#if IS_ENABLED(CONFIG_NFT_FLOW_OFFLOAD) -+ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD] = { -+ .procname = "nf_flowtable_udp_timeout", -+ .maxlen = sizeof(unsigned int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_jiffies, -+ }, -+ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP] = { -+ .procname = "nf_flowtable_udp_pickup", -+ .maxlen = sizeof(unsigned int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_jiffies, -+ }, -+#endif - [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP] = { - .procname = "nf_conntrack_icmp_timeout", - .maxlen = sizeof(unsigned int), -@@ -1078,6 +1096,10 @@ static int nf_conntrack_standalone_init_ - table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout; - table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP].data = &un->timeouts[UDP_CT_UNREPLIED]; - table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM].data = &un->timeouts[UDP_CT_REPLIED]; -+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD].data = &un->offload_timeout; -+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP].data = &un->offload_pickup; -+#endif - - nf_conntrack_standalone_init_tcp_sysctl(net, table); - nf_conntrack_standalone_init_sctp_sysctl(net, table); diff --git a/target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch b/target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch deleted file mode 100644 index 1e82308eaa..0000000000 --- a/target/linux/generic/backport-5.15/610-v5.13-57-netfilter-flowtable-Set-offload-timeouts-according-t.patch +++ /dev/null @@ -1,134 +0,0 @@ -From: Oz Shlomo -Date: Thu, 3 Jun 2021 15:12:35 +0300 -Subject: [PATCH] netfilter: flowtable: Set offload timeouts according to proto - values - -Currently the aging period for tcp/udp connections is hard coded to -30 seconds. Aged tcp/udp connections configure a hard coded 120/30 -seconds pickup timeout for conntrack. -This configuration may be too aggressive or permissive for some users. - -Dynamically configure the nf flow table GC timeout intervals according -to the user defined values. - -Signed-off-by: Oz Shlomo -Reviewed-by: Paul Blakey -Signed-off-by: Pablo Neira Ayuso ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -174,6 +174,8 @@ struct flow_offload { - #define NF_FLOW_TIMEOUT (30 * HZ) - #define nf_flowtable_time_stamp (u32)jiffies - -+unsigned long flow_offload_get_timeout(struct flow_offload *flow); -+ - static inline __s32 nf_flow_timeout_delta(unsigned int timeout) - { - return (__s32)(timeout - nf_flowtable_time_stamp); ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -175,12 +175,10 @@ static void flow_offload_fixup_tcp(struc - tcp->seen[1].td_maxwin = 0; - } - --#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ) --#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ) -- - static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) - { - const struct nf_conntrack_l4proto *l4proto; -+ struct net *net = nf_ct_net(ct); - int l4num = nf_ct_protonum(ct); - unsigned int timeout; - -@@ -188,12 +186,17 @@ static void flow_offload_fixup_ct_timeou - if (!l4proto) - return; - -- if (l4num == IPPROTO_TCP) -- timeout = NF_FLOWTABLE_TCP_PICKUP_TIMEOUT; -- else if (l4num == IPPROTO_UDP) -- timeout = NF_FLOWTABLE_UDP_PICKUP_TIMEOUT; -- else -+ if (l4num == IPPROTO_TCP) { -+ struct nf_tcp_net *tn = nf_tcp_pernet(net); -+ -+ timeout = tn->offload_pickup; -+ } else if (l4num == IPPROTO_UDP) { -+ struct nf_udp_net *tn = nf_udp_pernet(net); -+ -+ timeout = tn->offload_pickup; -+ } else { - return; -+ } - - if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout) - WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout); -@@ -265,11 +268,35 @@ static const struct rhashtable_params nf - .automatic_shrinking = true, - }; - -+unsigned long flow_offload_get_timeout(struct flow_offload *flow) -+{ -+ const struct nf_conntrack_l4proto *l4proto; -+ unsigned long timeout = NF_FLOW_TIMEOUT; -+ struct net *net = nf_ct_net(flow->ct); -+ int l4num = nf_ct_protonum(flow->ct); -+ -+ l4proto = nf_ct_l4proto_find(l4num); -+ if (!l4proto) -+ return timeout; -+ -+ if (l4num == IPPROTO_TCP) { -+ struct nf_tcp_net *tn = nf_tcp_pernet(net); -+ -+ timeout = tn->offload_timeout; -+ } else if (l4num == IPPROTO_UDP) { -+ struct nf_udp_net *tn = nf_udp_pernet(net); -+ -+ timeout = tn->offload_timeout; -+ } -+ -+ return timeout; -+} -+ - int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) - { - int err; - -- flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT; -+ flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); - - err = rhashtable_insert_fast(&flow_table->rhashtable, - &flow->tuplehash[0].node, -@@ -301,7 +328,7 @@ EXPORT_SYMBOL_GPL(flow_offload_add); - void flow_offload_refresh(struct nf_flowtable *flow_table, - struct flow_offload *flow) - { -- flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT; -+ flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow); - - if (likely(!nf_flowtable_hw_offload(flow_table))) - return; ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -885,7 +885,7 @@ static void flow_offload_work_stats(stru - - lastused = max_t(u64, stats[0].lastused, stats[1].lastused); - offload->flow->timeout = max_t(u64, offload->flow->timeout, -- lastused + NF_FLOW_TIMEOUT); -+ lastused + flow_offload_get_timeout(offload->flow)); - - if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) { - if (stats[0].pkts) -@@ -989,7 +989,7 @@ void nf_flow_offload_stats(struct nf_flo - __s32 delta; - - delta = nf_flow_timeout_delta(flow->timeout); -- if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10)) -+ if ((delta >= (9 * flow_offload_get_timeout(flow)) / 10)) - return; - - offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS); diff --git a/target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch b/target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch deleted file mode 100644 index 289d140f34..0000000000 --- a/target/linux/generic/backport-5.15/611-v5.12-net-ethernet-mediatek-support-setting-MTU.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 4fd59792097a6b2fb949d41264386a7ecade469e Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Mon, 25 Jan 2021 12:20:46 +0800 -Subject: [PATCH] net: ethernet: mediatek: support setting MTU - -MT762x HW, except for MT7628, supports frame length up to 2048 -(maximum length on GDM), so allow setting MTU up to 2030. - -Also set the default frame length to the hardware default 1518. - -Signed-off-by: DENG Qingfang -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20210125042046.5599-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 43 ++++++++++++++++++--- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++++-- - 2 files changed, 47 insertions(+), 8 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -355,7 +355,7 @@ static void mtk_mac_config(struct phylin - /* Setup gmac */ - mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); - mcr_new = mcr_cur; -- mcr_new |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | -+ mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | - MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK; - - /* Only update control register when needed! */ -@@ -782,8 +782,8 @@ static void mtk_get_stats64(struct net_d - static inline int mtk_max_frag_size(int mtu) - { - /* make sure buf_size will be at least MTK_MAX_RX_LENGTH */ -- if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH) -- mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; -+ if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH_2K) -+ mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; - - return SKB_DATA_ALIGN(MTK_RX_HLEN + mtu) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); -@@ -794,7 +794,7 @@ static inline int mtk_max_buf_size(int f - int buf_size = frag_size - NET_SKB_PAD - NET_IP_ALIGN - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - -- WARN_ON(buf_size < MTK_MAX_RX_LENGTH); -+ WARN_ON(buf_size < MTK_MAX_RX_LENGTH_2K); - - return buf_size; - } -@@ -2606,6 +2606,35 @@ static void mtk_uninit(struct net_device - mtk_rx_irq_disable(eth, ~0); - } - -+static int mtk_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ int length = new_mtu + MTK_RX_ETH_HLEN; -+ struct mtk_mac *mac = netdev_priv(dev); -+ struct mtk_eth *eth = mac->hw; -+ u32 mcr_cur, mcr_new; -+ -+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { -+ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -+ mcr_new = mcr_cur & ~MAC_MCR_MAX_RX_MASK; -+ -+ if (length <= 1518) -+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1518); -+ else if (length <= 1536) -+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1536); -+ else if (length <= 1552) -+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1552); -+ else -+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_2048); -+ -+ if (mcr_new != mcr_cur) -+ mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); -+ } -+ -+ dev->mtu = new_mtu; -+ -+ return 0; -+} -+ - static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) - { - struct mtk_mac *mac = netdev_priv(dev); -@@ -2902,6 +2931,7 @@ static const struct net_device_ops mtk_n - .ndo_set_mac_address = mtk_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = mtk_do_ioctl, -+ .ndo_change_mtu = mtk_change_mtu, - .ndo_tx_timeout = mtk_tx_timeout, - .ndo_get_stats64 = mtk_get_stats64, - .ndo_fix_features = mtk_fix_features, -@@ -3004,7 +3034,10 @@ static int mtk_add_mac(struct mtk_eth *e - eth->netdev[id]->irq = eth->irq[0]; - eth->netdev[id]->dev.of_node = np; - -- eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) -+ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; -+ else -+ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; - - return 0; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -20,12 +20,13 @@ - #include "mtk_ppe.h" - - #define MTK_QDMA_PAGE_SIZE 2048 --#define MTK_MAX_RX_LENGTH 1536 -+#define MTK_MAX_RX_LENGTH 1536 -+#define MTK_MAX_RX_LENGTH_2K 2048 - #define MTK_TX_DMA_BUF_LEN 0x3fff - #define MTK_DMA_SIZE 512 - #define MTK_NAPI_WEIGHT 64 - #define MTK_MAC_COUNT 2 --#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) -+#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) - #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) - #define MTK_DMA_DUMMY_DESC 0xffffffff - #define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \ -@@ -352,7 +353,12 @@ - - /* Mac control registers */ - #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100)) --#define MAC_MCR_MAX_RX_1536 BIT(24) -+#define MAC_MCR_MAX_RX_MASK GENMASK(25, 24) -+#define MAC_MCR_MAX_RX(_x) (MAC_MCR_MAX_RX_MASK & ((_x) << 24)) -+#define MAC_MCR_MAX_RX_1518 0x0 -+#define MAC_MCR_MAX_RX_1536 0x1 -+#define MAC_MCR_MAX_RX_1552 0x2 -+#define MAC_MCR_MAX_RX_2048 0x3 - #define MAC_MCR_IPG_CFG (BIT(18) | BIT(16)) - #define MAC_MCR_FORCE_MODE BIT(15) - #define MAC_MCR_TX_EN BIT(14) diff --git a/target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch b/target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch deleted file mode 100644 index 00be403299..0000000000 --- a/target/linux/generic/backport-5.15/705-net-phy-at803x-select-correct-page-on-config-init.patch +++ /dev/null @@ -1,108 +0,0 @@ -From c329e5afb42ff0a88285eb4d8a391a18793e4777 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Thu, 15 Apr 2021 03:26:50 +0200 -Subject: [PATCH] net: phy: at803x: select correct page on config init - -The Atheros AR8031 and AR8033 expose different registers for SGMII/Fiber -as well as the copper side of the PHY depending on the BT_BX_REG_SEL bit -in the chip configure register. - -The driver assumes the copper side is selected on probe, but this might -not be the case depending which page was last selected by the -bootloader. Notably, Ubiquiti UniFi bootloaders show this behavior. - -Select the copper page when probing to circumvent this. - -Signed-off-by: David Bauer -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 49 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -139,6 +139,9 @@ - #define ATH8035_PHY_ID 0x004dd072 - #define AT8030_PHY_ID_MASK 0xffffffef - -+#define AT803X_PAGE_FIBER 0 -+#define AT803X_PAGE_COPPER 1 -+ - MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); - MODULE_LICENSE("GPL"); -@@ -190,6 +193,35 @@ static int at803x_debug_reg_mask(struct - return phy_write(phydev, AT803X_DEBUG_DATA, val); - } - -+static int at803x_write_page(struct phy_device *phydev, int page) -+{ -+ int mask; -+ int set; -+ -+ if (page == AT803X_PAGE_COPPER) { -+ set = AT803X_BT_BX_REG_SEL; -+ mask = 0; -+ } else { -+ set = 0; -+ mask = AT803X_BT_BX_REG_SEL; -+ } -+ -+ return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set); -+} -+ -+static int at803x_read_page(struct phy_device *phydev) -+{ -+ int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG); -+ -+ if (ccr < 0) -+ return ccr; -+ -+ if (ccr & AT803X_BT_BX_REG_SEL) -+ return AT803X_PAGE_COPPER; -+ -+ return AT803X_PAGE_FIBER; -+} -+ - static int at803x_enable_rx_delay(struct phy_device *phydev) - { - return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, -@@ -508,6 +540,7 @@ static int at803x_probe(struct phy_devic - { - struct device *dev = &phydev->mdio.dev; - struct at803x_priv *priv; -+ int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -515,7 +548,20 @@ static int at803x_probe(struct phy_devic - - phydev->priv = priv; - -- return at803x_parse_dt(phydev); -+ ret = at803x_parse_dt(phydev); -+ if (ret) -+ return ret; -+ -+ /* Some bootloaders leave the fiber page selected. -+ * Switch to the copper page, as otherwise we read -+ * the PHY capabilities from the fiber side. -+ */ -+ if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) { -+ ret = phy_select_page(phydev, AT803X_PAGE_COPPER); -+ ret = phy_restore_page(phydev, AT803X_PAGE_COPPER, ret); -+ } -+ -+ return ret; - } - - static void at803x_remove(struct phy_device *phydev) -@@ -1097,6 +1143,8 @@ static struct phy_driver at803x_driver[] - .get_wol = at803x_get_wol, - .suspend = at803x_suspend, - .resume = at803x_resume, -+ .read_page = at803x_read_page, -+ .write_page = at803x_write_page, - /* PHY_GBIT_FEATURES */ - .read_status = at803x_read_status, - .aneg_done = at803x_aneg_done, diff --git a/target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch b/target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch deleted file mode 100644 index d6ec7450e8..0000000000 --- a/target/linux/generic/backport-5.15/706-net-phy-at803x-fix-probe-error-if-copper-page-is-sel.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 8f7e876273e294b732b42af2e5e6bba91d798954 Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Tue, 20 Apr 2021 12:29:29 +0200 -Subject: [PATCH] net: phy: at803x: fix probe error if copper page is selected - -The commit c329e5afb42f ("net: phy: at803x: select correct page on -config init") selects the copper page during probe. This fails if the -copper page was already selected. In this case, the value of the copper -page (which is 1) is propagated through phy_restore_page() and is -finally returned for at803x_probe(). Fix it, by just using the -at803x_page_write() directly. - -Also in case of an error, the regulator is not disabled and leads to a -WARN_ON() when the probe fails. This couldn't happen before, because -at803x_parse_dt() was the last call in at803x_probe(). It is hard to -see, that the parse_dt() actually enables the regulator. Thus move the -regulator_enable() to the probe function and undo it in case of an -error. - -Fixes: c329e5afb42f ("net: phy: at803x: select correct page on config init") -Signed-off-by: Michael Walle -Reviewed-by: David Bauer -Signed-off-by: David S. Miller ---- - drivers/net/phy/at803x.c | 23 +++++++++++++++++------ - 1 file changed, 17 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -527,10 +527,6 @@ static int at803x_parse_dt(struct phy_de - phydev_err(phydev, "failed to get VDDIO regulator\n"); - return PTR_ERR(priv->vddio); - } -- -- ret = regulator_enable(priv->vddio); -- if (ret < 0) -- return ret; - } - - return 0; -@@ -552,15 +548,30 @@ static int at803x_probe(struct phy_devic - if (ret) - return ret; - -+ if (priv->vddio) { -+ ret = regulator_enable(priv->vddio); -+ if (ret < 0) -+ return ret; -+ } -+ - /* Some bootloaders leave the fiber page selected. - * Switch to the copper page, as otherwise we read - * the PHY capabilities from the fiber side. - */ - if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) { -- ret = phy_select_page(phydev, AT803X_PAGE_COPPER); -- ret = phy_restore_page(phydev, AT803X_PAGE_COPPER, ret); -+ phy_lock_mdio_bus(phydev); -+ ret = at803x_write_page(phydev, AT803X_PAGE_COPPER); -+ phy_unlock_mdio_bus(phydev); -+ if (ret) -+ goto err; - } - -+ return 0; -+ -+err: -+ if (priv->vddio) -+ regulator_disable(priv->vddio); -+ - return ret; - } - diff --git a/target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch b/target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch deleted file mode 100644 index 5c7f97ea90..0000000000 --- a/target/linux/generic/backport-5.15/710-v5.12-net-phy-Add-100-base-x-mode.patch +++ /dev/null @@ -1,56 +0,0 @@ -From b1ae3587d16a8c8fc9453e147c8708d6f006ffbb Mon Sep 17 00:00:00 2001 -From: Bjarni Jonasson -Date: Wed, 13 Jan 2021 12:56:25 +0100 -Subject: [PATCH] net: phy: Add 100 base-x mode - -Sparx-5 supports this mode and it is missing in the PHY core. - -Signed-off-by: Bjarni Jonasson -Reviewed-by: Russell King -Signed-off-by: Jakub Kicinski ---- - Documentation/networking/phy.rst | 5 +++++ - include/linux/phy.h | 4 ++++ - 2 files changed, 9 insertions(+) - ---- a/Documentation/networking/phy.rst -+++ b/Documentation/networking/phy.rst -@@ -286,6 +286,11 @@ Some of the interface modes are describe - Note: due to legacy usage, some 10GBASE-R usage incorrectly makes - use of this definition. - -+``PHY_INTERFACE_MODE_100BASEX`` -+ This defines IEEE 802.3 Clause 24. The link operates at a fixed data -+ rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying -+ data rate of 100Mpbs. -+ - Pause frames / flow control - =========================== - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr - * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax - * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII - * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII -+ * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX - * @PHY_INTERFACE_MODE_1000BASEX: 1000 BaseX - * @PHY_INTERFACE_MODE_2500BASEX: 2500 BaseX - * @PHY_INTERFACE_MODE_RXAUI: Reduced XAUI -@@ -135,6 +136,7 @@ typedef enum { - PHY_INTERFACE_MODE_MOCA, - PHY_INTERFACE_MODE_QSGMII, - PHY_INTERFACE_MODE_TRGMII, -+ PHY_INTERFACE_MODE_100BASEX, - PHY_INTERFACE_MODE_1000BASEX, - PHY_INTERFACE_MODE_2500BASEX, - PHY_INTERFACE_MODE_RXAUI, -@@ -217,6 +219,8 @@ static inline const char *phy_modes(phy_ - return "usxgmii"; - case PHY_INTERFACE_MODE_10GKR: - return "10gbase-kr"; -+ case PHY_INTERFACE_MODE_100BASEX: -+ return "100base-x"; - default: - return "unknown"; - } diff --git a/target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch b/target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch deleted file mode 100644 index 7d06c235d9..0000000000 --- a/target/linux/generic/backport-5.15/711-v5.12-sfp-add-support-for-100-base-x-SFPs.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 6e12f35cef6b8a458d7ecf507ae330e0bffaad8c Mon Sep 17 00:00:00 2001 -From: Bjarni Jonasson -Date: Wed, 13 Jan 2021 12:56:26 +0100 -Subject: [PATCH] sfp: add support for 100 base-x SFPs - -Add support for 100Base-FX, 100Base-LX, 100Base-PX and 100Base-BX10 modules -This is needed for Sparx-5 switch. - -Signed-off-by: Bjarni Jonasson -Reviewed-by: Russell King -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/sfp-bus.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -280,6 +280,12 @@ void sfp_parse_support(struct sfp_bus *b - br_min <= 1300 && br_max >= 1200) - phylink_set(modes, 1000baseX_Full); - -+ /* 100Base-FX, 100Base-LX, 100Base-PX, 100Base-BX10 */ -+ if (id->base.e100_base_fx || id->base.e100_base_lx) -+ phylink_set(modes, 100baseFX_Full); -+ if ((id->base.e_base_px || id->base.e_base_bx10) && br_nom == 100) -+ phylink_set(modes, 100baseFX_Full); -+ - /* For active or passive cables, select the link modes - * based on the bit rates and the cable compliance bytes. - */ -@@ -399,6 +405,9 @@ phy_interface_t sfp_select_interface(str - if (phylink_test(link_modes, 1000baseX_Full)) - return PHY_INTERFACE_MODE_1000BASEX; - -+ if (phylink_test(link_modes, 100baseFX_Full)) -+ return PHY_INTERFACE_MODE_100BASEX; -+ - dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n"); - - return PHY_INTERFACE_MODE_NA; diff --git a/target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch b/target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch deleted file mode 100644 index 278df46313..0000000000 --- a/target/linux/generic/backport-5.15/712-v5.13-net-phy-marvell-refactor-HWMON-OOP-style.patch +++ /dev/null @@ -1,549 +0,0 @@ -From 41d26bf4aba070dfd2ab48866cc27a48ee6228c7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Tue, 20 Apr 2021 09:53:59 +0200 -Subject: [PATCH] net: phy: marvell: refactor HWMON OOP style -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use a structure of Marvell PHY specific HWMON methods to reduce code -duplication. Store a pointer to this structure into the PHY driver's -driver_data member. - -Signed-off-by: Marek Behún -Signed-off-by: David S. Miller ---- - drivers/net/phy/marvell.c | 369 +++++++++++++------------------------- - 1 file changed, 125 insertions(+), 244 deletions(-) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2141,6 +2141,19 @@ static int marvell_vct7_cable_test_get_s - } - - #ifdef CONFIG_HWMON -+struct marvell_hwmon_ops { -+ int (*get_temp)(struct phy_device *phydev, long *temp); -+ int (*get_temp_critical)(struct phy_device *phydev, long *temp); -+ int (*set_temp_critical)(struct phy_device *phydev, long temp); -+ int (*get_temp_alarm)(struct phy_device *phydev, long *alarm); -+}; -+ -+static const struct marvell_hwmon_ops * -+to_marvell_hwmon_ops(const struct phy_device *phydev) -+{ -+ return phydev->drv->driver_data; -+} -+ - static int m88e1121_get_temp(struct phy_device *phydev, long *temp) - { - int oldpage; -@@ -2184,75 +2197,6 @@ error: - return phy_restore_page(phydev, oldpage, ret); - } - --static int m88e1121_hwmon_read(struct device *dev, -- enum hwmon_sensor_types type, -- u32 attr, int channel, long *temp) --{ -- struct phy_device *phydev = dev_get_drvdata(dev); -- int err; -- -- switch (attr) { -- case hwmon_temp_input: -- err = m88e1121_get_temp(phydev, temp); -- break; -- default: -- return -EOPNOTSUPP; -- } -- -- return err; --} -- --static umode_t m88e1121_hwmon_is_visible(const void *data, -- enum hwmon_sensor_types type, -- u32 attr, int channel) --{ -- if (type != hwmon_temp) -- return 0; -- -- switch (attr) { -- case hwmon_temp_input: -- return 0444; -- default: -- return 0; -- } --} -- --static u32 m88e1121_hwmon_chip_config[] = { -- HWMON_C_REGISTER_TZ, -- 0 --}; -- --static const struct hwmon_channel_info m88e1121_hwmon_chip = { -- .type = hwmon_chip, -- .config = m88e1121_hwmon_chip_config, --}; -- --static u32 m88e1121_hwmon_temp_config[] = { -- HWMON_T_INPUT, -- 0 --}; -- --static const struct hwmon_channel_info m88e1121_hwmon_temp = { -- .type = hwmon_temp, -- .config = m88e1121_hwmon_temp_config, --}; -- --static const struct hwmon_channel_info *m88e1121_hwmon_info[] = { -- &m88e1121_hwmon_chip, -- &m88e1121_hwmon_temp, -- NULL --}; -- --static const struct hwmon_ops m88e1121_hwmon_hwmon_ops = { -- .is_visible = m88e1121_hwmon_is_visible, -- .read = m88e1121_hwmon_read, --}; -- --static const struct hwmon_chip_info m88e1121_hwmon_chip_info = { -- .ops = &m88e1121_hwmon_hwmon_ops, -- .info = m88e1121_hwmon_info, --}; -- - static int m88e1510_get_temp(struct phy_device *phydev, long *temp) - { - int ret; -@@ -2315,92 +2259,6 @@ static int m88e1510_get_temp_alarm(struc - return 0; - } - --static int m88e1510_hwmon_read(struct device *dev, -- enum hwmon_sensor_types type, -- u32 attr, int channel, long *temp) --{ -- struct phy_device *phydev = dev_get_drvdata(dev); -- int err; -- -- switch (attr) { -- case hwmon_temp_input: -- err = m88e1510_get_temp(phydev, temp); -- break; -- case hwmon_temp_crit: -- err = m88e1510_get_temp_critical(phydev, temp); -- break; -- case hwmon_temp_max_alarm: -- err = m88e1510_get_temp_alarm(phydev, temp); -- break; -- default: -- return -EOPNOTSUPP; -- } -- -- return err; --} -- --static int m88e1510_hwmon_write(struct device *dev, -- enum hwmon_sensor_types type, -- u32 attr, int channel, long temp) --{ -- struct phy_device *phydev = dev_get_drvdata(dev); -- int err; -- -- switch (attr) { -- case hwmon_temp_crit: -- err = m88e1510_set_temp_critical(phydev, temp); -- break; -- default: -- return -EOPNOTSUPP; -- } -- return err; --} -- --static umode_t m88e1510_hwmon_is_visible(const void *data, -- enum hwmon_sensor_types type, -- u32 attr, int channel) --{ -- if (type != hwmon_temp) -- return 0; -- -- switch (attr) { -- case hwmon_temp_input: -- case hwmon_temp_max_alarm: -- return 0444; -- case hwmon_temp_crit: -- return 0644; -- default: -- return 0; -- } --} -- --static u32 m88e1510_hwmon_temp_config[] = { -- HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM, -- 0 --}; -- --static const struct hwmon_channel_info m88e1510_hwmon_temp = { -- .type = hwmon_temp, -- .config = m88e1510_hwmon_temp_config, --}; -- --static const struct hwmon_channel_info *m88e1510_hwmon_info[] = { -- &m88e1121_hwmon_chip, -- &m88e1510_hwmon_temp, -- NULL --}; -- --static const struct hwmon_ops m88e1510_hwmon_hwmon_ops = { -- .is_visible = m88e1510_hwmon_is_visible, -- .read = m88e1510_hwmon_read, -- .write = m88e1510_hwmon_write, --}; -- --static const struct hwmon_chip_info m88e1510_hwmon_chip_info = { -- .ops = &m88e1510_hwmon_hwmon_ops, -- .info = m88e1510_hwmon_info, --}; -- - static int m88e6390_get_temp(struct phy_device *phydev, long *temp) - { - int sum = 0; -@@ -2459,63 +2317,112 @@ error: - return ret; - } - --static int m88e6390_hwmon_read(struct device *dev, -- enum hwmon_sensor_types type, -- u32 attr, int channel, long *temp) -+static int marvell_hwmon_read(struct device *dev, enum hwmon_sensor_types type, -+ u32 attr, int channel, long *temp) - { - struct phy_device *phydev = dev_get_drvdata(dev); -- int err; -+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); -+ int err = -EOPNOTSUPP; - - switch (attr) { - case hwmon_temp_input: -- err = m88e6390_get_temp(phydev, temp); -+ if (ops->get_temp) -+ err = ops->get_temp(phydev, temp); -+ break; -+ case hwmon_temp_crit: -+ if (ops->get_temp_critical) -+ err = ops->get_temp_critical(phydev, temp); -+ break; -+ case hwmon_temp_max_alarm: -+ if (ops->get_temp_alarm) -+ err = ops->get_temp_alarm(phydev, temp); -+ break; -+ } -+ -+ return err; -+} -+ -+static int marvell_hwmon_write(struct device *dev, enum hwmon_sensor_types type, -+ u32 attr, int channel, long temp) -+{ -+ struct phy_device *phydev = dev_get_drvdata(dev); -+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); -+ int err = -EOPNOTSUPP; -+ -+ switch (attr) { -+ case hwmon_temp_crit: -+ if (ops->set_temp_critical) -+ err = ops->set_temp_critical(phydev, temp); - break; - default: -- return -EOPNOTSUPP; -+ fallthrough; - } - - return err; - } - --static umode_t m88e6390_hwmon_is_visible(const void *data, -- enum hwmon_sensor_types type, -- u32 attr, int channel) -+static umode_t marvell_hwmon_is_visible(const void *data, -+ enum hwmon_sensor_types type, -+ u32 attr, int channel) - { -+ const struct phy_device *phydev = data; -+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); -+ - if (type != hwmon_temp) - return 0; - - switch (attr) { - case hwmon_temp_input: -- return 0444; -+ return ops->get_temp ? 0444 : 0; -+ case hwmon_temp_max_alarm: -+ return ops->get_temp_alarm ? 0444 : 0; -+ case hwmon_temp_crit: -+ return (ops->get_temp_critical ? 0444 : 0) | -+ (ops->set_temp_critical ? 0200 : 0); - default: - return 0; - } - } - --static u32 m88e6390_hwmon_temp_config[] = { -- HWMON_T_INPUT, -+static u32 marvell_hwmon_chip_config[] = { -+ HWMON_C_REGISTER_TZ, - 0 - }; - --static const struct hwmon_channel_info m88e6390_hwmon_temp = { -+static const struct hwmon_channel_info marvell_hwmon_chip = { -+ .type = hwmon_chip, -+ .config = marvell_hwmon_chip_config, -+}; -+ -+/* we can define HWMON_T_CRIT and HWMON_T_MAX_ALARM even though these are not -+ * defined for all PHYs, because the hwmon code checks whether the attributes -+ * exists via the .is_visible method -+ */ -+static u32 marvell_hwmon_temp_config[] = { -+ HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM, -+ 0 -+}; -+ -+static const struct hwmon_channel_info marvell_hwmon_temp = { - .type = hwmon_temp, -- .config = m88e6390_hwmon_temp_config, -+ .config = marvell_hwmon_temp_config, - }; - --static const struct hwmon_channel_info *m88e6390_hwmon_info[] = { -- &m88e1121_hwmon_chip, -- &m88e6390_hwmon_temp, -+static const struct hwmon_channel_info *marvell_hwmon_info[] = { -+ &marvell_hwmon_chip, -+ &marvell_hwmon_temp, - NULL - }; - --static const struct hwmon_ops m88e6390_hwmon_hwmon_ops = { -- .is_visible = m88e6390_hwmon_is_visible, -- .read = m88e6390_hwmon_read, -+static const struct hwmon_ops marvell_hwmon_hwmon_ops = { -+ .is_visible = marvell_hwmon_is_visible, -+ .read = marvell_hwmon_read, -+ .write = marvell_hwmon_write, - }; - --static const struct hwmon_chip_info m88e6390_hwmon_chip_info = { -- .ops = &m88e6390_hwmon_hwmon_ops, -- .info = m88e6390_hwmon_info, -+static const struct hwmon_chip_info marvell_hwmon_chip_info = { -+ .ops = &marvell_hwmon_hwmon_ops, -+ .info = marvell_hwmon_info, - }; - - static int marvell_hwmon_name(struct phy_device *phydev) -@@ -2538,49 +2445,48 @@ static int marvell_hwmon_name(struct phy - return 0; - } - --static int marvell_hwmon_probe(struct phy_device *phydev, -- const struct hwmon_chip_info *chip) -+static int marvell_hwmon_probe(struct phy_device *phydev) - { -+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev); - struct marvell_priv *priv = phydev->priv; - struct device *dev = &phydev->mdio.dev; - int err; - -+ if (!ops) -+ return 0; -+ - err = marvell_hwmon_name(phydev); - if (err) - return err; - - priv->hwmon_dev = devm_hwmon_device_register_with_info( -- dev, priv->hwmon_name, phydev, chip, NULL); -+ dev, priv->hwmon_name, phydev, &marvell_hwmon_chip_info, NULL); - - return PTR_ERR_OR_ZERO(priv->hwmon_dev); - } - --static int m88e1121_hwmon_probe(struct phy_device *phydev) --{ -- return marvell_hwmon_probe(phydev, &m88e1121_hwmon_chip_info); --} -+static const struct marvell_hwmon_ops m88e1121_hwmon_ops = { -+ .get_temp = m88e1121_get_temp, -+}; - --static int m88e1510_hwmon_probe(struct phy_device *phydev) --{ -- return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info); --} -+static const struct marvell_hwmon_ops m88e1510_hwmon_ops = { -+ .get_temp = m88e1510_get_temp, -+ .get_temp_critical = m88e1510_get_temp_critical, -+ .set_temp_critical = m88e1510_set_temp_critical, -+ .get_temp_alarm = m88e1510_get_temp_alarm, -+}; -+ -+static const struct marvell_hwmon_ops m88e6390_hwmon_ops = { -+ .get_temp = m88e6390_get_temp, -+}; -+ -+#define DEF_MARVELL_HWMON_OPS(s) (&(s)) - --static int m88e6390_hwmon_probe(struct phy_device *phydev) --{ -- return marvell_hwmon_probe(phydev, &m88e6390_hwmon_chip_info); --} - #else --static int m88e1121_hwmon_probe(struct phy_device *phydev) --{ -- return 0; --} - --static int m88e1510_hwmon_probe(struct phy_device *phydev) --{ -- return 0; --} -+#define DEF_MARVELL_HWMON_OPS(s) NULL - --static int m88e6390_hwmon_probe(struct phy_device *phydev) -+static int marvell_hwmon_probe(struct phy_device *phydev) - { - return 0; - } -@@ -2596,40 +2502,7 @@ static int marvell_probe(struct phy_devi - - phydev->priv = priv; - -- return 0; --} -- --static int m88e1121_probe(struct phy_device *phydev) --{ -- int err; -- -- err = marvell_probe(phydev); -- if (err) -- return err; -- -- return m88e1121_hwmon_probe(phydev); --} -- --static int m88e1510_probe(struct phy_device *phydev) --{ -- int err; -- -- err = marvell_probe(phydev); -- if (err) -- return err; -- -- return m88e1510_hwmon_probe(phydev); --} -- --static int m88e6390_probe(struct phy_device *phydev) --{ -- int err; -- -- err = marvell_probe(phydev); -- if (err) -- return err; -- -- return m88e6390_hwmon_probe(phydev); -+ return marvell_hwmon_probe(phydev); - } - - static struct phy_driver marvell_drivers[] = { -@@ -2714,8 +2587,9 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E1121R, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1121R", -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1121_hwmon_ops), - /* PHY_GBIT_FEATURES */ -- .probe = m88e1121_probe, -+ .probe = marvell_probe, - .config_init = marvell_config_init, - .config_aneg = m88e1121_config_aneg, - .read_status = marvell_read_status, -@@ -2834,9 +2708,10 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E1510, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1510", -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - .features = PHY_GBIT_FIBRE_FEATURES, - .flags = PHY_POLL_CABLE_TEST, -- .probe = m88e1510_probe, -+ .probe = marvell_probe, - .config_init = m88e1510_config_init, - .config_aneg = m88e1510_config_aneg, - .read_status = marvell_read_status, -@@ -2863,9 +2738,10 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E1540, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1540", -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, -- .probe = m88e1510_probe, -+ .probe = marvell_probe, - .config_init = marvell_config_init, - .config_aneg = m88e1510_config_aneg, - .read_status = marvell_read_status, -@@ -2889,7 +2765,8 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E1545, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1545", -- .probe = m88e1510_probe, -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), -+ .probe = marvell_probe, - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, - .config_init = marvell_config_init, -@@ -2935,9 +2812,10 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E6341_FAMILY, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E6341 Family", -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, -- .probe = m88e1510_probe, -+ .probe = marvell_probe, - .config_init = marvell_config_init, - .config_aneg = m88e6390_config_aneg, - .read_status = marvell_read_status, -@@ -2961,9 +2839,10 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E6390_FAMILY, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E6390 Family", -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e6390_hwmon_ops), - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, -- .probe = m88e6390_probe, -+ .probe = marvell_probe, - .config_init = marvell_config_init, - .config_aneg = m88e6390_config_aneg, - .read_status = marvell_read_status, -@@ -2987,7 +2866,8 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E1340S, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1340S", -- .probe = m88e1510_probe, -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), -+ .probe = marvell_probe, - /* PHY_GBIT_FEATURES */ - .config_init = marvell_config_init, - .config_aneg = m88e1510_config_aneg, -@@ -3009,7 +2889,8 @@ static struct phy_driver marvell_drivers - .phy_id = MARVELL_PHY_ID_88E1548P, - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1548P", -- .probe = m88e1510_probe, -+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), -+ .probe = marvell_probe, - .features = PHY_GBIT_FIBRE_FEATURES, - .config_init = marvell_config_init, - .config_aneg = m88e1510_config_aneg, diff --git a/target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch b/target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch deleted file mode 100644 index b86e9bf640..0000000000 --- a/target/linux/generic/backport-5.15/713-v5.15-net-phy-marvell-add-SFP-support-for-88E1510.patch +++ /dev/null @@ -1,161 +0,0 @@ -From b697d9d38a5a5ab405d7cc4743d39fe2c5d7517c Mon Sep 17 00:00:00 2001 -From: Ivan Bornyakov -Date: Thu, 12 Aug 2021 16:42:56 +0300 -Subject: [PATCH] net: phy: marvell: add SFP support for 88E1510 - -Add support for SFP cages connected to the Marvell 88E1512 transceiver. -88E1512 supports for SGMII/1000Base-X/100Base-FX media type with RGMII -on system interface. Configure PHY to appropriate mode depending on the -type of SFP inserted. On SFP removal configure PHY to the RGMII-copper -mode so RJ-45 port can still work. - -Signed-off-by: Ivan Bornyakov -Link: https://lore.kernel.org/r/20210812134256.2436-1-i.bornyakov@metrotek.ru -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 105 +++++++++++++++++++++++++++++++++++++- - 1 file changed, 104 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -46,6 +47,7 @@ - #define MII_MARVELL_MISC_TEST_PAGE 0x06 - #define MII_MARVELL_VCT7_PAGE 0x07 - #define MII_MARVELL_WOL_PAGE 0x11 -+#define MII_MARVELL_MODE_PAGE 0x12 - - #define MII_M1011_IEVENT 0x13 - #define MII_M1011_IEVENT_CLEAR 0x0000 -@@ -162,7 +164,14 @@ - - #define MII_88E1510_GEN_CTRL_REG_1 0x14 - #define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7 -+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII 0x0 /* RGMII to copper */ - #define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */ -+/* RGMII to 1000BASE-X */ -+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X 0x2 -+/* RGMII to 100BASE-FX */ -+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX 0x3 -+/* RGMII to SGMII */ -+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII 0x4 - #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */ - - #define MII_VCT5_TX_RX_MDI0_COUPLING 0x10 -@@ -2505,6 +2514,100 @@ static int marvell_probe(struct phy_devi - return marvell_hwmon_probe(phydev); - } - -+static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) -+{ -+ struct phy_device *phydev = upstream; -+ phy_interface_t interface; -+ struct device *dev; -+ int oldpage; -+ int ret = 0; -+ u16 mode; -+ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; -+ -+ dev = &phydev->mdio.dev; -+ -+ sfp_parse_support(phydev->sfp_bus, id, supported); -+ interface = sfp_select_interface(phydev->sfp_bus, supported); -+ -+ dev_info(dev, "%s SFP module inserted\n", phy_modes(interface)); -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_1000BASEX: -+ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; -+ -+ break; -+ case PHY_INTERFACE_MODE_100BASEX: -+ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; -+ -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; -+ -+ break; -+ default: -+ dev_err(dev, "Incompatible SFP module inserted\n"); -+ -+ return -EINVAL; -+ } -+ -+ oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); -+ if (oldpage < 0) -+ goto error; -+ -+ ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, -+ MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, mode); -+ if (ret < 0) -+ goto error; -+ -+ ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, -+ MII_88E1510_GEN_CTRL_REG_1_RESET); -+ -+error: -+ return phy_restore_page(phydev, oldpage, ret); -+} -+ -+static void m88e1510_sfp_remove(void *upstream) -+{ -+ struct phy_device *phydev = upstream; -+ int oldpage; -+ int ret = 0; -+ -+ oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); -+ if (oldpage < 0) -+ goto error; -+ -+ ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, -+ MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, -+ MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII); -+ if (ret < 0) -+ goto error; -+ -+ ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, -+ MII_88E1510_GEN_CTRL_REG_1_RESET); -+ -+error: -+ phy_restore_page(phydev, oldpage, ret); -+} -+ -+static const struct sfp_upstream_ops m88e1510_sfp_ops = { -+ .module_insert = m88e1510_sfp_insert, -+ .module_remove = m88e1510_sfp_remove, -+ .attach = phy_sfp_attach, -+ .detach = phy_sfp_detach, -+}; -+ -+static int m88e1510_probe(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = marvell_probe(phydev); -+ if (err) -+ return err; -+ -+ return phy_sfp_probe(phydev, &m88e1510_sfp_ops); -+} -+ - static struct phy_driver marvell_drivers[] = { - { - .phy_id = MARVELL_PHY_ID_88E1101, -@@ -2711,7 +2814,7 @@ static struct phy_driver marvell_drivers - .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - .features = PHY_GBIT_FIBRE_FEATURES, - .flags = PHY_POLL_CABLE_TEST, -- .probe = marvell_probe, -+ .probe = m88e1510_probe, - .config_init = m88e1510_config_init, - .config_aneg = m88e1510_config_aneg, - .read_status = marvell_read_status, diff --git a/target/linux/generic/backport-5.15/719-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch b/target/linux/generic/backport-5.15/719-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch deleted file mode 100644 index 3b630377f9..0000000000 --- a/target/linux/generic/backport-5.15/719-v5.12-net-dsa-automatically-bring-up-DSA-master-when-openi.patch +++ /dev/null @@ -1,85 +0,0 @@ -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.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch b/target/linux/generic/backport-5.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch deleted file mode 100644 index c43cb4d1f2..0000000000 --- a/target/linux/generic/backport-5.15/720-v5.12-net-bridge-notify-switchdev-of-disappearance-of-old-.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 90dc8fd36078a536671adae884d0b929cce6480a Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Wed, 6 Jan 2021 11:51:30 +0200 -Subject: [PATCH] net: bridge: notify switchdev of disappearance of old FDB - entry upon migration - -Currently the bridge emits atomic switchdev notifications for -dynamically learnt FDB entries. Monitoring these notifications works -wonders for switchdev drivers that want to keep their hardware FDB in -sync with the bridge's FDB. - -For example station A wants to talk to station B in the diagram below, -and we are concerned with the behavior of the bridge on the DUT device: - - DUT - +-------------------------------------+ - | br0 | - | +------+ +------+ +------+ +------+ | - | | | | | | | | | | - | | swp0 | | swp1 | | swp2 | | eth0 | | - +-------------------------------------+ - | | | - Station A | | - | | - +--+------+--+ +--+------+--+ - | | | | | | | | - | | swp0 | | | | swp0 | | - Another | +------+ | | +------+ | Another - switch | br0 | | br0 | switch - | +------+ | | +------+ | - | | | | | | | | - | | swp1 | | | | swp1 | | - +--+------+--+ +--+------+--+ - | - Station B - -Interfaces swp0, swp1, swp2 are handled by a switchdev driver that has -the following property: frames injected from its control interface bypass -the internal address analyzer logic, and therefore, this hardware does -not learn from the source address of packets transmitted by the network -stack through it. So, since bridging between eth0 (where Station B is -attached) and swp0 (where Station A is attached) is done in software, -the switchdev hardware will never learn the source address of Station B. -So the traffic towards that destination will be treated as unknown, i.e. -flooded. - -This is where the bridge notifications come in handy. When br0 on the -DUT sees frames with Station B's MAC address on eth0, the switchdev -driver gets these notifications and can install a rule to send frames -towards Station B's address that are incoming from swp0, swp1, swp2, -only towards the control interface. This is all switchdev driver private -business, which the notification makes possible. - -All is fine until someone unplugs Station B's cable and moves it to the -other switch: - - DUT - +-------------------------------------+ - | br0 | - | +------+ +------+ +------+ +------+ | - | | | | | | | | | | - | | swp0 | | swp1 | | swp2 | | eth0 | | - +-------------------------------------+ - | | | - Station A | | - | | - +--+------+--+ +--+------+--+ - | | | | | | | | - | | swp0 | | | | swp0 | | - Another | +------+ | | +------+ | Another - switch | br0 | | br0 | switch - | +------+ | | +------+ | - | | | | | | | | - | | swp1 | | | | swp1 | | - +--+------+--+ +--+------+--+ - | - Station B - -Luckily for the use cases we care about, Station B is noisy enough that -the DUT hears it (on swp1 this time). swp1 receives the frames and -delivers them to the bridge, who enters the unlikely path in br_fdb_update -of updating an existing entry. It moves the entry in the software bridge -to swp1 and emits an addition notification towards that. - -As far as the switchdev driver is concerned, all that it needs to ensure -is that traffic between Station A and Station B is not forever broken. -If it does nothing, then the stale rule to send frames for Station B -towards the control interface remains in place. But Station B is no -longer reachable via the control interface, but via a port that can -offload the bridge port learning attribute. It's just that the port is -prevented from learning this address, since the rule overrides FDB -updates. So the rule needs to go. The question is via what mechanism. - -It sure would be possible for this switchdev driver to keep track of all -addresses which are sent to the control interface, and then also listen -for bridge notifier events on its own ports, searching for the ones that -have a MAC address which was previously sent to the control interface. -But this is cumbersome and inefficient. Instead, with one small change, -the bridge could notify of the address deletion from the old port, in a -symmetrical manner with how it did for the insertion. Then the switchdev -driver would not be required to monitor learn/forget events for its own -ports. It could just delete the rule towards the control interface upon -bridge entry migration. This would make hardware address learning be -possible again. Then it would take a few more packets until the hardware -and software FDB would be in sync again. - -Signed-off-by: Vladimir Oltean -Acked-by: Nikolay Aleksandrov -Reviewed-by: Ido Schimmel -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - net/bridge/br_fdb.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/net/bridge/br_fdb.c -+++ b/net/bridge/br_fdb.c -@@ -602,6 +602,7 @@ void br_fdb_update(struct net_bridge *br - /* fastpath: update of existing entry */ - if (unlikely(source != fdb->dst && - !test_bit(BR_FDB_STICKY, &fdb->flags))) { -+ br_switchdev_fdb_notify(fdb, RTM_DELNEIGH); - fdb->dst = source; - fdb_modified = true; - /* Take over HW learned entry */ diff --git a/target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch b/target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch deleted file mode 100644 index f9337590f7..0000000000 --- a/target/linux/generic/backport-5.15/721-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 2fd186501b1cff155cc4a755c210793cfc0dffb5 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Wed, 6 Jan 2021 11:51:31 +0200 -Subject: [PATCH] net: dsa: be louder when a non-legacy FDB operation fails - -The dev_close() call was added in commit c9eb3e0f8701 ("net: dsa: Add -support for learning FDB through notification") "to indicate inconsistent -situation" when we could not delete an FDB entry from the port. - -bridge fdb del d8:58:d7:00:ca:6d dev swp0 self master - -It is a bit drastic and at the same time not helpful if the above fails -to only print with netdev_dbg log level, but on the other hand to bring -the interface down. - -So increase the verbosity of the error message, and drop dev_close(). - -Signed-off-by: Vladimir Oltean -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - net/dsa/slave.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2112,7 +2112,9 @@ static void dsa_slave_switchdev_event_wo - - err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); - if (err) { -- netdev_dbg(dev, "fdb add failed err=%d\n", err); -+ netdev_err(dev, -+ "failed to add %pM vid %d to fdb: %d\n", -+ fdb_info->addr, fdb_info->vid, err); - break; - } - fdb_info->offloaded = true; -@@ -2127,9 +2129,11 @@ static void dsa_slave_switchdev_event_wo - - err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); - if (err) { -- netdev_dbg(dev, "fdb del failed err=%d\n", err); -- dev_close(dev); -+ netdev_err(dev, -+ "failed to delete %pM vid %d from fdb: %d\n", -+ fdb_info->addr, fdb_info->vid, err); - } -+ - break; - } - rtnl_unlock(); diff --git a/target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch b/target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch deleted file mode 100644 index c1aa8fda82..0000000000 --- a/target/linux/generic/backport-5.15/722-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch +++ /dev/null @@ -1,226 +0,0 @@ -From c4bb76a9a0ef87c4cc1f636defed5f12deb9f5a7 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Wed, 6 Jan 2021 11:51:32 +0200 -Subject: [PATCH] net: dsa: don't use switchdev_notifier_fdb_info in - dsa_switchdev_event_work - -Currently DSA doesn't add FDB entries on the CPU port, because it only -does so through switchdev, which is associated with a net_device, and -there are none of those for the CPU port. - -But actually FDB addresses on the CPU port have some use cases of their -own, if the switchdev operations are initiated from within the DSA -layer. There is just one problem with the existing code: it passes a -structure in dsa_switchdev_event_work which was retrieved directly from -switchdev, so it contains a net_device. We need to generalize the -contents to something that covers the CPU port as well: the "ds, port" -tuple is fine for that. - -Note that the new procedure for notifying the successful FDB offload is -inspired from the rocker model. - -Also, nothing was being done if added_by_user was false. Let's check for -that a lot earlier, and don't actually bother to schedule the worker -for nothing. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - net/dsa/dsa_priv.h | 12 +++++ - net/dsa/slave.c | 106 ++++++++++++++++++++++----------------------- - 2 files changed, 65 insertions(+), 53 deletions(-) - ---- a/net/dsa/dsa_priv.h -+++ b/net/dsa/dsa_priv.h -@@ -73,6 +73,18 @@ struct dsa_notifier_mtu_info { - int mtu; - }; - -+struct dsa_switchdev_event_work { -+ struct dsa_switch *ds; -+ int port; -+ struct work_struct work; -+ unsigned long event; -+ /* Specific for SWITCHDEV_FDB_ADD_TO_DEVICE and -+ * SWITCHDEV_FDB_DEL_TO_DEVICE -+ */ -+ unsigned char addr[ETH_ALEN]; -+ u16 vid; -+}; -+ - struct dsa_slave_priv { - /* Copy of CPU port xmit for faster access in slave transmit hot path */ - struct sk_buff * (*xmit)(struct sk_buff *skb, ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2087,76 +2087,66 @@ static int dsa_slave_netdevice_event(str - return NOTIFY_DONE; - } - --struct dsa_switchdev_event_work { -- struct work_struct work; -- struct switchdev_notifier_fdb_info fdb_info; -- struct net_device *dev; -- unsigned long event; --}; -+static void -+dsa_fdb_offload_notify(struct dsa_switchdev_event_work *switchdev_work) -+{ -+ struct dsa_switch *ds = switchdev_work->ds; -+ struct switchdev_notifier_fdb_info info; -+ struct dsa_port *dp; -+ -+ if (!dsa_is_user_port(ds, switchdev_work->port)) -+ return; -+ -+ info.addr = switchdev_work->addr; -+ info.vid = switchdev_work->vid; -+ info.offloaded = true; -+ dp = dsa_to_port(ds, switchdev_work->port); -+ call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, -+ dp->slave, &info.info, NULL); -+} - - static void dsa_slave_switchdev_event_work(struct work_struct *work) - { - struct dsa_switchdev_event_work *switchdev_work = - container_of(work, struct dsa_switchdev_event_work, work); -- struct net_device *dev = switchdev_work->dev; -- struct switchdev_notifier_fdb_info *fdb_info; -- struct dsa_port *dp = dsa_slave_to_port(dev); -+ struct dsa_switch *ds = switchdev_work->ds; -+ struct dsa_port *dp; - int err; - -+ dp = dsa_to_port(ds, switchdev_work->port); -+ - rtnl_lock(); - switch (switchdev_work->event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: -- fdb_info = &switchdev_work->fdb_info; -- if (!fdb_info->added_by_user) -- break; -- -- err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); -+ err = dsa_port_fdb_add(dp, switchdev_work->addr, -+ switchdev_work->vid); - if (err) { -- netdev_err(dev, -- "failed to add %pM vid %d to fdb: %d\n", -- fdb_info->addr, fdb_info->vid, err); -+ dev_err(ds->dev, -+ "port %d failed to add %pM vid %d to fdb: %d\n", -+ dp->index, switchdev_work->addr, -+ switchdev_work->vid, err); - break; - } -- fdb_info->offloaded = true; -- call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, -- &fdb_info->info, NULL); -+ dsa_fdb_offload_notify(switchdev_work); - break; - - case SWITCHDEV_FDB_DEL_TO_DEVICE: -- fdb_info = &switchdev_work->fdb_info; -- if (!fdb_info->added_by_user) -- break; -- -- err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); -+ err = dsa_port_fdb_del(dp, switchdev_work->addr, -+ switchdev_work->vid); - if (err) { -- netdev_err(dev, -- "failed to delete %pM vid %d from fdb: %d\n", -- fdb_info->addr, fdb_info->vid, err); -+ dev_err(ds->dev, -+ "port %d failed to delete %pM vid %d from fdb: %d\n", -+ dp->index, switchdev_work->addr, -+ switchdev_work->vid, err); - } - - break; - } - rtnl_unlock(); - -- kfree(switchdev_work->fdb_info.addr); - kfree(switchdev_work); -- dev_put(dev); --} -- --static int --dsa_slave_switchdev_fdb_work_init(struct dsa_switchdev_event_work * -- switchdev_work, -- const struct switchdev_notifier_fdb_info * -- fdb_info) --{ -- memcpy(&switchdev_work->fdb_info, fdb_info, -- sizeof(switchdev_work->fdb_info)); -- switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); -- if (!switchdev_work->fdb_info.addr) -- return -ENOMEM; -- ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, -- fdb_info->addr); -- return 0; -+ if (dsa_is_user_port(ds, dp->index)) -+ dev_put(dp->slave); - } - - /* Called under rcu_read_lock() */ -@@ -2164,7 +2154,9 @@ static int dsa_slave_switchdev_event(str - unsigned long event, void *ptr) - { - struct net_device *dev = switchdev_notifier_info_to_dev(ptr); -+ const struct switchdev_notifier_fdb_info *fdb_info; - struct dsa_switchdev_event_work *switchdev_work; -+ struct dsa_port *dp; - int err; - - if (event == SWITCHDEV_PORT_ATTR_SET) { -@@ -2177,20 +2169,32 @@ static int dsa_slave_switchdev_event(str - if (!dsa_slave_dev_check(dev)) - return NOTIFY_DONE; - -+ dp = dsa_slave_to_port(dev); -+ - switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); - if (!switchdev_work) - return NOTIFY_BAD; - - INIT_WORK(&switchdev_work->work, - dsa_slave_switchdev_event_work); -- switchdev_work->dev = dev; -+ switchdev_work->ds = dp->ds; -+ switchdev_work->port = dp->index; - switchdev_work->event = event; - - switch (event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: - case SWITCHDEV_FDB_DEL_TO_DEVICE: -- if (dsa_slave_switchdev_fdb_work_init(switchdev_work, ptr)) -- goto err_fdb_work_init; -+ fdb_info = ptr; -+ -+ if (!fdb_info->added_by_user) { -+ kfree(switchdev_work); -+ return NOTIFY_OK; -+ } -+ -+ ether_addr_copy(switchdev_work->addr, -+ fdb_info->addr); -+ switchdev_work->vid = fdb_info->vid; -+ - dev_hold(dev); - break; - default: -@@ -2200,10 +2204,6 @@ static int dsa_slave_switchdev_event(str - - dsa_schedule_work(&switchdev_work->work); - return NOTIFY_OK; -- --err_fdb_work_init: -- kfree(switchdev_work); -- return NOTIFY_BAD; - } - - static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, diff --git a/target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch b/target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch deleted file mode 100644 index 9131df70d3..0000000000 --- a/target/linux/generic/backport-5.15/723-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 447d290a58bd335d68f665713842365d3d6447df Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Wed, 6 Jan 2021 11:51:33 +0200 -Subject: [PATCH] net: dsa: move switchdev event implementation under the same - switch/case statement - -We'll need to start listening to SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE -events even for interfaces where dsa_slave_dev_check returns false, so -we need that check inside the switch-case statement for SWITCHDEV_FDB_*. - -This movement also avoids a useless allocation / free of switchdev_work -on the untreated "default event" case. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - net/dsa/slave.c | 35 ++++++++++++++++------------------- - 1 file changed, 16 insertions(+), 19 deletions(-) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2159,31 +2159,29 @@ static int dsa_slave_switchdev_event(str - struct dsa_port *dp; - int err; - -- if (event == SWITCHDEV_PORT_ATTR_SET) { -+ switch (event) { -+ case SWITCHDEV_PORT_ATTR_SET: - err = switchdev_handle_port_attr_set(dev, ptr, - dsa_slave_dev_check, - dsa_slave_port_attr_set); - return notifier_from_errno(err); -- } -- -- if (!dsa_slave_dev_check(dev)) -- return NOTIFY_DONE; -+ case SWITCHDEV_FDB_ADD_TO_DEVICE: -+ case SWITCHDEV_FDB_DEL_TO_DEVICE: -+ if (!dsa_slave_dev_check(dev)) -+ return NOTIFY_DONE; - -- dp = dsa_slave_to_port(dev); -+ dp = dsa_slave_to_port(dev); - -- switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); -- if (!switchdev_work) -- return NOTIFY_BAD; -- -- INIT_WORK(&switchdev_work->work, -- dsa_slave_switchdev_event_work); -- switchdev_work->ds = dp->ds; -- switchdev_work->port = dp->index; -- switchdev_work->event = event; -+ switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); -+ if (!switchdev_work) -+ return NOTIFY_BAD; -+ -+ INIT_WORK(&switchdev_work->work, -+ dsa_slave_switchdev_event_work); -+ switchdev_work->ds = dp->ds; -+ switchdev_work->port = dp->index; -+ switchdev_work->event = event; - -- switch (event) { -- case SWITCHDEV_FDB_ADD_TO_DEVICE: -- case SWITCHDEV_FDB_DEL_TO_DEVICE: - fdb_info = ptr; - - if (!fdb_info->added_by_user) { -@@ -2196,13 +2194,12 @@ static int dsa_slave_switchdev_event(str - switchdev_work->vid = fdb_info->vid; - - dev_hold(dev); -+ dsa_schedule_work(&switchdev_work->work); - break; - default: -- kfree(switchdev_work); - return NOTIFY_DONE; - } - -- dsa_schedule_work(&switchdev_work->work); - return NOTIFY_OK; - } - diff --git a/target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch b/target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch deleted file mode 100644 index b7b6ebe461..0000000000 --- a/target/linux/generic/backport-5.15/724-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 5fb4a451a87d8ed3363d28b63a3295399373d6c4 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Wed, 6 Jan 2021 11:51:34 +0200 -Subject: [PATCH] net: dsa: exit early in dsa_slave_switchdev_event if we can't - program the FDB - -Right now, the following would happen for a switch driver that does not -implement .port_fdb_add or .port_fdb_del. - -dsa_slave_switchdev_event returns NOTIFY_OK and schedules: --> dsa_slave_switchdev_event_work - -> dsa_port_fdb_add - -> dsa_port_notify(DSA_NOTIFIER_FDB_ADD) - -> dsa_switch_fdb_add - -> if (!ds->ops->port_fdb_add) return -EOPNOTSUPP; - -> an error is printed with dev_dbg, and - dsa_fdb_offload_notify(switchdev_work) is not called. - -We can avoid scheduling the worker for nothing and say NOTIFY_DONE. -Because we don't call dsa_fdb_offload_notify, the static FDB entry will -remain just in the software bridge. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - net/dsa/slave.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2172,6 +2172,9 @@ static int dsa_slave_switchdev_event(str - - dp = dsa_slave_to_port(dev); - -+ if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) -+ return NOTIFY_DONE; -+ - switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); - if (!switchdev_work) - return NOTIFY_BAD; diff --git a/target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch b/target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch deleted file mode 100644 index e7b9af1951..0000000000 --- a/target/linux/generic/backport-5.15/725-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch +++ /dev/null @@ -1,264 +0,0 @@ -From d5f19486cee79d04c054427577ac96ed123706db Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Wed, 6 Jan 2021 11:51:35 +0200 -Subject: [PATCH] net: dsa: listen for SWITCHDEV_{FDB,DEL}_ADD_TO_DEVICE on - foreign bridge neighbors - -Some DSA switches (and not only) cannot learn source MAC addresses from -packets injected from the CPU. They only perform hardware address -learning from inbound traffic. - -This can be problematic when we have a bridge spanning some DSA switch -ports and some non-DSA ports (which we'll call "foreign interfaces" from -DSA's perspective). - -There are 2 classes of problems created by the lack of learning on -CPU-injected traffic: -- excessive flooding, due to the fact that DSA treats those addresses as - unknown -- the risk of stale routes, which can lead to temporary packet loss - -To illustrate the second class, consider the following situation, which -is common in production equipment (wireless access points, where there -is a WLAN interface and an Ethernet switch, and these form a single -bridging domain). - - AP 1: - +------------------------------------------------------------------------+ - | br0 | - +------------------------------------------------------------------------+ - +------------+ +------------+ +------------+ +------------+ +------------+ - | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | - +------------+ +------------+ +------------+ +------------+ +------------+ - | ^ ^ - | | | - | | | - | Client A Client B - | - | - | - +------------+ +------------+ +------------+ +------------+ +------------+ - | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | - +------------+ +------------+ +------------+ +------------+ +------------+ - +------------------------------------------------------------------------+ - | br0 | - +------------------------------------------------------------------------+ - AP 2 - -- br0 of AP 1 will know that Clients A and B are reachable via wlan0 -- the hardware fdb of a DSA switch driver today is not kept in sync with - the software entries on other bridge ports, so it will not know that - clients A and B are reachable via the CPU port UNLESS the hardware - switch itself performs SA learning from traffic injected from the CPU. - Nonetheless, a substantial number of switches don't. -- the hardware fdb of the DSA switch on AP 2 may autonomously learn that - Client A and B are reachable through swp0. Therefore, the software br0 - of AP 2 also may or may not learn this. In the example we're - illustrating, some Ethernet traffic has been going on, and br0 from AP - 2 has indeed learnt that it can reach Client B through swp0. - -One of the wireless clients, say Client B, disconnects from AP 1 and -roams to AP 2. The topology now looks like this: - - AP 1: - +------------------------------------------------------------------------+ - | br0 | - +------------------------------------------------------------------------+ - +------------+ +------------+ +------------+ +------------+ +------------+ - | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | - +------------+ +------------+ +------------+ +------------+ +------------+ - | ^ - | | - | Client A - | - | - | Client B - | | - | v - +------------+ +------------+ +------------+ +------------+ +------------+ - | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | - +------------+ +------------+ +------------+ +------------+ +------------+ - +------------------------------------------------------------------------+ - | br0 | - +------------------------------------------------------------------------+ - AP 2 - -- br0 of AP 1 still knows that Client A is reachable via wlan0 (no change) -- br0 of AP 1 will (possibly) know that Client B has left wlan0. There - are cases where it might never find out though. Either way, DSA today - does not process that notification in any way. -- the hardware FDB of the DSA switch on AP 1 may learn autonomously that - Client B can be reached via swp0, if it receives any packet with - Client 1's source MAC address over Ethernet. -- the hardware FDB of the DSA switch on AP 2 still thinks that Client B - can be reached via swp0. It does not know that it has roamed to wlan0, - because it doesn't perform SA learning from the CPU port. - -Now Client A contacts Client B. -AP 1 routes the packet fine towards swp0 and delivers it on the Ethernet -segment. -AP 2 sees a frame on swp0 and its fdb says that the destination is swp0. -Hairpinning is disabled => drop. - -This problem comes from the fact that these switches have a 'blind spot' -for addresses coming from software bridging. The generic solution is not -to assume that hardware learning can be enabled somehow, but to listen -to more bridge learning events. It turns out that the bridge driver does -learn in software from all inbound frames, in __br_handle_local_finish. -A proper SWITCHDEV_FDB_ADD_TO_DEVICE notification is emitted for the -addresses serviced by the bridge on 'foreign' interfaces. The software -bridge also does the right thing on migration, by notifying that the old -entry is deleted, so that does not need to be special-cased in DSA. When -it is deleted, we just need to delete our static FDB entry towards the -CPU too, and wait. - -The problem is that DSA currently only cares about SWITCHDEV_FDB_ADD_TO_DEVICE -events received on its own interfaces, such as static FDB entries. - -Luckily we can change that, and DSA can listen to all switchdev FDB -add/del events in the system and figure out if those events were emitted -by a bridge that spans at least one of DSA's own ports. In case that is -true, DSA will also offload that address towards its own CPU port, in -the eventuality that there might be bridge clients attached to the DSA -switch who want to talk to the station connected to the foreign -interface. - -In terms of implementation, we need to keep the fdb_info->added_by_user -check for the case where the switchdev event was targeted directly at a -DSA switch port. But we don't need to look at that flag for snooped -events. So the check is currently too late, we need to move it earlier. -This also simplifies the code a bit, since we avoid uselessly allocating -and freeing switchdev_work. - -We could probably do some improvements in the future. For example, -multi-bridge support is rudimentary at the moment. If there are two -bridges spanning a DSA switch's ports, and both of them need to service -the same MAC address, then what will happen is that the migration of one -of those stations will trigger the deletion of the FDB entry from the -CPU port while it is still used by other bridge. That could be improved -with reference counting but is left for another time. - -This behavior needs to be enabled at driver level by setting -ds->assisted_learning_on_cpu_port = true. This is because we don't want -to inflict a potential performance penalty (accesses through -MDIO/I2C/SPI are expensive) to hardware that really doesn't need it -because address learning on the CPU port works there. - -Reported-by: DENG Qingfang -Signed-off-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - include/net/dsa.h | 5 +++++ - net/dsa/slave.c | 66 +++++++++++++++++++++++++++++++++++++++++++++---------- - 2 files changed, 60 insertions(+), 11 deletions(-) - ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -317,6 +317,11 @@ struct dsa_switch { - */ - bool untag_bridge_pvid; - -+ /* Let DSA manage the FDB entries towards the CPU, based on the -+ * software bridge database. -+ */ -+ bool assisted_learning_on_cpu_port; -+ - /* In case vlan_filtering_is_global is set, the VLAN awareness state - * should be retrieved from here and not from the per-port settings. - */ ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2149,6 +2149,28 @@ static void dsa_slave_switchdev_event_wo - dev_put(dp->slave); - } - -+static int dsa_lower_dev_walk(struct net_device *lower_dev, -+ struct netdev_nested_priv *priv) -+{ -+ if (dsa_slave_dev_check(lower_dev)) { -+ priv->data = (void *)netdev_priv(lower_dev); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static struct dsa_slave_priv *dsa_slave_dev_lower_find(struct net_device *dev) -+{ -+ struct netdev_nested_priv priv = { -+ .data = NULL, -+ }; -+ -+ netdev_walk_all_lower_dev_rcu(dev, dsa_lower_dev_walk, &priv); -+ -+ return (struct dsa_slave_priv *)priv.data; -+} -+ - /* Called under rcu_read_lock() */ - static int dsa_slave_switchdev_event(struct notifier_block *unused, - unsigned long event, void *ptr) -@@ -2167,10 +2189,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: -- if (!dsa_slave_dev_check(dev)) -- return NOTIFY_DONE; -+ fdb_info = ptr; -+ -+ if (dsa_slave_dev_check(dev)) { -+ if (!fdb_info->added_by_user) -+ return NOTIFY_OK; -+ -+ dp = dsa_slave_to_port(dev); -+ } else { -+ /* Snoop addresses learnt on foreign interfaces -+ * bridged with us, for switches that don't -+ * automatically learn SA from CPU-injected traffic -+ */ -+ struct net_device *br_dev; -+ struct dsa_slave_priv *p; -+ -+ br_dev = netdev_master_upper_dev_get_rcu(dev); -+ if (!br_dev) -+ return NOTIFY_DONE; -+ -+ if (!netif_is_bridge_master(br_dev)) -+ return NOTIFY_DONE; -+ -+ p = dsa_slave_dev_lower_find(br_dev); -+ if (!p) -+ return NOTIFY_DONE; - -- dp = dsa_slave_to_port(dev); -+ dp = p->dp->cpu_dp; -+ -+ if (!dp->ds->assisted_learning_on_cpu_port) -+ return NOTIFY_DONE; -+ } - - if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) - return NOTIFY_DONE; -@@ -2185,18 +2234,13 @@ static int dsa_slave_switchdev_event(str - switchdev_work->port = dp->index; - switchdev_work->event = event; - -- fdb_info = ptr; -- -- if (!fdb_info->added_by_user) { -- kfree(switchdev_work); -- return NOTIFY_OK; -- } -- - ether_addr_copy(switchdev_work->addr, - fdb_info->addr); - switchdev_work->vid = fdb_info->vid; - -- dev_hold(dev); -+ /* Hold a reference on the slave for dsa_fdb_offload_notify */ -+ if (dsa_is_user_port(dp->ds, dp->index)) -+ dev_hold(dev); - dsa_schedule_work(&switchdev_work->work); - break; - default: diff --git a/target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch b/target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch deleted file mode 100644 index f3a6f948ad..0000000000 --- a/target/linux/generic/backport-5.15/730-net-dsa-mt7530-setup-core-clock-even-in-TRGMII-mode.patch +++ /dev/null @@ -1,84 +0,0 @@ -From c3b8e07909dbe67b0d580416c1a5257643a73be7 Mon Sep 17 00:00:00 2001 -From: Ilya Lipnitskiy -Date: Fri, 12 Mar 2021 00:07:03 -0800 -Subject: [PATCH] net: dsa: mt7530: setup core clock even in TRGMII mode - -A recent change to MIPS ralink reset logic made it so mt7530 actually -resets the switch on platforms such as mt7621 (where bit 2 is the reset -line for the switch). That exposed an issue where the switch would not -function properly in TRGMII mode after a reset. - -Reconfigure core clock in TRGMII mode to fix the issue. - -Tested on Ubiquiti ER-X (MT7621) with TRGMII mode enabled. - -Fixes: 3f9ef7785a9c ("MIPS: ralink: manage low reset lines") -Signed-off-by: Ilya Lipnitskiy -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 52 +++++++++++++++++++--------------------- - 1 file changed, 25 insertions(+), 27 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -436,34 +436,32 @@ mt7530_pad_clk_setup(struct dsa_switch * - TD_DM_DRVP(8) | TD_DM_DRVN(8)); - - /* Setup core clock for MT7530 */ -- if (!trgint) { -- /* Disable MT7530 core clock */ -- core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); -- -- /* Disable PLL, since phy_device has not yet been created -- * provided for phy_[read,write]_mmd_indirect is called, we -- * provide our own core_write_mmd_indirect to complete this -- * function. -- */ -- core_write_mmd_indirect(priv, -- CORE_GSWPLL_GRP1, -- MDIO_MMD_VEND2, -- 0); -- -- /* Set core clock into 500Mhz */ -- core_write(priv, CORE_GSWPLL_GRP2, -- RG_GSWPLL_POSDIV_500M(1) | -- RG_GSWPLL_FBKDIV_500M(25)); -- -- /* Enable PLL */ -- core_write(priv, CORE_GSWPLL_GRP1, -- RG_GSWPLL_EN_PRE | -- RG_GSWPLL_POSDIV_200M(2) | -- RG_GSWPLL_FBKDIV_200M(32)); -- -- /* Enable MT7530 core clock */ -- core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); -- } -+ /* Disable MT7530 core clock */ -+ core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); -+ -+ /* Disable PLL, since phy_device has not yet been created -+ * provided for phy_[read,write]_mmd_indirect is called, we -+ * provide our own core_write_mmd_indirect to complete this -+ * function. -+ */ -+ core_write_mmd_indirect(priv, -+ CORE_GSWPLL_GRP1, -+ MDIO_MMD_VEND2, -+ 0); -+ -+ /* Set core clock into 500Mhz */ -+ core_write(priv, CORE_GSWPLL_GRP2, -+ RG_GSWPLL_POSDIV_500M(1) | -+ RG_GSWPLL_FBKDIV_500M(25)); -+ -+ /* Enable PLL */ -+ core_write(priv, CORE_GSWPLL_GRP1, -+ RG_GSWPLL_EN_PRE | -+ RG_GSWPLL_POSDIV_200M(2) | -+ RG_GSWPLL_FBKDIV_200M(32)); -+ -+ /* Enable MT7530 core clock */ -+ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); - - /* Setup the MT7530 TRGMII Tx Clock */ - core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); diff --git a/target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch b/target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch deleted file mode 100644 index 9e5047a16b..0000000000 --- a/target/linux/generic/backport-5.15/731-v5.12-net-dsa-mt7530-MT7530-optional-GPIO-support.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 429a0edeefd88cbfca5c417dfb8561047bb50769 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Mon, 25 Jan 2021 12:43:22 +0800 -Subject: [PATCH] net: dsa: mt7530: MT7530 optional GPIO support - -MT7530's LED controller can drive up to 15 LED/GPIOs. - -Add support for GPIO control and allow users to use its GPIOs by -setting gpio-controller property in device tree. - -Signed-off-by: DENG Qingfang -Reviewed-by: Linus Walleij -Reviewed-by: Andrew Lunn -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mt7530.c | 110 +++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.h | 20 +++++++ - 2 files changed, 130 insertions(+) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - - #include "mt7530.h" -@@ -1534,6 +1535,109 @@ mtk_get_tag_protocol(struct dsa_switch * - } - } - -+static inline u32 -+mt7530_gpio_to_bit(unsigned int offset) -+{ -+ /* Map GPIO offset to register bit -+ * [ 2: 0] port 0 LED 0..2 as GPIO 0..2 -+ * [ 6: 4] port 1 LED 0..2 as GPIO 3..5 -+ * [10: 8] port 2 LED 0..2 as GPIO 6..8 -+ * [14:12] port 3 LED 0..2 as GPIO 9..11 -+ * [18:16] port 4 LED 0..2 as GPIO 12..14 -+ */ -+ return BIT(offset + offset / 3); -+} -+ -+static int -+mt7530_gpio_get(struct gpio_chip *gc, unsigned int offset) -+{ -+ struct mt7530_priv *priv = gpiochip_get_data(gc); -+ u32 bit = mt7530_gpio_to_bit(offset); -+ -+ return !!(mt7530_read(priv, MT7530_LED_GPIO_DATA) & bit); -+} -+ -+static void -+mt7530_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) -+{ -+ struct mt7530_priv *priv = gpiochip_get_data(gc); -+ u32 bit = mt7530_gpio_to_bit(offset); -+ -+ if (value) -+ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit); -+ else -+ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit); -+} -+ -+static int -+mt7530_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) -+{ -+ struct mt7530_priv *priv = gpiochip_get_data(gc); -+ u32 bit = mt7530_gpio_to_bit(offset); -+ -+ return (mt7530_read(priv, MT7530_LED_GPIO_DIR) & bit) ? -+ GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; -+} -+ -+static int -+mt7530_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) -+{ -+ struct mt7530_priv *priv = gpiochip_get_data(gc); -+ u32 bit = mt7530_gpio_to_bit(offset); -+ -+ mt7530_clear(priv, MT7530_LED_GPIO_OE, bit); -+ mt7530_clear(priv, MT7530_LED_GPIO_DIR, bit); -+ -+ return 0; -+} -+ -+static int -+mt7530_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value) -+{ -+ struct mt7530_priv *priv = gpiochip_get_data(gc); -+ u32 bit = mt7530_gpio_to_bit(offset); -+ -+ mt7530_set(priv, MT7530_LED_GPIO_DIR, bit); -+ -+ if (value) -+ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit); -+ else -+ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit); -+ -+ mt7530_set(priv, MT7530_LED_GPIO_OE, bit); -+ -+ return 0; -+} -+ -+static int -+mt7530_setup_gpio(struct mt7530_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ struct gpio_chip *gc; -+ -+ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); -+ if (!gc) -+ return -ENOMEM; -+ -+ mt7530_write(priv, MT7530_LED_GPIO_OE, 0); -+ mt7530_write(priv, MT7530_LED_GPIO_DIR, 0); -+ mt7530_write(priv, MT7530_LED_IO_MODE, 0); -+ -+ gc->label = "mt7530"; -+ gc->parent = dev; -+ gc->owner = THIS_MODULE; -+ gc->get_direction = mt7530_gpio_get_direction; -+ gc->direction_input = mt7530_gpio_direction_input; -+ gc->direction_output = mt7530_gpio_direction_output; -+ gc->get = mt7530_gpio_get; -+ gc->set = mt7530_gpio_set; -+ gc->base = -1; -+ gc->ngpio = 15; -+ gc->can_sleep = true; -+ -+ return devm_gpiochip_add_data(dev, gc, priv); -+} -+ - static int - mt7530_setup(struct dsa_switch *ds) - { -@@ -1675,6 +1779,12 @@ mt7530_setup(struct dsa_switch *ds) - } - } - -+ if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) { -+ ret = mt7530_setup_gpio(priv); -+ if (ret) -+ return ret; -+ } -+ - mt7530_setup_port5(ds, interface); - - /* Flush the FDB table */ ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -529,6 +529,26 @@ enum mt7531_clk_skew { - #define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16) - #define MT7531_EXT_P_MDIO_12 (2 << 16) - -+/* Registers for LED GPIO control (MT7530 only) -+ * All registers follow this pattern: -+ * [ 2: 0] port 0 -+ * [ 6: 4] port 1 -+ * [10: 8] port 2 -+ * [14:12] port 3 -+ * [18:16] port 4 -+ */ -+ -+/* LED enable, 0: Disable, 1: Enable (Default) */ -+#define MT7530_LED_EN 0x7d00 -+/* LED mode, 0: GPIO mode, 1: PHY mode (Default) */ -+#define MT7530_LED_IO_MODE 0x7d04 -+/* GPIO direction, 0: Input, 1: Output */ -+#define MT7530_LED_GPIO_DIR 0x7d10 -+/* GPIO output enable, 0: Disable, 1: Enable */ -+#define MT7530_LED_GPIO_OE 0x7d14 -+/* GPIO value, 0: Low, 1: High */ -+#define MT7530_LED_GPIO_DATA 0x7d18 -+ - #define MT7530_CREV 0x7ffc - #define CHIP_NAME_SHIFT 16 - #define MT7530_ID 0x7530 diff --git a/target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch b/target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch deleted file mode 100644 index 38dd8a7296..0000000000 --- a/target/linux/generic/backport-5.15/731-v5.13-net-dsa-mt7530-Add-support-for-EEE-features.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 40b5d2f15c091fa9c854acde91ad2acb504027d7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= -Date: Mon, 12 Apr 2021 08:50:31 +0200 -Subject: [PATCH] net: dsa: mt7530: Add support for EEE features -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch adds EEE support. - -Signed-off-by: René van Dorst -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 43 ++++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.h | 14 ++++++++++++- - 2 files changed, 56 insertions(+), 1 deletion(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2371,6 +2371,17 @@ static void mt753x_phylink_mac_link_up(s - mcr |= PMCR_RX_FC_EN; - } - -+ if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, 0) >= 0) { -+ switch (speed) { -+ case SPEED_1000: -+ mcr |= PMCR_FORCE_EEE1G; -+ break; -+ case SPEED_100: -+ mcr |= PMCR_FORCE_EEE100; -+ break; -+ } -+ } -+ - mt7530_set(priv, MT7530_PMCR_P(port), mcr); - } - -@@ -2601,6 +2612,36 @@ mt753x_phy_write(struct dsa_switch *ds, - return priv->info->phy_write(ds, port, regnum, val); - } - -+static int mt753x_get_mac_eee(struct dsa_switch *ds, int port, -+ struct ethtool_eee *e) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 eeecr = mt7530_read(priv, MT7530_PMEEECR_P(port)); -+ -+ e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN); -+ e->tx_lpi_timer = GET_LPI_THRESH(eeecr); -+ -+ return 0; -+} -+ -+static int mt753x_set_mac_eee(struct dsa_switch *ds, int port, -+ struct ethtool_eee *e) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 set, mask = LPI_THRESH_MASK | LPI_MODE_EN; -+ -+ if (e->tx_lpi_timer > 0xFFF) -+ return -EINVAL; -+ -+ set = SET_LPI_THRESH(e->tx_lpi_timer); -+ if (!e->tx_lpi_enabled) -+ /* Force LPI Mode without a delay */ -+ set |= LPI_MODE_EN; -+ mt7530_rmw(priv, MT7530_PMEEECR_P(port), mask, set); -+ -+ return 0; -+} -+ - static const struct dsa_switch_ops mt7530_switch_ops = { - .get_tag_protocol = mtk_get_tag_protocol, - .setup = mt753x_setup, -@@ -2629,6 +2670,8 @@ static const struct dsa_switch_ops mt753 - .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, - .phylink_mac_link_down = mt753x_phylink_mac_link_down, - .phylink_mac_link_up = mt753x_phylink_mac_link_up, -+ .get_mac_eee = mt753x_get_mac_eee, -+ .set_mac_eee = mt753x_set_mac_eee, - }; - - static const struct mt753x_info mt753x_table[] = { ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -240,6 +240,8 @@ enum mt7530_vlan_port_attr { - #define PMCR_RX_EN BIT(13) - #define PMCR_BACKOFF_EN BIT(9) - #define PMCR_BACKPR_EN BIT(8) -+#define PMCR_FORCE_EEE1G BIT(7) -+#define PMCR_FORCE_EEE100 BIT(6) - #define PMCR_TX_FC_EN BIT(5) - #define PMCR_RX_FC_EN BIT(4) - #define PMCR_FORCE_SPEED_1000 BIT(3) -@@ -264,7 +266,8 @@ enum mt7530_vlan_port_attr { - #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ - PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ - PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ -- PMCR_FORCE_FDX | PMCR_FORCE_LNK) -+ PMCR_FORCE_FDX | PMCR_FORCE_LNK | \ -+ PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100) - #define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \ - PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ - PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ -@@ -273,6 +276,15 @@ enum mt7530_vlan_port_attr { - PMCR_FORCE_SPEED_1000 | \ - PMCR_FORCE_FDX | PMCR_FORCE_LNK) - -+#define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100) -+#define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24) -+#define WAKEUP_TIME_100(x) (((x) & 0xFF) << 16) -+#define LPI_THRESH_MASK GENMASK(15, 4) -+#define LPI_THRESH_SHT 4 -+#define SET_LPI_THRESH(x) (((x) << LPI_THRESH_SHT) & LPI_THRESH_MASK) -+#define GET_LPI_THRESH(x) (((x) & LPI_THRESH_MASK) >> LPI_THRESH_SHT) -+#define LPI_MODE_EN BIT(0) -+ - #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) - #define PMSR_EEE1G BIT(7) - #define PMSR_EEE100M BIT(6) diff --git a/target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch b/target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch deleted file mode 100644 index 60b07e5a3e..0000000000 --- a/target/linux/generic/backport-5.15/732-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch +++ /dev/null @@ -1,1935 +0,0 @@ -From 83216e3988cd196183542937c9bd58b279f946af Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 12 Apr 2021 19:47:17 +0200 -Subject: of: net: pass the dst buffer to of_get_mac_address() - -of_get_mac_address() returns a "const void*" pointer to a MAC address. -Lately, support to fetch the MAC address by an NVMEM provider was added. -But this will only work with platform devices. It will not work with -PCI devices (e.g. of an integrated root complex) and esp. not with DSA -ports. - -There is an of_* variant of the nvmem binding which works without -devices. The returned data of a nvmem_cell_read() has to be freed after -use. On the other hand the return of_get_mac_address() points to some -static data without a lifetime. The trick for now, was to allocate a -device resource managed buffer which is then returned. This will only -work if we have an actual device. - -Change it, so that the caller of of_get_mac_address() has to supply a -buffer where the MAC address is written to. Unfortunately, this will -touch all drivers which use the of_get_mac_address(). - -Usually the code looks like: - - const char *addr; - addr = of_get_mac_address(np); - if (!IS_ERR(addr)) - ether_addr_copy(ndev->dev_addr, addr); - -This can then be simply rewritten as: - - of_get_mac_address(np, ndev->dev_addr); - -Sometimes is_valid_ether_addr() is used to test the MAC address. -of_get_mac_address() already makes sure, it just returns a valid MAC -address. Thus we can just test its return code. But we have to be -careful if there are still other sources for the MAC address before the -of_get_mac_address(). In this case we have to keep the -is_valid_ether_addr() call. - -The following coccinelle patch was used to convert common cases to the -new style. Afterwards, I've manually gone over the drivers and fixed the -return code variable: either used a new one or if one was already -available use that. Mansour Moufid, thanks for that coccinelle patch! - - -@a@ -identifier x; -expression y, z; -@@ -- x = of_get_mac_address(y); -+ x = of_get_mac_address(y, z); - <... -- ether_addr_copy(z, x); - ...> - -@@ -identifier a.x; -@@ -- if (<+... x ...+>) {} - -@@ -identifier a.x; -@@ - if (<+... x ...+>) { - ... - } -- else {} - -@@ -identifier a.x; -expression e; -@@ -- if (<+... x ...+>@e) -- {} -- else -+ if (!(e)) - {...} - -@@ -expression x, y, z; -@@ -- x = of_get_mac_address(y, z); -+ of_get_mac_address(y, z); - ... when != x - - -All drivers, except drivers/net/ethernet/aeroflex/greth.c, were -compile-time tested. - -Suggested-by: Andrew Lunn -Signed-off-by: Michael Walle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - arch/arm/mach-mvebu/kirkwood.c | 3 +- - arch/powerpc/sysdev/tsi108_dev.c | 5 +- - drivers/net/ethernet/aeroflex/greth.c | 6 +-- - drivers/net/ethernet/allwinner/sun4i-emac.c | 10 ++-- - drivers/net/ethernet/altera/altera_tse_main.c | 7 +-- - drivers/net/ethernet/arc/emac_main.c | 8 +-- - drivers/net/ethernet/atheros/ag71xx.c | 7 +-- - drivers/net/ethernet/broadcom/bcm4908_enet.c | 7 +-- - drivers/net/ethernet/broadcom/bcmsysport.c | 7 +-- - drivers/net/ethernet/broadcom/bgmac-bcma.c | 10 ++-- - drivers/net/ethernet/broadcom/bgmac-platform.c | 11 ++-- - drivers/net/ethernet/cadence/macb_main.c | 11 ++-- - drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 8 +-- - drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 5 +- - drivers/net/ethernet/davicom/dm9000.c | 10 ++-- - drivers/net/ethernet/ethoc.c | 6 +-- - drivers/net/ethernet/ezchip/nps_enet.c | 7 +-- - drivers/net/ethernet/freescale/fec_main.c | 7 +-- - drivers/net/ethernet/freescale/fec_mpc52xx.c | 7 +-- - drivers/net/ethernet/freescale/fman/mac.c | 9 ++-- - .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 5 +- - drivers/net/ethernet/freescale/gianfar.c | 8 +-- - drivers/net/ethernet/freescale/ucc_geth.c | 5 +- - drivers/net/ethernet/hisilicon/hisi_femac.c | 7 +-- - drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 7 +-- - drivers/net/ethernet/lantiq_xrx200.c | 7 +-- - drivers/net/ethernet/marvell/mv643xx_eth.c | 5 +- - drivers/net/ethernet/marvell/mvneta.c | 6 +-- - .../net/ethernet/marvell/prestera/prestera_main.c | 11 ++-- - drivers/net/ethernet/marvell/pxa168_eth.c | 9 +--- - drivers/net/ethernet/marvell/sky2.c | 8 ++- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 ++-- - drivers/net/ethernet/micrel/ks8851_common.c | 7 ++- - drivers/net/ethernet/microchip/lan743x_main.c | 5 +- - drivers/net/ethernet/nxp/lpc_eth.c | 4 +- - drivers/net/ethernet/qualcomm/qca_spi.c | 10 ++-- - drivers/net/ethernet/qualcomm/qca_uart.c | 9 +--- - drivers/net/ethernet/renesas/ravb_main.c | 12 +++-- - drivers/net/ethernet/renesas/sh_eth.c | 5 +- - .../net/ethernet/samsung/sxgbe/sxgbe_platform.c | 13 ++--- - drivers/net/ethernet/socionext/sni_ave.c | 10 ++-- - .../net/ethernet/stmicro/stmmac/dwmac-anarion.c | 2 +- - .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-generic.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-intel-plat.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c | 2 +- - .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +- - .../net/ethernet/stmicro/stmmac/dwmac-visconti.c | 2 +- - drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +- - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- - .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 14 ++--- - .../net/ethernet/stmicro/stmmac/stmmac_platform.h | 2 +- - drivers/net/ethernet/ti/am65-cpsw-nuss.c | 19 ++++--- - drivers/net/ethernet/ti/cpsw.c | 7 +-- - drivers/net/ethernet/ti/cpsw_new.c | 7 +-- - drivers/net/ethernet/ti/davinci_emac.c | 8 +-- - drivers/net/ethernet/ti/netcp_core.c | 7 +-- - drivers/net/ethernet/wiznet/w5100-spi.c | 8 ++- - drivers/net/ethernet/wiznet/w5100.c | 2 +- - drivers/net/ethernet/xilinx/ll_temac_main.c | 8 +-- - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 15 +++--- - drivers/net/ethernet/xilinx/xilinx_emaclite.c | 8 +-- - drivers/net/wireless/ath/ath9k/init.c | 5 +- - drivers/net/wireless/mediatek/mt76/eeprom.c | 9 +--- - drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 6 +-- - drivers/of/of_net.c | 60 ++++++++++------------ - drivers/staging/octeon/ethernet.c | 10 ++-- - drivers/staging/wfx/main.c | 7 ++- - include/linux/of_net.h | 6 +-- - include/net/dsa.h | 2 +- - net/dsa/dsa2.c | 2 +- - net/dsa/slave.c | 2 +- - net/ethernet/eth.c | 11 ++-- - 85 files changed, 218 insertions(+), 364 deletions(-) - ---- a/arch/arm/mach-mvebu/kirkwood.c -+++ b/arch/arm/mach-mvebu/kirkwood.c -@@ -84,6 +84,7 @@ static void __init kirkwood_dt_eth_fixup - struct device_node *pnp = of_get_parent(np); - struct clk *clk; - struct property *pmac; -+ u8 tmpmac[ETH_ALEN]; - void __iomem *io; - u8 *macaddr; - u32 reg; -@@ -93,7 +94,7 @@ static void __init kirkwood_dt_eth_fixup - - /* skip disabled nodes or nodes with valid MAC address*/ - if (!of_device_is_available(pnp) || -- !IS_ERR(of_get_mac_address(np))) -+ !of_get_mac_address(np, tmpmac)) - goto eth_fixup_skip; - - clk = of_clk_get(pnp, 0); ---- a/arch/powerpc/sysdev/tsi108_dev.c -+++ b/arch/powerpc/sysdev/tsi108_dev.c -@@ -73,7 +73,6 @@ static int __init tsi108_eth_of_init(voi - struct device_node *phy, *mdio; - hw_info tsi_eth_data; - const unsigned int *phy_id; -- const void *mac_addr; - const phandle *ph; - - memset(r, 0, sizeof(r)); -@@ -101,9 +100,7 @@ static int __init tsi108_eth_of_init(voi - goto err; - } - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(tsi_eth_data.mac_addr, mac_addr); -+ of_get_mac_address(np, tsi_eth_data.mac_addr); - - ph = of_get_property(np, "mdio-handle", NULL); - mdio = of_find_node_by_phandle(*ph); ---- a/drivers/net/ethernet/aeroflex/greth.c -+++ b/drivers/net/ethernet/aeroflex/greth.c -@@ -1449,10 +1449,10 @@ static int greth_of_probe(struct platfor - break; - } - if (i == 6) { -- const u8 *addr; -+ u8 addr[ETH_ALEN]; - -- addr = of_get_mac_address(ofdev->dev.of_node); -- if (!IS_ERR(addr)) { -+ err = of_get_mac_address(ofdev->dev.of_node, addr); -+ if (!err) { - for (i = 0; i < 6; i++) - macaddr[i] = (unsigned int) addr[i]; - } else { ---- a/drivers/net/ethernet/allwinner/sun4i-emac.c -+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c -@@ -790,7 +790,6 @@ static int emac_probe(struct platform_de - struct emac_board_info *db; - struct net_device *ndev; - int ret = 0; -- const char *mac_addr; - - ndev = alloc_etherdev(sizeof(struct emac_board_info)); - if (!ndev) { -@@ -853,12 +852,9 @@ static int emac_probe(struct platform_de - } - - /* Read MAC-address from DT */ -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- -- /* Check if the MAC address is valid, if not get a random one */ -- if (!is_valid_ether_addr(ndev->dev_addr)) { -+ ret = of_get_mac_address(np, ndev->dev_addr); -+ if (ret) { -+ /* if the MAC address is invalid get a random one */ - eth_hw_addr_random(ndev); - dev_warn(&pdev->dev, "using random MAC address %pM\n", - ndev->dev_addr); ---- a/drivers/net/ethernet/altera/altera_tse_main.c -+++ b/drivers/net/ethernet/altera/altera_tse_main.c -@@ -1351,7 +1351,6 @@ static int altera_tse_probe(struct platf - struct resource *control_port; - struct resource *dma_res; - struct altera_tse_private *priv; -- const unsigned char *macaddr; - void __iomem *descmap; - const struct of_device_id *of_id = NULL; - -@@ -1528,10 +1527,8 @@ static int altera_tse_probe(struct platf - priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE; - - /* get default MAC address from device tree */ -- macaddr = of_get_mac_address(pdev->dev.of_node); -- if (!IS_ERR(macaddr)) -- ether_addr_copy(ndev->dev_addr, macaddr); -- else -+ ret = of_get_mac_address(pdev->dev.of_node, ndev->dev_addr); -+ if (ret) - eth_hw_addr_random(ndev); - - /* get phy addr and create mdio */ ---- a/drivers/net/ethernet/arc/emac_main.c -+++ b/drivers/net/ethernet/arc/emac_main.c -@@ -857,7 +857,6 @@ int arc_emac_probe(struct net_device *nd - struct device_node *phy_node; - struct phy_device *phydev = NULL; - struct arc_emac_priv *priv; -- const char *mac_addr; - unsigned int id, clock_frequency, irq; - int err; - -@@ -942,11 +941,8 @@ int arc_emac_probe(struct net_device *nd - } - - /* Get MAC address from device tree */ -- mac_addr = of_get_mac_address(dev->of_node); -- -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- else -+ err = of_get_mac_address(dev->of_node, ndev->dev_addr); -+ if (err) - eth_hw_addr_random(ndev); - - arc_emac_set_address_internal(ndev); ---- a/drivers/net/ethernet/atheros/ag71xx.c -+++ b/drivers/net/ethernet/atheros/ag71xx.c -@@ -1856,7 +1856,6 @@ static int ag71xx_probe(struct platform_ - const struct ag71xx_dcfg *dcfg; - struct net_device *ndev; - struct resource *res; -- const void *mac_addr; - int tx_size, err, i; - struct ag71xx *ag; - -@@ -1952,10 +1951,8 @@ static int ag71xx_probe(struct platform_ - ag->stop_desc->ctrl = 0; - ag->stop_desc->next = (u32)ag->stop_desc_dma; - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); -- if (IS_ERR(mac_addr) || !is_valid_ether_addr(ndev->dev_addr)) { -+ err = of_get_mac_address(np, ndev->dev_addr); -+ if (err) { - netif_err(ag, probe, ndev, "invalid MAC address, using random address\n"); - eth_random_addr(ndev->dev_addr); - } ---- a/drivers/net/ethernet/broadcom/bcmsysport.c -+++ b/drivers/net/ethernet/broadcom/bcmsysport.c -@@ -2468,7 +2468,6 @@ static int bcm_sysport_probe(struct plat - struct bcm_sysport_priv *priv; - struct device_node *dn; - struct net_device *dev; -- const void *macaddr; - u32 txq, rxq; - int ret; - -@@ -2563,12 +2562,10 @@ static int bcm_sysport_probe(struct plat - } - - /* Initialize netdevice members */ -- macaddr = of_get_mac_address(dn); -- if (IS_ERR(macaddr)) { -+ ret = of_get_mac_address(dn, dev->dev_addr); -+ if (ret) { - dev_warn(&pdev->dev, "using random Ethernet MAC\n"); - eth_hw_addr_random(dev); -- } else { -- ether_addr_copy(dev->dev_addr, macaddr); - } - - SET_NETDEV_DEV(dev, &pdev->dev); ---- a/drivers/net/ethernet/broadcom/bgmac-bcma.c -+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c -@@ -115,7 +115,7 @@ static int bgmac_probe(struct bcma_devic - struct ssb_sprom *sprom = &core->bus->sprom; - struct mii_bus *mii_bus; - struct bgmac *bgmac; -- const u8 *mac = NULL; -+ const u8 *mac; - int err; - - bgmac = bgmac_alloc(&core->dev); -@@ -128,11 +128,10 @@ static int bgmac_probe(struct bcma_devic - - bcma_set_drvdata(core, bgmac); - -- if (bgmac->dev->of_node) -- mac = of_get_mac_address(bgmac->dev->of_node); -+ err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); - - /* If no MAC address assigned via device tree, check SPROM */ -- if (IS_ERR_OR_NULL(mac)) { -+ if (err) { - switch (core->core_unit) { - case 0: - mac = sprom->et0mac; -@@ -149,10 +148,9 @@ static int bgmac_probe(struct bcma_devic - err = -ENOTSUPP; - goto err; - } -+ ether_addr_copy(bgmac->net_dev->dev_addr, mac); - } - -- ether_addr_copy(bgmac->net_dev->dev_addr, mac); -- - /* On BCM4706 we need common core to access PHY */ - if (core->id.id == BCMA_CORE_4706_MAC_GBIT && - !core->bus->drv_gmac_cmn.core) { ---- a/drivers/net/ethernet/broadcom/bgmac-platform.c -+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c -@@ -173,7 +173,7 @@ static int bgmac_probe(struct platform_d - struct device_node *np = pdev->dev.of_node; - struct bgmac *bgmac; - struct resource *regs; -- const u8 *mac_addr; -+ int ret; - - bgmac = bgmac_alloc(&pdev->dev); - if (!bgmac) -@@ -192,11 +192,10 @@ static int bgmac_probe(struct platform_d - bgmac->dev = &pdev->dev; - bgmac->dma_dev = &pdev->dev; - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(bgmac->net_dev->dev_addr, mac_addr); -- else -- dev_warn(&pdev->dev, "MAC address not present in device tree\n"); -+ ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); -+ if (ret) -+ dev_warn(&pdev->dev, -+ "MAC address not present in device tree\n"); - - bgmac->irq = platform_get_irq(pdev, 0); - if (bgmac->irq < 0) ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -4479,7 +4479,6 @@ static int macb_probe(struct platform_de - struct net_device *dev; - struct resource *regs; - void __iomem *mem; -- const char *mac; - struct macb *bp; - int err, val; - -@@ -4592,15 +4591,11 @@ static int macb_probe(struct platform_de - if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR) - bp->rx_intr_mask |= MACB_BIT(RXUBR); - -- mac = of_get_mac_address(np); -- if (PTR_ERR(mac) == -EPROBE_DEFER) { -- err = -EPROBE_DEFER; -+ err = of_get_mac_address(np, bp->dev->dev_addr); -+ if (err == -EPROBE_DEFER) - goto err_out_free_netdev; -- } else if (!IS_ERR_OR_NULL(mac)) { -- ether_addr_copy(bp->dev->dev_addr, mac); -- } else { -+ else if (err) - macb_get_hwaddr(bp); -- } - - err = of_get_phy_mode(np, &interface); - if (err) ---- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c -+++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c -@@ -1385,7 +1385,6 @@ static int octeon_mgmt_probe(struct plat - struct net_device *netdev; - struct octeon_mgmt *p; - const __be32 *data; -- const u8 *mac; - struct resource *res_mix; - struct resource *res_agl; - struct resource *res_agl_prt_ctl; -@@ -1502,11 +1501,8 @@ static int octeon_mgmt_probe(struct plat - netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM; - netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM - VLAN_HLEN; - -- mac = of_get_mac_address(pdev->dev.of_node); -- -- if (!IS_ERR(mac)) -- ether_addr_copy(netdev->dev_addr, mac); -- else -+ result = of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); -+ if (result) - eth_hw_addr_random(netdev); - - p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); ---- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c -+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c -@@ -1474,7 +1474,6 @@ static int bgx_init_of_phy(struct bgx *b - device_for_each_child_node(&bgx->pdev->dev, fwn) { - struct phy_device *pd; - struct device_node *phy_np; -- const char *mac; - - /* Should always be an OF node. But if it is not, we - * cannot handle it, so exit the loop. -@@ -1483,9 +1482,7 @@ static int bgx_init_of_phy(struct bgx *b - if (!node) - break; - -- mac = of_get_mac_address(node); -- if (!IS_ERR(mac)) -- ether_addr_copy(bgx->lmac[lmac].mac, mac); -+ of_get_mac_address(node, bgx->lmac[lmac].mac); - - SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev); - bgx->lmac[lmac].lmacid = lmac; ---- a/drivers/net/ethernet/davicom/dm9000.c -+++ b/drivers/net/ethernet/davicom/dm9000.c -@@ -1388,7 +1388,7 @@ static struct dm9000_plat_data *dm9000_p - { - struct dm9000_plat_data *pdata; - struct device_node *np = dev->of_node; -- const void *mac_addr; -+ int ret; - - if (!IS_ENABLED(CONFIG_OF) || !np) - return ERR_PTR(-ENXIO); -@@ -1402,11 +1402,9 @@ static struct dm9000_plat_data *dm9000_p - if (of_find_property(np, "davicom,no-eeprom", NULL)) - pdata->flags |= DM9000_PLATF_NO_EEPROM; - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(pdata->dev_addr, mac_addr); -- else if (PTR_ERR(mac_addr) == -EPROBE_DEFER) -- return ERR_CAST(mac_addr); -+ ret = of_get_mac_address(np, pdata->dev_addr); -+ if (ret == -EPROBE_DEFER) -+ return ERR_PTR(ret); - - return pdata; - } ---- a/drivers/net/ethernet/ethoc.c -+++ b/drivers/net/ethernet/ethoc.c -@@ -1151,11 +1151,7 @@ static int ethoc_probe(struct platform_d - ether_addr_copy(netdev->dev_addr, pdata->hwaddr); - priv->phy_id = pdata->phy_id; - } else { -- const void *mac; -- -- mac = of_get_mac_address(pdev->dev.of_node); -- if (!IS_ERR(mac)) -- ether_addr_copy(netdev->dev_addr, mac); -+ of_get_mac_address(pdev->dev.of_node, netdev->dev_addr); - priv->phy_id = -1; - } - ---- a/drivers/net/ethernet/ezchip/nps_enet.c -+++ b/drivers/net/ethernet/ezchip/nps_enet.c -@@ -575,7 +575,6 @@ static s32 nps_enet_probe(struct platfor - struct net_device *ndev; - struct nps_enet_priv *priv; - s32 err = 0; -- const char *mac_addr; - - if (!dev->of_node) - return -ENODEV; -@@ -602,10 +601,8 @@ static s32 nps_enet_probe(struct platfor - dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs_base); - - /* set kernel MAC address to dev */ -- mac_addr = of_get_mac_address(dev->of_node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- else -+ err = of_get_mac_address(dev->of_node, ndev->dev_addr); -+ if (err) - eth_hw_addr_random(ndev); - - /* Get IRQ number */ ---- a/drivers/net/ethernet/freescale/fec_main.c -+++ b/drivers/net/ethernet/freescale/fec_main.c -@@ -1666,6 +1666,7 @@ static void fec_get_mac(struct net_devic - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev); - unsigned char *iap, tmpaddr[ETH_ALEN]; -+ int ret; - - /* - * try to get mac address in following order: -@@ -1681,9 +1682,9 @@ static void fec_get_mac(struct net_devic - if (!is_valid_ether_addr(iap)) { - struct device_node *np = fep->pdev->dev.of_node; - if (np) { -- const char *mac = of_get_mac_address(np); -- if (!IS_ERR(mac)) -- iap = (unsigned char *) mac; -+ ret = of_get_mac_address(np, tmpaddr); -+ if (!ret) -+ iap = tmpaddr; - } - } - ---- a/drivers/net/ethernet/freescale/fec_mpc52xx.c -+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c -@@ -813,7 +813,6 @@ static int mpc52xx_fec_probe(struct plat - const u32 *prop; - int prop_size; - struct device_node *np = op->dev.of_node; -- const char *mac_addr; - - phys_addr_t rx_fifo; - phys_addr_t tx_fifo; -@@ -891,10 +890,8 @@ static int mpc52xx_fec_probe(struct plat - * - * First try to read MAC address from DT - */ -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) { -- ether_addr_copy(ndev->dev_addr, mac_addr); -- } else { -+ rv = of_get_mac_address(np, ndev->dev_addr); -+ if (rv) { - struct mpc52xx_fec __iomem *fec = priv->fec; - - /* ---- a/drivers/net/ethernet/freescale/fman/mac.c -+++ b/drivers/net/ethernet/freescale/fman/mac.c -@@ -616,7 +616,6 @@ static int mac_probe(struct platform_dev - struct platform_device *of_dev; - struct resource res; - struct mac_priv_s *priv; -- const u8 *mac_addr; - u32 val; - u8 fman_id; - phy_interface_t phy_if; -@@ -734,11 +733,9 @@ static int mac_probe(struct platform_dev - priv->cell_index = (u8)val; - - /* Get the MAC address */ -- mac_addr = of_get_mac_address(mac_node); -- if (IS_ERR(mac_addr)) -+ err = of_get_mac_address(mac_node, mac_dev->addr); -+ if (err) - dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node); -- else -- ether_addr_copy(mac_dev->addr, mac_addr); - - /* Get the port handles */ - nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL); -@@ -864,7 +861,7 @@ static int mac_probe(struct platform_dev - if (err < 0) - dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); - -- if (!IS_ERR(mac_addr)) -+ if (!is_zero_ether_addr(mac_dev->addr)) - dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); - - priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); ---- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c -+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c -@@ -918,7 +918,6 @@ static int fs_enet_probe(struct platform - const u32 *data; - struct clk *clk; - int err; -- const u8 *mac_addr; - const char *phy_connection_type; - int privsize, len, ret = -ENODEV; - -@@ -1006,9 +1005,7 @@ static int fs_enet_probe(struct platform - spin_lock_init(&fep->lock); - spin_lock_init(&fep->tx_lock); - -- mac_addr = of_get_mac_address(ofdev->dev.of_node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -+ of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr); - - ret = fep->ops->allocate_bd(ndev); - if (ret) ---- a/drivers/net/ethernet/freescale/gianfar.c -+++ b/drivers/net/ethernet/freescale/gianfar.c -@@ -641,7 +641,6 @@ static phy_interface_t gfar_get_interfac - static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) - { - const char *model; -- const void *mac_addr; - int err = 0, i; - phy_interface_t interface; - struct net_device *dev = NULL; -@@ -783,11 +782,8 @@ static int gfar_of_init(struct platform_ - if (stash_len || stash_idx) - priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING; - -- mac_addr = of_get_mac_address(np); -- -- if (!IS_ERR(mac_addr)) { -- ether_addr_copy(dev->dev_addr, mac_addr); -- } else { -+ err = of_get_mac_address(np, dev->dev_addr); -+ if (err) { - eth_hw_addr_random(dev); - dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr); - } ---- a/drivers/net/ethernet/freescale/ucc_geth.c -+++ b/drivers/net/ethernet/freescale/ucc_geth.c -@@ -3696,7 +3696,6 @@ static int ucc_geth_probe(struct platfor - int err, ucc_num, max_speed = 0; - const unsigned int *prop; - const char *sprop; -- const void *mac_addr; - phy_interface_t phy_interface; - static const int enet_to_speed[] = { - SPEED_10, SPEED_10, SPEED_10, -@@ -3906,9 +3905,7 @@ static int ucc_geth_probe(struct platfor - goto err_free_netdev; - } - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(dev->dev_addr, mac_addr); -+ of_get_mac_address(np, dev->dev_addr); - - ugeth->ug_info = ug_info; - ugeth->dev = device; ---- a/drivers/net/ethernet/hisilicon/hisi_femac.c -+++ b/drivers/net/ethernet/hisilicon/hisi_femac.c -@@ -772,7 +772,6 @@ static int hisi_femac_drv_probe(struct p - struct net_device *ndev; - struct hisi_femac_priv *priv; - struct phy_device *phy; -- const char *mac_addr; - int ret; - - ndev = alloc_etherdev(sizeof(*priv)); -@@ -842,10 +841,8 @@ static int hisi_femac_drv_probe(struct p - (unsigned long)phy->phy_id, - phy_modes(phy->interface)); - -- mac_addr = of_get_mac_address(node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- if (!is_valid_ether_addr(ndev->dev_addr)) { -+ ret = of_get_mac_address(node, ndev->dev_addr); -+ if (ret) { - eth_hw_addr_random(ndev); - dev_warn(dev, "using random MAC address %pM\n", - ndev->dev_addr); ---- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c -+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c -@@ -1098,7 +1098,6 @@ static int hix5hd2_dev_probe(struct plat - struct net_device *ndev; - struct hix5hd2_priv *priv; - struct mii_bus *bus; -- const char *mac_addr; - int ret; - - ndev = alloc_etherdev(sizeof(struct hix5hd2_priv)); -@@ -1220,10 +1219,8 @@ static int hix5hd2_dev_probe(struct plat - goto out_phy_node; - } - -- mac_addr = of_get_mac_address(node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- if (!is_valid_ether_addr(ndev->dev_addr)) { -+ ret = of_get_mac_address(node, ndev->dev_addr); -+ if (ret) { - eth_hw_addr_random(ndev); - netdev_warn(ndev, "using random MAC address %pM\n", - ndev->dev_addr); ---- a/drivers/net/ethernet/lantiq_xrx200.c -+++ b/drivers/net/ethernet/lantiq_xrx200.c -@@ -440,7 +440,6 @@ static int xrx200_probe(struct platform_ - struct resource *res; - struct xrx200_priv *priv; - struct net_device *net_dev; -- const u8 *mac; - int err; - - /* alloc the network device */ -@@ -484,10 +483,8 @@ static int xrx200_probe(struct platform_ - return PTR_ERR(priv->clk); - } - -- mac = of_get_mac_address(np); -- if (!IS_ERR(mac)) -- ether_addr_copy(net_dev->dev_addr, mac); -- else -+ err = of_get_mac_address(np, net_dev->dev_addr); -+ if (err) - eth_hw_addr_random(net_dev); - - /* bring up the dma engine and IP core */ ---- a/drivers/net/ethernet/marvell/mv643xx_eth.c -+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c -@@ -2700,7 +2700,6 @@ static int mv643xx_eth_shared_of_add_por - struct platform_device *ppdev; - struct mv643xx_eth_platform_data ppd; - struct resource res; -- const char *mac_addr; - int ret; - int dev_num = 0; - -@@ -2731,9 +2730,7 @@ static int mv643xx_eth_shared_of_add_por - return -EINVAL; - } - -- mac_addr = of_get_mac_address(pnp); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ppd.mac_addr, mac_addr); -+ of_get_mac_address(pnp, ppd.mac_addr); - - mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size); - mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr); ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -5062,7 +5062,6 @@ static int mvneta_probe(struct platform_ - struct net_device *dev; - struct phylink *phylink; - struct phy *comphy; -- const char *dt_mac_addr; - char hw_mac_addr[ETH_ALEN]; - phy_interface_t phy_mode; - const char *mac_from; -@@ -5158,10 +5157,9 @@ static int mvneta_probe(struct platform_ - goto err_free_ports; - } - -- dt_mac_addr = of_get_mac_address(dn); -- if (!IS_ERR(dt_mac_addr)) { -+ err = of_get_mac_address(dn, dev->dev_addr); -+ if (!err) { - mac_from = "device tree"; -- ether_addr_copy(dev->dev_addr, dt_mac_addr); - } else { - mvneta_get_mac_addr(pp, hw_mac_addr); - if (is_valid_ether_addr(hw_mac_addr)) { ---- a/drivers/net/ethernet/marvell/prestera/prestera_main.c -+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c -@@ -466,20 +466,17 @@ static int prestera_switch_set_base_mac_ - { - struct device_node *base_mac_np; - struct device_node *np; -- const char *base_mac; -+ int ret; - - np = of_find_compatible_node(NULL, NULL, "marvell,prestera"); - base_mac_np = of_parse_phandle(np, "base-mac-provider", 0); - -- base_mac = of_get_mac_address(base_mac_np); -- of_node_put(base_mac_np); -- if (!IS_ERR(base_mac)) -- ether_addr_copy(sw->base_mac, base_mac); -- -- if (!is_valid_ether_addr(sw->base_mac)) { -+ ret = of_get_mac_address(base_mac_np, sw->base_mac); -+ if (ret) { - eth_random_addr(sw->base_mac); - dev_info(prestera_dev(sw), "using random base mac address\n"); - } -+ of_node_put(base_mac_np); - - return prestera_hw_switch_mac_set(sw, sw->base_mac); - } ---- a/drivers/net/ethernet/marvell/pxa168_eth.c -+++ b/drivers/net/ethernet/marvell/pxa168_eth.c -@@ -1392,7 +1392,6 @@ static int pxa168_eth_probe(struct platf - struct resource *res; - struct clk *clk; - struct device_node *np; -- const unsigned char *mac_addr = NULL; - int err; - - printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n"); -@@ -1435,12 +1434,8 @@ static int pxa168_eth_probe(struct platf - - INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); - -- if (pdev->dev.of_node) -- mac_addr = of_get_mac_address(pdev->dev.of_node); -- -- if (!IS_ERR_OR_NULL(mac_addr)) { -- ether_addr_copy(dev->dev_addr, mac_addr); -- } else { -+ err = of_get_mac_address(pdev->dev.of_node, dev->dev_addr); -+ if (err) { - /* try reading the mac address, if set by the bootloader */ - pxa168_eth_get_mac_address(dev, dev->dev_addr); - if (!is_valid_ether_addr(dev->dev_addr)) { ---- a/drivers/net/ethernet/marvell/sky2.c -+++ b/drivers/net/ethernet/marvell/sky2.c -@@ -4725,7 +4725,7 @@ static struct net_device *sky2_init_netd - { - struct sky2_port *sky2; - struct net_device *dev = alloc_etherdev(sizeof(*sky2)); -- const void *iap; -+ int ret; - - if (!dev) - return NULL; -@@ -4795,10 +4795,8 @@ static struct net_device *sky2_init_netd - * 1) from device tree data - * 2) from internal registers set by bootloader - */ -- iap = of_get_mac_address(hw->pdev->dev.of_node); -- if (!IS_ERR(iap)) -- ether_addr_copy(dev->dev_addr, iap); -- else -+ ret = of_get_mac_address(hw->pdev->dev.of_node, dev->dev_addr); -+ if (ret) - memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, - ETH_ALEN); - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2580,14 +2580,11 @@ static int __init mtk_init(struct net_de - { - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; -- const char *mac_addr; -+ int ret; - -- mac_addr = of_get_mac_address(mac->of_node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(dev->dev_addr, mac_addr); -- -- /* If the mac address is invalid, use random mac address */ -- if (!is_valid_ether_addr(dev->dev_addr)) { -+ ret = of_get_mac_address(mac->of_node, dev->dev_addr); -+ if (ret) { -+ /* If the mac address is invalid, use random mac address */ - eth_hw_addr_random(dev); - dev_err(eth->dev, "generated random MAC address %pM\n", - dev->dev_addr); ---- a/drivers/net/ethernet/micrel/ks8851_common.c -+++ b/drivers/net/ethernet/micrel/ks8851_common.c -@@ -194,11 +194,10 @@ static void ks8851_read_mac_addr(struct - static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np) - { - struct net_device *dev = ks->netdev; -- const u8 *mac_addr; -+ int ret; - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) { -- ether_addr_copy(dev->dev_addr, mac_addr); -+ ret = of_get_mac_address(np, dev->dev_addr); -+ if (!ret) { - ks8851_write_mac_addr(dev); - return; - } ---- a/drivers/net/ethernet/microchip/lan743x_main.c -+++ b/drivers/net/ethernet/microchip/lan743x_main.c -@@ -2831,7 +2831,6 @@ static int lan743x_pcidev_probe(struct p - { - struct lan743x_adapter *adapter = NULL; - struct net_device *netdev = NULL; -- const void *mac_addr; - int ret = -ENODEV; - - netdev = devm_alloc_etherdev(&pdev->dev, -@@ -2848,9 +2847,7 @@ static int lan743x_pcidev_probe(struct p - NETIF_MSG_IFDOWN | NETIF_MSG_TX_QUEUED; - netdev->max_mtu = LAN743X_MAX_FRAME_SIZE; - -- mac_addr = of_get_mac_address(pdev->dev.of_node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(adapter->mac_address, mac_addr); -+ of_get_mac_address(pdev->dev.of_node, adapter->mac_address); - - ret = lan743x_pci_init(adapter, pdev); - if (ret) ---- a/drivers/net/ethernet/nxp/lpc_eth.c -+++ b/drivers/net/ethernet/nxp/lpc_eth.c -@@ -1347,9 +1347,7 @@ static int lpc_eth_drv_probe(struct plat - __lpc_get_mac(pldat, ndev->dev_addr); - - if (!is_valid_ether_addr(ndev->dev_addr)) { -- const char *macaddr = of_get_mac_address(np); -- if (!IS_ERR(macaddr)) -- ether_addr_copy(ndev->dev_addr, macaddr); -+ of_get_mac_address(np, ndev->dev_addr); - } - if (!is_valid_ether_addr(ndev->dev_addr)) - eth_hw_addr_random(ndev); ---- a/drivers/net/ethernet/qualcomm/qca_spi.c -+++ b/drivers/net/ethernet/qualcomm/qca_spi.c -@@ -885,7 +885,7 @@ qca_spi_probe(struct spi_device *spi) - struct net_device *qcaspi_devs = NULL; - u8 legacy_mode = 0; - u16 signature; -- const char *mac; -+ int ret; - - if (!spi->dev.of_node) { - dev_err(&spi->dev, "Missing device tree\n"); -@@ -962,12 +962,8 @@ qca_spi_probe(struct spi_device *spi) - - spi_set_drvdata(spi, qcaspi_devs); - -- mac = of_get_mac_address(spi->dev.of_node); -- -- if (!IS_ERR(mac)) -- ether_addr_copy(qca->net_dev->dev_addr, mac); -- -- if (!is_valid_ether_addr(qca->net_dev->dev_addr)) { -+ ret = of_get_mac_address(spi->dev.of_node, qca->net_dev->dev_addr); -+ if (ret) { - eth_hw_addr_random(qca->net_dev); - dev_info(&spi->dev, "Using random MAC address: %pM\n", - qca->net_dev->dev_addr); ---- a/drivers/net/ethernet/qualcomm/qca_uart.c -+++ b/drivers/net/ethernet/qualcomm/qca_uart.c -@@ -323,7 +323,6 @@ static int qca_uart_probe(struct serdev_ - { - struct net_device *qcauart_dev = alloc_etherdev(sizeof(struct qcauart)); - struct qcauart *qca; -- const char *mac; - u32 speed = 115200; - int ret; - -@@ -348,12 +347,8 @@ static int qca_uart_probe(struct serdev_ - - of_property_read_u32(serdev->dev.of_node, "current-speed", &speed); - -- mac = of_get_mac_address(serdev->dev.of_node); -- -- if (!IS_ERR(mac)) -- ether_addr_copy(qca->net_dev->dev_addr, mac); -- -- if (!is_valid_ether_addr(qca->net_dev->dev_addr)) { -+ ret = of_get_mac_address(serdev->dev.of_node, qca->net_dev->dev_addr); -+ if (ret) { - eth_hw_addr_random(qca->net_dev); - dev_info(&serdev->dev, "Using random MAC address: %pM\n", - qca->net_dev->dev_addr); ---- a/drivers/net/ethernet/renesas/ravb_main.c -+++ b/drivers/net/ethernet/renesas/ravb_main.c -@@ -109,11 +109,13 @@ static void ravb_set_buffer_align(struct - * Ethernet AVB device doesn't have ROM for MAC address. - * This function gets the MAC address that was used by a bootloader. - */ --static void ravb_read_mac_address(struct net_device *ndev, const u8 *mac) -+static void ravb_read_mac_address(struct device_node *np, -+ struct net_device *ndev) - { -- if (!IS_ERR(mac)) { -- ether_addr_copy(ndev->dev_addr, mac); -- } else { -+ int ret; -+ -+ ret = of_get_mac_address(np, ndev->dev_addr); -+ if (ret) { - u32 mahr = ravb_read(ndev, MAHR); - u32 malr = ravb_read(ndev, MALR); - -@@ -2189,7 +2191,7 @@ static int ravb_probe(struct platform_de - priv->msg_enable = RAVB_DEF_MSG_ENABLE; - - /* Read and set MAC address */ -- ravb_read_mac_address(ndev, of_get_mac_address(np)); -+ ravb_read_mac_address(np, ndev); - if (!is_valid_ether_addr(ndev->dev_addr)) { - dev_warn(&pdev->dev, - "no valid MAC address supplied, using a random one\n"); ---- a/drivers/net/ethernet/renesas/sh_eth.c -+++ b/drivers/net/ethernet/renesas/sh_eth.c -@@ -3145,7 +3145,6 @@ static struct sh_eth_plat_data *sh_eth_p - struct device_node *np = dev->of_node; - struct sh_eth_plat_data *pdata; - phy_interface_t interface; -- const char *mac_addr; - int ret; - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); -@@ -3157,9 +3156,7 @@ static struct sh_eth_plat_data *sh_eth_p - return NULL; - pdata->phy_interface = interface; - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(pdata->mac_addr, mac_addr); -+ of_get_mac_address(np, pdata->mac_addr); - - pdata->no_ether_link = - of_property_read_bool(np, "renesas,no-ether-link"); ---- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c -+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c -@@ -25,8 +25,7 @@ - - #ifdef CONFIG_OF - static int sxgbe_probe_config_dt(struct platform_device *pdev, -- struct sxgbe_plat_data *plat, -- const char **mac) -+ struct sxgbe_plat_data *plat) - { - struct device_node *np = pdev->dev.of_node; - struct sxgbe_dma_cfg *dma_cfg; -@@ -35,7 +34,6 @@ static int sxgbe_probe_config_dt(struct - if (!np) - return -ENODEV; - -- *mac = of_get_mac_address(np); - err = of_get_phy_mode(np, &plat->interface); - if (err && err != -ENODEV) - return err; -@@ -63,8 +61,7 @@ static int sxgbe_probe_config_dt(struct - } - #else - static int sxgbe_probe_config_dt(struct platform_device *pdev, -- struct sxgbe_plat_data *plat, -- const char **mac) -+ struct sxgbe_plat_data *plat) - { - return -ENOSYS; - } -@@ -85,7 +82,6 @@ static int sxgbe_platform_probe(struct p - void __iomem *addr; - struct sxgbe_priv_data *priv = NULL; - struct sxgbe_plat_data *plat_dat = NULL; -- const char *mac = NULL; - struct net_device *ndev = platform_get_drvdata(pdev); - struct device_node *node = dev->of_node; - -@@ -101,7 +97,7 @@ static int sxgbe_platform_probe(struct p - if (!plat_dat) - return -ENOMEM; - -- ret = sxgbe_probe_config_dt(pdev, plat_dat, &mac); -+ ret = sxgbe_probe_config_dt(pdev, plat_dat); - if (ret) { - pr_err("%s: main dt probe failed\n", __func__); - return ret; -@@ -122,8 +118,7 @@ static int sxgbe_platform_probe(struct p - } - - /* Get MAC address if available (DT) */ -- if (!IS_ERR_OR_NULL(mac)) -- ether_addr_copy(priv->dev->dev_addr, mac); -+ of_get_mac_address(node, priv->dev->dev_addr); - - /* Get the TX/RX IRQ numbers */ - for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) { ---- a/drivers/net/ethernet/socionext/sni_ave.c -+++ b/drivers/net/ethernet/socionext/sni_ave.c -@@ -1559,7 +1559,6 @@ static int ave_probe(struct platform_dev - struct ave_private *priv; - struct net_device *ndev; - struct device_node *np; -- const void *mac_addr; - void __iomem *base; - const char *name; - int i, irq, ret; -@@ -1600,12 +1599,9 @@ static int ave_probe(struct platform_dev - - ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN); - -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- -- /* if the mac address is invalid, use random mac address */ -- if (!is_valid_ether_addr(ndev->dev_addr)) { -+ ret = of_get_mac_address(np, ndev->dev_addr); -+ if (ret) { -+ /* if the mac address is invalid, use random mac address */ - eth_hw_addr_random(ndev); - dev_warn(dev, "Using random MAC address: %pM\n", - ndev->dev_addr); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c -@@ -115,7 +115,7 @@ static int anarion_dwmac_probe(struct pl - if (IS_ERR(gmac)) - return PTR_ERR(gmac); - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c -@@ -444,7 +444,7 @@ static int dwc_eth_dwmac_probe(struct pl - if (IS_ERR(stmmac_res.addr)) - return PTR_ERR(stmmac_res.addr); - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c -@@ -27,7 +27,7 @@ static int dwmac_generic_probe(struct pl - return ret; - - if (pdev->dev.of_node) { -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) { - dev_err(&pdev->dev, "dt configuration failed\n"); - return PTR_ERR(plat_dat); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c -@@ -226,7 +226,7 @@ static int imx_dwmac_probe(struct platfo - if (!dwmac) - return -ENOMEM; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c -@@ -88,7 +88,7 @@ static int intel_eth_plat_probe(struct p - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) { - dev_err(&pdev->dev, "dt configuration failed\n"); - return PTR_ERR(plat_dat); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c -@@ -255,7 +255,7 @@ static int ipq806x_gmac_probe(struct pla - if (val) - return val; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c -@@ -37,7 +37,7 @@ static int lpc18xx_dwmac_probe(struct pl - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c -@@ -407,7 +407,7 @@ static int mediatek_dwmac_probe(struct p - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c -@@ -52,7 +52,7 @@ static int meson6_dwmac_probe(struct pla - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c -@@ -372,7 +372,7 @@ static int meson8b_dwmac_probe(struct pl - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c -@@ -118,7 +118,7 @@ static int oxnas_dwmac_probe(struct plat - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c -@@ -461,7 +461,7 @@ static int qcom_ethqos_probe(struct plat - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) { - dev_err(&pdev->dev, "dt configuration failed\n"); - return PTR_ERR(plat_dat); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -1392,7 +1392,7 @@ static int rk_gmac_probe(struct platform - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -398,7 +398,7 @@ static int socfpga_dwmac_probe(struct pl - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c -@@ -325,7 +325,7 @@ static int sti_dwmac_probe(struct platfo - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c -@@ -371,7 +371,7 @@ static int stm32_dwmac_probe(struct plat - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -1202,7 +1202,7 @@ static int sun8i_dwmac_probe(struct plat - if (ret) - return -EINVAL; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c -@@ -108,7 +108,7 @@ static int sun7i_gmac_probe(struct platf - if (ret) - return ret; - -- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -25,7 +25,7 @@ - - struct stmmac_resources { - void __iomem *addr; -- const char *mac; -+ u8 mac[ETH_ALEN]; - int wol_irq; - int lpi_irq; - int irq; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -4988,7 +4988,7 @@ int stmmac_dvr_probe(struct device *devi - priv->wol_irq = res->wol_irq; - priv->lpi_irq = res->lpi_irq; - -- if (!IS_ERR_OR_NULL(res->mac)) -+ if (!is_zero_ether_addr(res->mac)) - memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); - - dev_set_drvdata(device, priv->dev); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -395,7 +395,7 @@ static int stmmac_of_get_mac_mode(struct - * set some private fields that will be used by the main at runtime. - */ - struct plat_stmmacenet_data * --stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) -+stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) - { - struct device_node *np = pdev->dev.of_node; - struct plat_stmmacenet_data *plat; -@@ -407,12 +407,12 @@ stmmac_probe_config_dt(struct platform_d - if (!plat) - return ERR_PTR(-ENOMEM); - -- *mac = of_get_mac_address(np); -- if (IS_ERR(*mac)) { -- if (PTR_ERR(*mac) == -EPROBE_DEFER) -- return ERR_CAST(*mac); -+ rc = of_get_mac_address(np, mac); -+ if (rc) { -+ if (rc == -EPROBE_DEFER) -+ return ERR_PTR(rc); - -- *mac = NULL; -+ eth_zero_addr(mac); - } - - phy_mode = device_get_phy_mode(&pdev->dev); -@@ -644,7 +644,7 @@ void stmmac_remove_config_dt(struct plat - } - #else - struct plat_stmmacenet_data * --stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) -+stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) - { - return ERR_PTR(-EINVAL); - } ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h -@@ -12,7 +12,7 @@ - #include "stmmac.h" - - struct plat_stmmacenet_data * --stmmac_probe_config_dt(struct platform_device *pdev, const char **mac); -+stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); - void stmmac_remove_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat); - ---- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c -+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c -@@ -1741,7 +1741,6 @@ static int am65_cpsw_nuss_init_slave_por - - for_each_child_of_node(node, port_np) { - struct am65_cpsw_port *port; -- const void *mac_addr; - u32 port_id; - - /* it is not a slave port node, continue */ -@@ -1820,15 +1819,15 @@ static int am65_cpsw_nuss_init_slave_por - return ret; - } - -- mac_addr = of_get_mac_address(port_np); -- if (!IS_ERR(mac_addr)) { -- ether_addr_copy(port->slave.mac_addr, mac_addr); -- } else if (am65_cpsw_am654_get_efuse_macid(port_np, -- port->port_id, -- port->slave.mac_addr) || -- !is_valid_ether_addr(port->slave.mac_addr)) { -- random_ether_addr(port->slave.mac_addr); -- dev_err(dev, "Use random MAC address\n"); -+ ret = of_get_mac_address(port_np, port->slave.mac_addr); -+ if (ret) { -+ am65_cpsw_am654_get_efuse_macid(port_np, -+ port->port_id, -+ port->slave.mac_addr); -+ if (!is_valid_ether_addr(port->slave.mac_addr)) { -+ random_ether_addr(port->slave.mac_addr); -+ dev_err(dev, "Use random MAC address\n"); -+ } - } - } - of_node_put(node); ---- a/drivers/net/ethernet/ti/cpsw.c -+++ b/drivers/net/ethernet/ti/cpsw.c -@@ -1306,7 +1306,6 @@ static int cpsw_probe_dt(struct cpsw_pla - - for_each_available_child_of_node(node, slave_node) { - struct cpsw_slave_data *slave_data = data->slave_data + i; -- const void *mac_addr = NULL; - int lenp; - const __be32 *parp; - -@@ -1378,10 +1377,8 @@ static int cpsw_probe_dt(struct cpsw_pla - } - - no_phy_slave: -- mac_addr = of_get_mac_address(slave_node); -- if (!IS_ERR(mac_addr)) { -- ether_addr_copy(slave_data->mac_addr, mac_addr); -- } else { -+ ret = of_get_mac_address(slave_node, slave_data->mac_addr); -+ if (ret) { - ret = ti_cm_get_macid(&pdev->dev, i, - slave_data->mac_addr); - if (ret) ---- a/drivers/net/ethernet/ti/cpsw_new.c -+++ b/drivers/net/ethernet/ti/cpsw_new.c -@@ -1267,7 +1267,6 @@ static int cpsw_probe_dt(struct cpsw_com - - for_each_child_of_node(tmp_node, port_np) { - struct cpsw_slave_data *slave_data; -- const void *mac_addr; - u32 port_id; - - ret = of_property_read_u32(port_np, "reg", &port_id); -@@ -1326,10 +1325,8 @@ static int cpsw_probe_dt(struct cpsw_com - goto err_node_put; - } - -- mac_addr = of_get_mac_address(port_np); -- if (!IS_ERR(mac_addr)) { -- ether_addr_copy(slave_data->mac_addr, mac_addr); -- } else { -+ ret = of_get_mac_address(port_np, slave_data->mac_addr); -+ if (ret) { - ret = ti_cm_get_macid(dev, port_id - 1, - slave_data->mac_addr); - if (ret) ---- a/drivers/net/ethernet/ti/davinci_emac.c -+++ b/drivers/net/ethernet/ti/davinci_emac.c -@@ -1699,7 +1699,6 @@ davinci_emac_of_get_pdata(struct platfor - const struct of_device_id *match; - const struct emac_platform_data *auxdata; - struct emac_platform_data *pdata = NULL; -- const u8 *mac_addr; - - if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) - return dev_get_platdata(&pdev->dev); -@@ -1711,11 +1710,8 @@ davinci_emac_of_get_pdata(struct platfor - np = pdev->dev.of_node; - pdata->version = EMAC_VERSION_2; - -- if (!is_valid_ether_addr(pdata->mac_addr)) { -- mac_addr = of_get_mac_address(np); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(pdata->mac_addr, mac_addr); -- } -+ if (!is_valid_ether_addr(pdata->mac_addr)) -+ of_get_mac_address(np, pdata->mac_addr); - - of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", - &pdata->ctrl_reg_offset); ---- a/drivers/net/ethernet/ti/netcp_core.c -+++ b/drivers/net/ethernet/ti/netcp_core.c -@@ -1966,7 +1966,6 @@ static int netcp_create_interface(struct - struct resource res; - void __iomem *efuse = NULL; - u32 efuse_mac = 0; -- const void *mac_addr; - u8 efuse_mac_addr[6]; - u32 temp[2]; - int ret = 0; -@@ -2036,10 +2035,8 @@ static int netcp_create_interface(struct - devm_iounmap(dev, efuse); - devm_release_mem_region(dev, res.start, size); - } else { -- mac_addr = of_get_mac_address(node_interface); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(ndev->dev_addr, mac_addr); -- else -+ ret = of_get_mac_address(node_interface, ndev->dev_addr); -+ if (ret) - eth_random_addr(ndev->dev_addr); - } - ---- a/drivers/net/ethernet/wiznet/w5100-spi.c -+++ b/drivers/net/ethernet/wiznet/w5100-spi.c -@@ -423,8 +423,14 @@ static int w5100_spi_probe(struct spi_de - const struct of_device_id *of_id; - const struct w5100_ops *ops; - kernel_ulong_t driver_data; -+ const void *mac = NULL; -+ u8 tmpmac[ETH_ALEN]; - int priv_size; -- const void *mac = of_get_mac_address(spi->dev.of_node); -+ int ret; -+ -+ ret = of_get_mac_address(spi->dev.of_node, tmpmac); -+ if (!ret) -+ mac = tmpmac; - - if (spi->dev.of_node) { - of_id = of_match_device(w5100_of_match, &spi->dev); ---- a/drivers/net/ethernet/wiznet/w5100.c -+++ b/drivers/net/ethernet/wiznet/w5100.c -@@ -1159,7 +1159,7 @@ int w5100_probe(struct device *dev, cons - INIT_WORK(&priv->setrx_work, w5100_setrx_work); - INIT_WORK(&priv->restart_work, w5100_restart_work); - -- if (!IS_ERR_OR_NULL(mac_addr)) -+ if (mac_addr) - memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); - else - eth_hw_addr_random(ndev); ---- a/drivers/net/ethernet/xilinx/ll_temac_main.c -+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c -@@ -438,7 +438,7 @@ static void temac_do_set_mac_address(str - - static int temac_init_mac_address(struct net_device *ndev, const void *address) - { -- ether_addr_copy(ndev->dev_addr, address); -+ memcpy(ndev->dev_addr, address, ETH_ALEN); - if (!is_valid_ether_addr(ndev->dev_addr)) - eth_hw_addr_random(ndev); - temac_do_set_mac_address(ndev); -@@ -1370,7 +1370,7 @@ static int temac_probe(struct platform_d - struct device_node *temac_np = dev_of_node(&pdev->dev), *dma_np; - struct temac_local *lp; - struct net_device *ndev; -- const void *addr; -+ u8 addr[ETH_ALEN]; - __be32 *p; - bool little_endian; - int rc = 0; -@@ -1563,8 +1563,8 @@ static int temac_probe(struct platform_d - - if (temac_np) { - /* Retrieve the MAC address */ -- addr = of_get_mac_address(temac_np); -- if (IS_ERR(addr)) { -+ rc = of_get_mac_address(temac_np, addr); -+ if (rc) { - dev_err(&pdev->dev, "could not find MAC address\n"); - return -ENODEV; - } ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1831,8 +1831,8 @@ static int axienet_probe(struct platform - struct device_node *np; - struct axienet_local *lp; - struct net_device *ndev; -- const void *mac_addr; - struct resource *ethres; -+ u8 mac_addr[ETH_ALEN]; - int addr_width = 32; - u32 value; - -@@ -2032,13 +2032,14 @@ static int axienet_probe(struct platform - dev_info(&pdev->dev, "Ethernet core IRQ not defined\n"); - - /* Retrieve the MAC address */ -- mac_addr = of_get_mac_address(pdev->dev.of_node); -- if (IS_ERR(mac_addr)) { -- dev_warn(&pdev->dev, "could not find MAC address property: %ld\n", -- PTR_ERR(mac_addr)); -- mac_addr = NULL; -+ ret = of_get_mac_address(pdev->dev.of_node, mac_addr); -+ if (!ret) { -+ axienet_set_mac_address(ndev, mac_addr); -+ } else { -+ dev_warn(&pdev->dev, "could not find MAC address property: %d\n", -+ ret); -+ axienet_set_mac_address(ndev, NULL); - } -- axienet_set_mac_address(ndev, mac_addr); - - lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; - lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; ---- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c -+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c -@@ -1113,7 +1113,6 @@ static int xemaclite_of_probe(struct pla - struct net_device *ndev = NULL; - struct net_local *lp = NULL; - struct device *dev = &ofdev->dev; -- const void *mac_address; - - int rc = 0; - -@@ -1155,12 +1154,9 @@ static int xemaclite_of_probe(struct pla - lp->next_rx_buf_to_use = 0x0; - lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong"); - lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong"); -- mac_address = of_get_mac_address(ofdev->dev.of_node); - -- if (!IS_ERR(mac_address)) { -- /* Set the MAC address. */ -- ether_addr_copy(ndev->dev_addr, mac_address); -- } else { -+ rc = of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr); -+ if (rc) { - dev_warn(dev, "No MAC address found, using random\n"); - eth_hw_addr_random(ndev); - } ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -618,7 +618,6 @@ static int ath9k_of_init(struct ath_soft - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - enum ath_bus_type bus_type = common->bus_ops->ath_bus_type; -- const char *mac; - char eeprom_name[100]; - int ret; - -@@ -641,9 +640,7 @@ static int ath9k_of_init(struct ath_soft - ah->ah_flags |= AH_NO_EEP_SWAP; - } - -- mac = of_get_mac_address(np); -- if (!IS_ERR(mac)) -- ether_addr_copy(common->macaddr, mac); -+ of_get_mac_address(np, common->macaddr); - - return 0; - } ---- a/drivers/net/wireless/mediatek/mt76/eeprom.c -+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c -@@ -90,15 +90,9 @@ out_put_node: - void - mt76_eeprom_override(struct mt76_dev *dev) - { --#ifdef CONFIG_OF - struct device_node *np = dev->dev->of_node; -- const u8 *mac = NULL; - -- if (np) -- mac = of_get_mac_address(np); -- if (!IS_ERR_OR_NULL(mac)) -- ether_addr_copy(dev->macaddr, mac); --#endif -+ of_get_mac_address(np, dev->macaddr); - - if (!is_valid_ether_addr(dev->macaddr)) { - eth_random_addr(dev->macaddr); ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -990,11 +990,7 @@ static void rt2x00lib_rate(struct ieee80 - - void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) - { -- const char *mac_addr; -- -- mac_addr = of_get_mac_address(rt2x00dev->dev->of_node); -- if (!IS_ERR(mac_addr)) -- ether_addr_copy(eeprom_mac_addr, mac_addr); -+ of_get_mac_address(rt2x00dev->dev->of_node, eeprom_mac_addr); - - if (!is_valid_ether_addr(eeprom_mac_addr)) { - eth_random_addr(eeprom_mac_addr); ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c -@@ -45,37 +45,29 @@ int of_get_phy_mode(struct device_node * - } - EXPORT_SYMBOL_GPL(of_get_phy_mode); - --static const void *of_get_mac_addr(struct device_node *np, const char *name) -+static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) - { - struct property *pp = of_find_property(np, name, NULL); - -- if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) -- return pp->value; -- return NULL; -+ if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) { -+ memcpy(addr, pp->value, ETH_ALEN); -+ return 0; -+ } -+ return -ENODEV; - } - --static const void *of_get_mac_addr_nvmem(struct device_node *np) -+static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) - { -- int ret; -- const void *mac; -- u8 nvmem_mac[ETH_ALEN]; - struct platform_device *pdev = of_find_device_by_node(np); -+ int ret; - - if (!pdev) -- return ERR_PTR(-ENODEV); -+ return -ENODEV; - -- ret = nvmem_get_mac_address(&pdev->dev, &nvmem_mac); -- if (ret) { -- put_device(&pdev->dev); -- return ERR_PTR(ret); -- } -- -- mac = devm_kmemdup(&pdev->dev, nvmem_mac, ETH_ALEN, GFP_KERNEL); -+ ret = nvmem_get_mac_address(&pdev->dev, addr); - put_device(&pdev->dev); -- if (!mac) -- return ERR_PTR(-ENOMEM); - -- return mac; -+ return ret; - } - - /** -@@ -98,24 +90,27 @@ static const void *of_get_mac_addr_nvmem - * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists - * but is all zeros. - * -- * Return: Will be a valid pointer on success and ERR_PTR in case of error. -+ * Return: 0 on success and errno in case of error. - */ --const void *of_get_mac_address(struct device_node *np) -+int of_get_mac_address(struct device_node *np, u8 *addr) - { -- const void *addr; -- -- addr = of_get_mac_addr(np, "mac-address"); -- if (addr) -- return addr; -+ int ret; - -- addr = of_get_mac_addr(np, "local-mac-address"); -- if (addr) -- return addr; -+ if (!np) -+ return -ENODEV; - -- addr = of_get_mac_addr(np, "address"); -- if (addr) -- return addr; -+ ret = of_get_mac_addr(np, "mac-address", addr); -+ if (!ret) -+ return 0; -+ -+ ret = of_get_mac_addr(np, "local-mac-address", addr); -+ if (!ret) -+ return 0; -+ -+ ret = of_get_mac_addr(np, "address", addr); -+ if (!ret) -+ return 0; - -- return of_get_mac_addr_nvmem(np); -+ return of_get_mac_addr_nvmem(np, addr); - } - EXPORT_SYMBOL(of_get_mac_address); ---- a/drivers/staging/octeon/ethernet.c -+++ b/drivers/staging/octeon/ethernet.c -@@ -407,14 +407,10 @@ static int cvm_oct_common_set_mac_addres - int cvm_oct_common_init(struct net_device *dev) - { - struct octeon_ethernet *priv = netdev_priv(dev); -- const u8 *mac = NULL; -+ int ret; - -- if (priv->of_node) -- mac = of_get_mac_address(priv->of_node); -- -- if (!IS_ERR_OR_NULL(mac)) -- ether_addr_copy(dev->dev_addr, mac); -- else -+ ret = of_get_mac_address(priv->of_node, dev->dev_addr); -+ if (ret) - eth_hw_addr_random(dev); - - /* ---- a/drivers/staging/wfx/main.c -+++ b/drivers/staging/wfx/main.c -@@ -334,7 +334,6 @@ int wfx_probe(struct wfx_dev *wdev) - { - int i; - int err; -- const void *macaddr; - struct gpio_desc *gpio_saved; - - // During first part of boot, gpio_wakeup cannot yet been used. So -@@ -423,9 +422,9 @@ int wfx_probe(struct wfx_dev *wdev) - - for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { - eth_zero_addr(wdev->addresses[i].addr); -- macaddr = of_get_mac_address(wdev->dev->of_node); -- if (!IS_ERR_OR_NULL(macaddr)) { -- ether_addr_copy(wdev->addresses[i].addr, macaddr); -+ err = of_get_mac_address(wdev->dev->of_node, -+ wdev->addresses[i].addr); -+ if (!err) { - wdev->addresses[i].addr[ETH_ALEN - 1] += i; - } else { - ether_addr_copy(wdev->addresses[i].addr, ---- a/include/linux/of_net.h -+++ b/include/linux/of_net.h -@@ -13,7 +13,7 @@ - - struct net_device; - extern int of_get_phy_mode(struct device_node *np, phy_interface_t *interface); --extern const void *of_get_mac_address(struct device_node *np); -+extern int of_get_mac_address(struct device_node *np, u8 *mac); - extern struct net_device *of_find_net_device_by_node(struct device_node *np); - #else - static inline int of_get_phy_mode(struct device_node *np, -@@ -22,9 +22,9 @@ static inline int of_get_phy_mode(struct - return -ENODEV; - } - --static inline const void *of_get_mac_address(struct device_node *np) -+static inline int of_get_mac_address(struct device_node *np, u8 *mac) - { -- return ERR_PTR(-ENODEV); -+ return -ENODEV; - } - - static inline struct net_device *of_find_net_device_by_node(struct device_node *np) ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -208,7 +208,7 @@ struct dsa_port { - unsigned int index; - const char *name; - struct dsa_port *cpu_dp; -- const char *mac; -+ u8 mac[ETH_ALEN]; - struct device_node *dn; - unsigned int ageing_time; - bool vlan_filtering; ---- a/net/dsa/dsa2.c -+++ b/net/dsa/dsa2.c -@@ -288,7 +288,7 @@ static int dsa_port_setup(struct dsa_por - - break; - case DSA_PORT_TYPE_USER: -- dp->mac = of_get_mac_address(dp->dn); -+ of_get_mac_address(dp->dn, dp->mac); - err = dsa_slave_create(dp); - if (err) - break; ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -1855,7 +1855,7 @@ int dsa_slave_create(struct dsa_port *po - slave_dev->hw_features |= NETIF_F_HW_TC; - slave_dev->features |= NETIF_F_LLTX; - slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; -- if (!IS_ERR_OR_NULL(port->mac)) -+ if (!is_zero_ether_addr(port->mac)) - ether_addr_copy(slave_dev->dev_addr, port->mac); - else - eth_hw_addr_inherit(slave_dev, master); ---- a/net/ethernet/eth.c -+++ b/net/ethernet/eth.c -@@ -506,13 +506,14 @@ unsigned char * __weak arch_get_platform - - int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr) - { -- const unsigned char *addr = NULL; -+ unsigned char *addr; -+ int ret; - -- if (dev->of_node) -- addr = of_get_mac_address(dev->of_node); -- if (IS_ERR_OR_NULL(addr)) -- addr = arch_get_platform_mac_address(); -+ ret = of_get_mac_address(dev->of_node, mac_addr); -+ if (!ret) -+ return 0; - -+ addr = arch_get_platform_mac_address(); - if (!addr) - return -ENODEV; - diff --git a/target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch b/target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch deleted file mode 100644 index 245c5f3bd6..0000000000 --- a/target/linux/generic/backport-5.15/732-net-next-2-of-net-fix-of_get_mac_addr_nvmem-for-non-platform-devices.patch +++ /dev/null @@ -1,77 +0,0 @@ -From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001 -From: Michael Walle -Date: Mon, 12 Apr 2021 19:47:18 +0200 -Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices - -of_get_mac_address() already supports fetching the MAC address by an -nvmem provider. But until now, it was just working for platform devices. -Esp. it was not working for DSA ports and PCI devices. It gets more -common that PCI devices have a device tree binding since SoCs contain -integrated root complexes. - -Use the nvmem of_* binding to fetch the nvmem cells by a struct -device_node. We still have to try to read the cell by device first -because there might be a nvmem_cell_lookup associated with that device. - -Signed-off-by: Michael Walle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++----- - 1 file changed, 30 insertions(+), 5 deletions(-) - ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - /** - * of_get_phy_mode - Get phy mode for given device_node -@@ -59,15 +60,39 @@ static int of_get_mac_addr(struct device - static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) - { - struct platform_device *pdev = of_find_device_by_node(np); -+ struct nvmem_cell *cell; -+ const void *mac; -+ size_t len; - int ret; - -- if (!pdev) -- return -ENODEV; -+ /* Try lookup by device first, there might be a nvmem_cell_lookup -+ * associated with a given device. -+ */ -+ if (pdev) { -+ ret = nvmem_get_mac_address(&pdev->dev, addr); -+ put_device(&pdev->dev); -+ return ret; -+ } -+ -+ cell = of_nvmem_cell_get(np, "mac-address"); -+ if (IS_ERR(cell)) -+ return PTR_ERR(cell); -+ -+ mac = nvmem_cell_read(cell, &len); -+ nvmem_cell_put(cell); -+ -+ if (IS_ERR(mac)) -+ return PTR_ERR(mac); -+ -+ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) { -+ kfree(mac); -+ return -EINVAL; -+ } - -- ret = nvmem_get_mac_address(&pdev->dev, addr); -- put_device(&pdev->dev); -+ memcpy(addr, mac, ETH_ALEN); -+ kfree(mac); - -- return ret; -+ return 0; - } - - /** diff --git a/target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch b/target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch deleted file mode 100644 index 6e7f20634f..0000000000 --- a/target/linux/generic/backport-5.15/733-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 029497e66bdc762e001880e4c85a91f35a54b1e2 Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Sun, 19 Sep 2021 13:57:25 +0200 -Subject: [PATCH] net: bgmac-bcma: handle deferred probe error due to - mac-address -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Due to the inclusion of nvmem handling into the mac-address getter -function of_get_mac_address() by -commit d01f449c008a ("of_net: add NVMEM support to of_get_mac_address") -it is now possible to get a -EPROBE_DEFER return code. Which did cause -bgmac to assign a random ethernet address. - -This exact issue happened on my Meraki MR32. The nvmem provider is -an EEPROM (at24c64) which gets instantiated once the module -driver is loaded... This happens once the filesystem becomes available. - -With this patch, bgmac_probe() will propagate the -EPROBE_DEFER error. -Then the driver subsystem will reschedule the probe at a later time. - -Cc: Petr Štetiar -Cc: Michael Walle -Fixes: d01f449c008a ("of_net: add NVMEM support to of_get_mac_address") -Signed-off-by: Christian Lamparter -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/broadcom/bgmac-bcma.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/ethernet/broadcom/bgmac-bcma.c -+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c -@@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_devic - bcma_set_drvdata(core, bgmac); - - err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); -+ if (err == -EPROBE_DEFER) -+ return err; - - /* If no MAC address assigned via device tree, check SPROM */ - if (err) { diff --git a/target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch b/target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch deleted file mode 100644 index bde62f3b1b..0000000000 --- a/target/linux/generic/backport-5.15/733-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 763716a55cb1f480ffe1a9702e6b5d9ea1a80a24 Mon Sep 17 00:00:00 2001 -From: Matthew Hagan -Date: Sat, 25 Sep 2021 11:36:27 +0000 -Subject: [PATCH] net: bgmac-platform: handle mac-address deferral - -This patch is a replication of Christian Lamparter's "net: bgmac-bcma: -handle deferred probe error due to mac-address" patch for the -bgmac-platform driver [1]. - -As is the case with the bgmac-bcma driver, this change is to cover the -scenario where the MAC address cannot yet be discovered due to reliance -on an nvmem provider which is yet to be instantiated, resulting in a -random address being assigned that has to be manually overridden. - -[1] https://lore.kernel.org/netdev/20210919115725.29064-1-chunkeey@gmail.com - -Signed-off-by: Matthew Hagan -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/broadcom/bgmac-platform.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/broadcom/bgmac-platform.c -+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c -@@ -193,6 +193,9 @@ static int bgmac_probe(struct platform_d - bgmac->dma_dev = &pdev->dev; - - ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); -+ if (ret == -EPROBE_DEFER) -+ return ret; -+ - if (ret) - dev_warn(&pdev->dev, - "MAC address not present in device tree\n"); diff --git a/target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch b/target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch deleted file mode 100644 index b8e6d9b613..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-01-net-dsa-qca8k-change-simple-print-to-dev-variant.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 5d9e068402dcf7354cc8ee66c2152845306d2ccb Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:51 +0200 -Subject: [PATCH] net: dsa: qca8k: change simple print to dev variant - -Change pr_err and pr_warn to dev variant. - -Signed-off-by: Ansuel Smith -Reviewed-by: Florian Fainelli -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -701,7 +701,7 @@ qca8k_setup(struct dsa_switch *ds) - - /* Make sure that port 0 is the cpu port */ - if (!dsa_is_cpu_port(ds, 0)) { -- pr_err("port 0 is not the CPU port\n"); -+ dev_err(priv->dev, "port 0 is not the CPU port"); - return -EINVAL; - } - -@@ -711,7 +711,7 @@ qca8k_setup(struct dsa_switch *ds) - priv->regmap = devm_regmap_init(ds->dev, NULL, priv, - &qca8k_regmap_config); - if (IS_ERR(priv->regmap)) -- pr_warn("regmap initialization failed"); -+ dev_warn(priv->dev, "regmap initialization failed"); - - ret = qca8k_setup_mdio_bus(priv); - if (ret) diff --git a/target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch b/target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch deleted file mode 100644 index ff8288d484..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-02-net-dsa-qca8k-use-iopoll-macro-for-qca8k_busy_wait.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 2ad255f2faaffb3af786031fba2e7955454b558a Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:52 +0200 -Subject: [PATCH] net: dsa: qca8k: use iopoll macro for qca8k_busy_wait - -Use iopoll macro instead of while loop. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 23 +++++++++++------------ - drivers/net/dsa/qca8k.h | 2 ++ - 2 files changed, 13 insertions(+), 12 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -262,21 +262,20 @@ static struct regmap_config qca8k_regmap - static int - qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) - { -- unsigned long timeout; -+ u32 val; -+ int ret; - -- timeout = jiffies + msecs_to_jiffies(20); -+ ret = read_poll_timeout(qca8k_read, val, !(val & mask), -+ 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -+ priv, reg); - -- /* loop until the busy flag has cleared */ -- do { -- u32 val = qca8k_read(priv, reg); -- int busy = val & mask; -+ /* Check if qca8k_read has failed for a different reason -+ * before returning -ETIMEDOUT -+ */ -+ if (ret < 0 && val < 0) -+ return val; - -- if (!busy) -- break; -- cond_resched(); -- } while (!time_after_eq(jiffies, timeout)); -- -- return time_after_eq(jiffies, timeout); -+ return ret; - } - - static void ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -18,6 +18,8 @@ - #define PHY_ID_QCA8337 0x004dd036 - #define QCA8K_ID_QCA8337 0x13 - -+#define QCA8K_BUSY_WAIT_TIMEOUT 20 -+ - #define QCA8K_NUM_FDB_RECORDS 2048 - - #define QCA8K_CPU_PORT 0 diff --git a/target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch b/target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch deleted file mode 100644 index c403589874..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-03-net-dsa-qca8k-improve-qca8k-read-write-rmw-bus-acces.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 504bf65931824eda83494e5b5d75686e27ace03e Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:53 +0200 -Subject: [PATCH] net: dsa: qca8k: improve qca8k read/write/rmw bus access - -Put bus in local variable to improve faster access to the mdio bus. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 29 ++++++++++++++++------------- - 1 file changed, 16 insertions(+), 13 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -142,17 +142,18 @@ qca8k_set_page(struct mii_bus *bus, u16 - static u32 - qca8k_read(struct qca8k_priv *priv, u32 reg) - { -+ struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - - qca8k_split_addr(reg, &r1, &r2, &page); - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- qca8k_set_page(priv->bus, page); -- val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); -+ qca8k_set_page(bus, page); -+ val = qca8k_mii_read32(bus, 0x10 | r2, r1); - -- mutex_unlock(&priv->bus->mdio_lock); -+ mutex_unlock(&bus->mdio_lock); - - return val; - } -@@ -160,35 +161,37 @@ qca8k_read(struct qca8k_priv *priv, u32 - static void - qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) - { -+ struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - - qca8k_split_addr(reg, &r1, &r2, &page); - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- qca8k_set_page(priv->bus, page); -- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); -+ qca8k_set_page(bus, page); -+ qca8k_mii_write32(bus, 0x10 | r2, r1, val); - -- mutex_unlock(&priv->bus->mdio_lock); -+ mutex_unlock(&bus->mdio_lock); - } - - static u32 - qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val) - { -+ struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 ret; - - qca8k_split_addr(reg, &r1, &r2, &page); - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- qca8k_set_page(priv->bus, page); -- ret = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); -+ qca8k_set_page(bus, page); -+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1); - ret &= ~mask; - ret |= val; -- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, ret); -+ qca8k_mii_write32(bus, 0x10 | r2, r1, ret); - -- mutex_unlock(&priv->bus->mdio_lock); -+ mutex_unlock(&bus->mdio_lock); - - return ret; - } diff --git a/target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch b/target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch deleted file mode 100644 index 6be494a8c7..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-04-net-dsa-qca8k-handle-qca8k_set_page-errors.patch +++ /dev/null @@ -1,101 +0,0 @@ -From ba5707ec58cfb6853dff41c2aae72deb6a03d389 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:54 +0200 -Subject: [PATCH] net: dsa: qca8k: handle qca8k_set_page errors - -With a remote possibility, the set_page function can fail. Since this is -a critical part of the write/read qca8k regs, propagate the error and -terminate any read/write operation. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 33 ++++++++++++++++++++++++++------- - 1 file changed, 26 insertions(+), 7 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -127,16 +127,23 @@ qca8k_mii_write32(struct mii_bus *bus, i - "failed to write qca8k 32bit register\n"); - } - --static void -+static int - qca8k_set_page(struct mii_bus *bus, u16 page) - { -+ int ret; -+ - if (page == qca8k_current_page) -- return; -+ return 0; - -- if (bus->write(bus, 0x18, 0, page) < 0) -+ ret = bus->write(bus, 0x18, 0, page); -+ if (ret < 0) { - dev_err_ratelimited(&bus->dev, - "failed to set qca8k page\n"); -+ return ret; -+ } -+ - qca8k_current_page = page; -+ return 0; - } - - static u32 -@@ -150,11 +157,14 @@ qca8k_read(struct qca8k_priv *priv, u32 - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- qca8k_set_page(bus, page); -+ val = qca8k_set_page(bus, page); -+ if (val < 0) -+ goto exit; -+ - val = qca8k_mii_read32(bus, 0x10 | r2, r1); - -+exit: - mutex_unlock(&bus->mdio_lock); -- - return val; - } - -@@ -163,14 +173,19 @@ qca8k_write(struct qca8k_priv *priv, u32 - { - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; -+ int ret; - - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- qca8k_set_page(bus, page); -+ ret = qca8k_set_page(bus, page); -+ if (ret < 0) -+ goto exit; -+ - qca8k_mii_write32(bus, 0x10 | r2, r1, val); - -+exit: - mutex_unlock(&bus->mdio_lock); - } - -@@ -185,12 +200,16 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- qca8k_set_page(bus, page); -+ ret = qca8k_set_page(bus, page); -+ if (ret < 0) -+ goto exit; -+ - ret = qca8k_mii_read32(bus, 0x10 | r2, r1); - ret &= ~mask; - ret |= val; - qca8k_mii_write32(bus, 0x10 | r2, r1, ret); - -+exit: - mutex_unlock(&bus->mdio_lock); - - return ret; diff --git a/target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch b/target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch deleted file mode 100644 index 3349b7897a..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-05-net-dsa-qca8k-handle-error-with-qca8k_read-operation.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 028f5f8ef44fcf87a456772cbb9f0d90a0a22884 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:55 +0200 -Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_read operation - -qca8k_read can fail. Rework any user to handle error values and -correctly return. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 73 ++++++++++++++++++++++++++++++++--------- - 1 file changed, 58 insertions(+), 15 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -231,8 +231,13 @@ static int - qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) - { - struct qca8k_priv *priv = (struct qca8k_priv *)ctx; -+ int ret; -+ -+ ret = qca8k_read(priv, reg); -+ if (ret < 0) -+ return ret; - -- *val = qca8k_read(priv, reg); -+ *val = ret; - - return 0; - } -@@ -300,15 +305,20 @@ qca8k_busy_wait(struct qca8k_priv *priv, - return ret; - } - --static void -+static int - qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) - { -- u32 reg[4]; -+ u32 reg[4], val; - int i; - - /* load the ARL table into an array */ -- for (i = 0; i < 4; i++) -- reg[i] = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4)); -+ for (i = 0; i < 4; i++) { -+ val = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4)); -+ if (val < 0) -+ return val; -+ -+ reg[i] = val; -+ } - - /* vid - 83:72 */ - fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M; -@@ -323,6 +333,8 @@ qca8k_fdb_read(struct qca8k_priv *priv, - fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff; - fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff; - fdb->mac[5] = reg[0] & 0xff; -+ -+ return 0; - } - - static void -@@ -374,6 +386,8 @@ qca8k_fdb_access(struct qca8k_priv *priv - /* Check for table full violation when adding an entry */ - if (cmd == QCA8K_FDB_LOAD) { - reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC); -+ if (reg < 0) -+ return reg; - if (reg & QCA8K_ATU_FUNC_FULL) - return -1; - } -@@ -388,10 +402,10 @@ qca8k_fdb_next(struct qca8k_priv *priv, - - qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging); - ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port); -- if (ret >= 0) -- qca8k_fdb_read(priv, fdb); -+ if (ret < 0) -+ return ret; - -- return ret; -+ return qca8k_fdb_read(priv, fdb); - } - - static int -@@ -449,6 +463,8 @@ qca8k_vlan_access(struct qca8k_priv *pri - /* Check for table full violation when adding an entry */ - if (cmd == QCA8K_VLAN_LOAD) { - reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1); -+ if (reg < 0) -+ return reg; - if (reg & QCA8K_VTU_FUNC1_FULL) - return -ENOMEM; - } -@@ -475,6 +491,8 @@ qca8k_vlan_add(struct qca8k_priv *priv, - goto out; - - reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); -+ if (reg < 0) -+ return reg; - reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; - reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); - if (untagged) -@@ -506,6 +524,8 @@ qca8k_vlan_del(struct qca8k_priv *priv, - goto out; - - reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); -+ if (reg < 0) -+ return reg; - reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); - reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << - QCA8K_VTU_FUNC0_EG_MODE_S(port); -@@ -621,8 +641,11 @@ qca8k_mdio_read(struct qca8k_priv *priv, - QCA8K_MDIO_MASTER_BUSY)) - return -ETIMEDOUT; - -- val = (qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL) & -- QCA8K_MDIO_MASTER_DATA_MASK); -+ val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL); -+ if (val < 0) -+ return val; -+ -+ val &= QCA8K_MDIO_MASTER_DATA_MASK; - - return val; - } -@@ -978,6 +1001,8 @@ qca8k_phylink_mac_link_state(struct dsa_ - u32 reg; - - reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port)); -+ if (reg < 0) -+ return reg; - - state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); - state->an_complete = state->link; -@@ -1078,18 +1103,26 @@ qca8k_get_ethtool_stats(struct dsa_switc - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - const struct qca8k_mib_desc *mib; -- u32 reg, i; -+ u32 reg, i, val; - u64 hi; - - for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { - mib = &ar8327_mib[i]; - reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; - -- data[i] = qca8k_read(priv, reg); -+ val = qca8k_read(priv, reg); -+ if (val < 0) -+ continue; -+ - if (mib->size == 2) { - hi = qca8k_read(priv, reg + 4); -- data[i] |= hi << 32; -+ if (hi < 0) -+ continue; - } -+ -+ data[i] = val; -+ if (mib->size == 2) -+ data[i] |= hi << 32; - } - } - -@@ -1107,18 +1140,25 @@ qca8k_set_mac_eee(struct dsa_switch *ds, - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port); -+ int ret = 0; - u32 reg; - - mutex_lock(&priv->reg_mutex); - reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL); -+ if (reg < 0) { -+ ret = reg; -+ goto exit; -+ } -+ - if (eee->eee_enabled) - reg |= lpi_en; - else - reg &= ~lpi_en; - qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); -- mutex_unlock(&priv->reg_mutex); - -- return 0; -+exit: -+ mutex_unlock(&priv->reg_mutex); -+ return ret; - } - - static int -@@ -1456,6 +1496,9 @@ qca8k_sw_probe(struct mdio_device *mdiod - - /* read the switches ID register */ - id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); -+ if (id < 0) -+ return id; -+ - id >>= QCA8K_MASK_CTRL_ID_S; - id &= QCA8K_MASK_CTRL_ID_M; - if (id != QCA8K_ID_QCA8337) diff --git a/target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch b/target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch deleted file mode 100644 index 1e0e224c39..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-06-net-dsa-qca8k-handle-error-with-qca8k_write-operatio.patch +++ /dev/null @@ -1,263 +0,0 @@ -From d7805757c75c76e9518fc1023a29f0c4eed5b581 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:56 +0200 -Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_write operation - -qca8k_write can fail. Rework any user to handle error values and -correctly return. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 102 ++++++++++++++++++++++++++-------------- - 1 file changed, 67 insertions(+), 35 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -168,7 +168,7 @@ exit: - return val; - } - --static void -+static int - qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) - { - struct mii_bus *bus = priv->bus; -@@ -187,6 +187,7 @@ qca8k_write(struct qca8k_priv *priv, u32 - - exit: - mutex_unlock(&bus->mdio_lock); -+ return ret; - } - - static u32 -@@ -247,9 +248,7 @@ qca8k_regmap_write(void *ctx, uint32_t r - { - struct qca8k_priv *priv = (struct qca8k_priv *)ctx; - -- qca8k_write(priv, reg, val); -- -- return 0; -+ return qca8k_write(priv, reg, val); - } - - static const struct regmap_range qca8k_readable_ranges[] = { -@@ -367,6 +366,7 @@ static int - qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port) - { - u32 reg; -+ int ret; - - /* Set the command and FDB index */ - reg = QCA8K_ATU_FUNC_BUSY; -@@ -377,7 +377,9 @@ qca8k_fdb_access(struct qca8k_priv *priv - } - - /* Write the function register triggering the table access */ -- qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg); -+ ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg); -+ if (ret) -+ return ret; - - /* wait for completion */ - if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY)) -@@ -447,6 +449,7 @@ static int - qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) - { - u32 reg; -+ int ret; - - /* Set the command and VLAN index */ - reg = QCA8K_VTU_FUNC1_BUSY; -@@ -454,7 +457,9 @@ qca8k_vlan_access(struct qca8k_priv *pri - reg |= vid << QCA8K_VTU_FUNC1_VID_S; - - /* Write the function register triggering the table access */ -- qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); -+ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); -+ if (ret) -+ return ret; - - /* wait for completion */ - if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY)) -@@ -502,7 +507,9 @@ qca8k_vlan_add(struct qca8k_priv *priv, - reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG << - QCA8K_VTU_FUNC0_EG_MODE_S(port); - -- qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); -+ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); -+ if (ret) -+ return ret; - ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); - - out: -@@ -545,7 +552,9 @@ qca8k_vlan_del(struct qca8k_priv *priv, - if (del) { - ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid); - } else { -- qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); -+ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); -+ if (ret) -+ return ret; - ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); - } - -@@ -555,15 +564,20 @@ out: - return ret; - } - --static void -+static int - qca8k_mib_init(struct qca8k_priv *priv) - { -+ int ret; -+ - mutex_lock(&priv->reg_mutex); - qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); - qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); - qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); -- qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); -+ -+ ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); -+ - mutex_unlock(&priv->reg_mutex); -+ return ret; - } - - static void -@@ -600,6 +614,7 @@ static int - qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) - { - u32 phy, val; -+ int ret; - - if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) - return -EINVAL; -@@ -613,7 +628,9 @@ qca8k_mdio_write(struct qca8k_priv *priv - QCA8K_MDIO_MASTER_REG_ADDR(regnum) | - QCA8K_MDIO_MASTER_DATA(data); - -- qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); -+ ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); -+ if (ret) -+ return ret; - - return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); -@@ -623,6 +640,7 @@ static int - qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) - { - u32 phy, val; -+ int ret; - - if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) - return -EINVAL; -@@ -635,7 +653,9 @@ qca8k_mdio_read(struct qca8k_priv *priv, - QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | - QCA8K_MDIO_MASTER_REG_ADDR(regnum); - -- qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); -+ ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); -+ if (ret) -+ return ret; - - if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY)) -@@ -766,12 +786,18 @@ qca8k_setup(struct dsa_switch *ds) - QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); - - /* Enable MIB counters */ -- qca8k_mib_init(priv); -+ ret = qca8k_mib_init(priv); -+ if (ret) -+ dev_warn(priv->dev, "mib init failed"); - - /* Enable QCA header mode on the cpu port */ -- qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT), -- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | -- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); -+ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT), -+ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S | -+ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S); -+ if (ret) { -+ dev_err(priv->dev, "failed enabling QCA header mode"); -+ return ret; -+ } - - /* Disable forwarding by default on all ports */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) -@@ -783,11 +809,13 @@ qca8k_setup(struct dsa_switch *ds) - qca8k_port_set_status(priv, i, 0); - - /* Forward all unknown frames to CPU port for Linux processing */ -- qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, -- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | -- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | -- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | -- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); -+ ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, -+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S | -+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S | -+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S | -+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S); -+ if (ret) -+ return ret; - - /* Setup connection between CPU port & user ports */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) { -@@ -815,16 +843,20 @@ qca8k_setup(struct dsa_switch *ds) - qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), - 0xfff << shift, - QCA8K_PORT_VID_DEF << shift); -- qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), -- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | -- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -+ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), -+ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | -+ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -+ if (ret) -+ return ret; - } - } - - /* Setup our port MTUs to match power on defaults */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) - priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; -- qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); -+ ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); -+ if (ret) -+ dev_warn(priv->dev, "failed setting MTU settings"); - - /* Flush the FDB table */ - qca8k_fdb_flush(priv); -@@ -1140,8 +1172,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds, - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port); -- int ret = 0; - u32 reg; -+ int ret; - - mutex_lock(&priv->reg_mutex); - reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL); -@@ -1154,7 +1186,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds, - reg |= lpi_en; - else - reg &= ~lpi_en; -- qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); -+ ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg); - - exit: - mutex_unlock(&priv->reg_mutex); -@@ -1284,9 +1316,7 @@ qca8k_port_change_mtu(struct dsa_switch - mtu = priv->port_mtu[i]; - - /* Include L2 header / FCS length */ -- qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN); -- -- return 0; -+ return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN); - } - - static int diff --git a/target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch b/target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch deleted file mode 100644 index 506966f1af..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-07-net-dsa-qca8k-handle-error-with-qca8k_rmw-operation.patch +++ /dev/null @@ -1,226 +0,0 @@ -From aaf421425cbdec4eb6fd75a29e65c2867b0b7bbd Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:57 +0200 -Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_rmw operation - -qca8k_rmw can fail. Rework any user to handle error values and -correctly return. Change qca8k_rmw to return the error code or 0 instead -of the reg value. The reg returned by qca8k_rmw wasn't used anywhere, -so this doesn't cause any functional change. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 133 +++++++++++++++++++++++++--------------- - 1 file changed, 83 insertions(+), 50 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -190,12 +190,13 @@ exit: - return ret; - } - --static u32 --qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val) -+static int -+qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) - { - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; -- u32 ret; -+ u32 val; -+ int ret; - - qca8k_split_addr(reg, &r1, &r2, &page); - -@@ -205,10 +206,15 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r - if (ret < 0) - goto exit; - -- ret = qca8k_mii_read32(bus, 0x10 | r2, r1); -- ret &= ~mask; -- ret |= val; -- qca8k_mii_write32(bus, 0x10 | r2, r1, ret); -+ val = qca8k_mii_read32(bus, 0x10 | r2, r1); -+ if (val < 0) { -+ ret = val; -+ goto exit; -+ } -+ -+ val &= ~mask; -+ val |= write_val; -+ qca8k_mii_write32(bus, 0x10 | r2, r1, val); - - exit: - mutex_unlock(&bus->mdio_lock); -@@ -216,16 +222,16 @@ exit: - return ret; - } - --static void -+static int - qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val) - { -- qca8k_rmw(priv, reg, 0, val); -+ return qca8k_rmw(priv, reg, 0, val); - } - --static void -+static int - qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val) - { -- qca8k_rmw(priv, reg, val, 0); -+ return qca8k_rmw(priv, reg, val, 0); - } - - static int -@@ -570,12 +576,19 @@ qca8k_mib_init(struct qca8k_priv *priv) - int ret; - - mutex_lock(&priv->reg_mutex); -- qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); -+ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); -+ if (ret) -+ goto exit; -+ - qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); -- qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); -+ -+ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); -+ if (ret) -+ goto exit; - - ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB); - -+exit: - mutex_unlock(&priv->reg_mutex); - return ret; - } -@@ -747,9 +760,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv * - * a dt-overlay and driver reload changed the configuration - */ - -- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_EN); -- return 0; -+ return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_EN); - } - - priv->ops.phy_read = qca8k_phy_read; -@@ -782,8 +794,12 @@ qca8k_setup(struct dsa_switch *ds) - return ret; - - /* Enable CPU Port */ -- qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, -- QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); -+ ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, -+ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); -+ if (ret) { -+ dev_err(priv->dev, "failed enabling CPU port"); -+ return ret; -+ } - - /* Enable MIB counters */ - ret = qca8k_mib_init(priv); -@@ -800,9 +816,12 @@ qca8k_setup(struct dsa_switch *ds) - } - - /* Disable forwarding by default on all ports */ -- for (i = 0; i < QCA8K_NUM_PORTS; i++) -- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_MEMBER, 0); -+ for (i = 0; i < QCA8K_NUM_PORTS; i++) { -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -+ QCA8K_PORT_LOOKUP_MEMBER, 0); -+ if (ret) -+ return ret; -+ } - - /* Disable MAC by default on all ports */ - for (i = 1; i < QCA8K_NUM_PORTS; i++) -@@ -821,28 +840,37 @@ qca8k_setup(struct dsa_switch *ds) - for (i = 0; i < QCA8K_NUM_PORTS; i++) { - /* CPU port gets connected to all user ports of the switch */ - if (dsa_is_cpu_port(ds, i)) { -- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), -- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT), -+ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); -+ if (ret) -+ return ret; - } - - /* Individual user ports get connected to CPU port only */ - if (dsa_is_user_port(ds, i)) { - int shift = 16 * (i % 2); - -- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_MEMBER, -- BIT(QCA8K_CPU_PORT)); -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), -+ QCA8K_PORT_LOOKUP_MEMBER, -+ BIT(QCA8K_CPU_PORT)); -+ if (ret) -+ return ret; - - /* Enable ARP Auto-learning by default */ -- qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), -- QCA8K_PORT_LOOKUP_LEARN); -+ ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), -+ QCA8K_PORT_LOOKUP_LEARN); -+ if (ret) -+ return ret; - - /* For port based vlans to work we need to set the - * default egress vid - */ -- qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), -- 0xfff << shift, -- QCA8K_PORT_VID_DEF << shift); -+ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), -+ 0xfff << shift, -+ QCA8K_PORT_VID_DEF << shift); -+ if (ret) -+ return ret; -+ - ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), - QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | - QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); -@@ -1234,7 +1262,7 @@ qca8k_port_bridge_join(struct dsa_switch - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - int port_mask = BIT(QCA8K_CPU_PORT); -- int i; -+ int i, ret; - - for (i = 1; i < QCA8K_NUM_PORTS; i++) { - if (dsa_to_port(ds, i)->bridge_dev != br) -@@ -1242,17 +1270,20 @@ qca8k_port_bridge_join(struct dsa_switch - /* Add this port to the portvlan mask of the other ports - * in the bridge - */ -- qca8k_reg_set(priv, -- QCA8K_PORT_LOOKUP_CTRL(i), -- BIT(port)); -+ ret = qca8k_reg_set(priv, -+ QCA8K_PORT_LOOKUP_CTRL(i), -+ BIT(port)); -+ if (ret) -+ return ret; - if (i != port) - port_mask |= BIT(i); - } -+ - /* Add all other ports to this ports portvlan mask */ -- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), -- QCA8K_PORT_LOOKUP_MEMBER, port_mask); -+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), -+ QCA8K_PORT_LOOKUP_MEMBER, port_mask); - -- return 0; -+ return ret; - } - - static void diff --git a/target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch b/target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch deleted file mode 100644 index 360ce1d947..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-08-net-dsa-qca8k-handle-error-from-qca8k_busy_wait.patch +++ /dev/null @@ -1,66 +0,0 @@ -From b7c818d194927bdc60ed15db55bb8654496a36b7 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:58 +0200 -Subject: [PATCH] net: dsa: qca8k: handle error from qca8k_busy_wait - -Propagate errors from qca8k_busy_wait instead of hardcoding return -value. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 21 +++++++++++++-------- - 1 file changed, 13 insertions(+), 8 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -388,8 +388,9 @@ qca8k_fdb_access(struct qca8k_priv *priv - return ret; - - /* wait for completion */ -- if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY)) -- return -1; -+ ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY); -+ if (ret) -+ return ret; - - /* Check for table full violation when adding an entry */ - if (cmd == QCA8K_FDB_LOAD) { -@@ -468,8 +469,9 @@ qca8k_vlan_access(struct qca8k_priv *pri - return ret; - - /* wait for completion */ -- if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY)) -- return -ETIMEDOUT; -+ ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY); -+ if (ret) -+ return ret; - - /* Check for table full violation when adding an entry */ - if (cmd == QCA8K_VLAN_LOAD) { -@@ -580,7 +582,9 @@ qca8k_mib_init(struct qca8k_priv *priv) - if (ret) - goto exit; - -- qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); -+ ret = qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY); -+ if (ret) -+ goto exit; - - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); - if (ret) -@@ -670,9 +674,10 @@ qca8k_mdio_read(struct qca8k_priv *priv, - if (ret) - return ret; - -- if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_BUSY)) -- return -ETIMEDOUT; -+ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_BUSY); -+ if (ret) -+ return ret; - - val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL); - if (val < 0) diff --git a/target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch b/target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch deleted file mode 100644 index 72305850ca..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-09-net-dsa-qca8k-add-support-for-qca8327-switch.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 6e82a457e06252b59102486767539cc9c2aba60b Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 22:59:59 +0200 -Subject: [PATCH] net: dsa: qca8k: add support for qca8327 switch - -qca8327 switch is a low tier version of the more recent qca8337. -It does share the same regs used by the qca8k driver and can be -supported with minimal change. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Reviewed-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 23 ++++++++++++++++++++--- - drivers/net/dsa/qca8k.h | 6 ++++++ - 2 files changed, 26 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1533,6 +1533,7 @@ static const struct dsa_switch_ops qca8k - static int - qca8k_sw_probe(struct mdio_device *mdiodev) - { -+ const struct qca8k_match_data *data; - struct qca8k_priv *priv; - u32 id; - -@@ -1560,6 +1561,11 @@ qca8k_sw_probe(struct mdio_device *mdiod - gpiod_set_value_cansleep(priv->reset_gpio, 0); - } - -+ /* get the switches ID from the compatible */ -+ data = of_device_get_match_data(&mdiodev->dev); -+ if (!data) -+ return -ENODEV; -+ - /* read the switches ID register */ - id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); - if (id < 0) -@@ -1567,8 +1573,10 @@ qca8k_sw_probe(struct mdio_device *mdiod - - id >>= QCA8K_MASK_CTRL_ID_S; - id &= QCA8K_MASK_CTRL_ID_M; -- if (id != QCA8K_ID_QCA8337) -+ if (id != data->id) { -+ dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id); - return -ENODEV; -+ } - - priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); - if (!priv->ds) -@@ -1634,9 +1642,18 @@ static int qca8k_resume(struct device *d - static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, - qca8k_suspend, qca8k_resume); - -+static const struct qca8k_match_data qca832x = { -+ .id = QCA8K_ID_QCA8327, -+}; -+ -+static const struct qca8k_match_data qca833x = { -+ .id = QCA8K_ID_QCA8337, -+}; -+ - static const struct of_device_id qca8k_of_match[] = { -- { .compatible = "qca,qca8334" }, -- { .compatible = "qca,qca8337" }, -+ { .compatible = "qca,qca8327", .data = &qca832x }, -+ { .compatible = "qca,qca8334", .data = &qca833x }, -+ { .compatible = "qca,qca8337", .data = &qca833x }, - { /* sentinel */ }, - }; - ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -15,6 +15,8 @@ - #define QCA8K_NUM_PORTS 7 - #define QCA8K_MAX_MTU 9000 - -+#define PHY_ID_QCA8327 0x004dd034 -+#define QCA8K_ID_QCA8327 0x12 - #define PHY_ID_QCA8337 0x004dd036 - #define QCA8K_ID_QCA8337 0x13 - -@@ -213,6 +215,10 @@ struct ar8xxx_port_status { - int enabled; - }; - -+struct qca8k_match_data { -+ u8 id; -+}; -+ - struct qca8k_priv { - struct regmap *regmap; - struct mii_bus *bus; diff --git a/target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch b/target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch deleted file mode 100644 index 3c4a14bd0b..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-10-devicetree-net-dsa-qca8k-Document-new-compatible-qca.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 227a9ffc1bc77037339530607fe129af3824620e Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:00 +0200 -Subject: [PATCH] devicetree: net: dsa: qca8k: Document new compatible qca8327 - -Add support for qca8327 in the compatible list. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Acked-by: Rob Herring -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - Documentation/devicetree/bindings/net/dsa/qca8k.txt | 1 + - 1 file changed, 1 insertion(+) - ---- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt -+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt -@@ -3,6 +3,7 @@ - Required properties: - - - compatible: should be one of: -+ "qca,qca8327" - "qca,qca8334" - "qca,qca8337" - diff --git a/target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch b/target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch deleted file mode 100644 index cd3050ef71..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-11-net-dsa-qca8k-add-priority-tweak-to-qca8337-switch.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 83a3ceb39b2495171aabe9446271b94c678354f3 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:01 +0200 -Subject: [PATCH] net: dsa: qca8k: add priority tweak to qca8337 switch - -The port 5 of the qca8337 have some problem in flood condition. The -original legacy driver had some specific buffer and priority settings -for the different port suggested by the QCA switch team. Add this -missing settings to improve switch stability under load condition. -The packet priority tweak is only needed for the qca8337 switch and -other qca8k switch are not affected. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 47 +++++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/qca8k.h | 25 ++++++++++++++++++++++ - 2 files changed, 72 insertions(+) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -779,6 +779,7 @@ qca8k_setup(struct dsa_switch *ds) - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - int ret, i; -+ u32 mask; - - /* Make sure that port 0 is the cpu port */ - if (!dsa_is_cpu_port(ds, 0)) { -@@ -884,6 +885,51 @@ qca8k_setup(struct dsa_switch *ds) - } - } - -+ /* The port 5 of the qca8337 have some problem in flood condition. The -+ * original legacy driver had some specific buffer and priority settings -+ * for the different port suggested by the QCA switch team. Add this -+ * missing settings to improve switch stability under load condition. -+ * This problem is limited to qca8337 and other qca8k switch are not affected. -+ */ -+ if (priv->switch_id == QCA8K_ID_QCA8337) { -+ for (i = 0; i < QCA8K_NUM_PORTS; i++) { -+ switch (i) { -+ /* The 2 CPU port and port 5 requires some different -+ * priority than any other ports. -+ */ -+ case 0: -+ case 5: -+ case 6: -+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | -+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); -+ break; -+ default: -+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | -+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | -+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); -+ } -+ qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); -+ -+ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | -+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_WRED_EN; -+ qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), -+ QCA8K_PORT_HOL_CTRL1_ING_BUF | -+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | -+ QCA8K_PORT_HOL_CTRL1_WRED_EN, -+ mask); -+ } -+ } -+ - /* Setup our port MTUs to match power on defaults */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) - priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; -@@ -1578,6 +1624,7 @@ qca8k_sw_probe(struct mdio_device *mdiod - return -ENODEV; - } - -+ priv->switch_id = id; - priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); - if (!priv->ds) - return -ENOMEM; ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -168,6 +168,30 @@ - #define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) - #define QCA8K_PORT_LOOKUP_LEARN BIT(20) - -+#define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF GENMASK(7, 4) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) ((x) << 4) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF GENMASK(11, 8) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) ((x) << 8) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF GENMASK(15, 12) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) ((x) << 12) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF GENMASK(19, 16) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) ((x) << 16) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF GENMASK(23, 20) -+#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) ((x) << 20) -+#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF GENMASK(29, 24) -+#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) ((x) << 24) -+ -+#define QCA8K_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) -+#define QCA8K_PORT_HOL_CTRL1_ING_BUF GENMASK(3, 0) -+#define QCA8K_PORT_HOL_CTRL1_ING(x) ((x) << 0) -+#define QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN BIT(6) -+#define QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN BIT(7) -+#define QCA8K_PORT_HOL_CTRL1_WRED_EN BIT(8) -+#define QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) -+ - /* Pkt edit registers */ - #define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2))) - -@@ -220,6 +244,7 @@ struct qca8k_match_data { - }; - - struct qca8k_priv { -+ u8 switch_id; - struct regmap *regmap; - struct mii_bus *bus; - struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch b/target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch deleted file mode 100644 index d25edbb1aa..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-12-net-dsa-qca8k-limit-port5-delay-to-qca8337.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 5bf9ff3b9fb5ecb67a1a3517b26db3a00f2a2f11 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:02 +0200 -Subject: [PATCH] net: dsa: qca8k: limit port5 delay to qca8337 - -Limit port5 rx delay to qca8337. This is taken from the legacy QSDK code -that limits the rx delay on port5 to only this particular switch version, -on other switch only the tx and rx delay for port0 are needed. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1003,8 +1003,10 @@ qca8k_phylink_mac_config(struct dsa_swit - QCA8K_PORT_PAD_RGMII_EN | - QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) | - QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY)); -- qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, -- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); -+ /* QCA8337 requires to set rgmii rx delay */ -+ if (priv->switch_id == QCA8K_ID_QCA8337) -+ qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, -+ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); - break; - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: diff --git a/target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch b/target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch deleted file mode 100644 index 2b393d242a..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-13-net-dsa-qca8k-add-GLOBAL_FC-settings-needed-for-qca8.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0fc57e4b5e39461fc0a54aae0afe4241363a7267 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:03 +0200 -Subject: [PATCH] net: dsa: qca8k: add GLOBAL_FC settings needed for qca8327 - -Switch qca8327 needs special settings for the GLOBAL_FC_THRES regs. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 10 ++++++++++ - drivers/net/dsa/qca8k.h | 6 ++++++ - 2 files changed, 16 insertions(+) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -930,6 +930,16 @@ qca8k_setup(struct dsa_switch *ds) - } - } - -+ /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ -+ if (priv->switch_id == QCA8K_ID_QCA8327) { -+ mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | -+ QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); -+ qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, -+ QCA8K_GLOBAL_FC_GOL_XON_THRES_S | -+ QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S, -+ mask); -+ } -+ - /* Setup our port MTUs to match power on defaults */ - for (i = 0; i < QCA8K_NUM_PORTS; i++) - priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN; ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -168,6 +168,12 @@ - #define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16) - #define QCA8K_PORT_LOOKUP_LEARN BIT(20) - -+#define QCA8K_REG_GLOBAL_FC_THRESH 0x800 -+#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16) -+#define QCA8K_GLOBAL_FC_GOL_XON_THRES_S GENMASK(24, 16) -+#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) ((x) << 0) -+#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S GENMASK(8, 0) -+ - #define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8) - #define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0) - #define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0) diff --git a/target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch b/target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch deleted file mode 100644 index ed9b8188de..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 95ffeaf18b3bb90eeef52cbf7d79ccc9d0345ff5 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:04 +0200 -Subject: [PATCH] net: dsa: qca8k: add support for switch rev - -qca8k internal phy driver require some special debug value to be set -based on the switch revision. Rework the switch id read function to -also read the chip revision. - -Signed-off-by: Ansuel Smith -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 53 ++++++++++++++++++++++++++--------------- - drivers/net/dsa/qca8k.h | 7 ++++-- - 2 files changed, 39 insertions(+), 21 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1588,12 +1588,40 @@ static const struct dsa_switch_ops qca8k - .phylink_mac_link_up = qca8k_phylink_mac_link_up, - }; - -+static int qca8k_read_switch_id(struct qca8k_priv *priv) -+{ -+ const struct qca8k_match_data *data; -+ u32 val; -+ u8 id; -+ -+ /* get the switches ID from the compatible */ -+ data = of_device_get_match_data(priv->dev); -+ if (!data) -+ return -ENODEV; -+ -+ val = qca8k_read(priv, QCA8K_REG_MASK_CTRL); -+ if (val < 0) -+ return -ENODEV; -+ -+ id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); -+ if (id != data->id) { -+ dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); -+ return -ENODEV; -+ } -+ -+ priv->switch_id = id; -+ -+ /* Save revision to communicate to the internal PHY driver */ -+ priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK); -+ -+ return 0; -+} -+ - static int - qca8k_sw_probe(struct mdio_device *mdiodev) - { -- const struct qca8k_match_data *data; - struct qca8k_priv *priv; -- u32 id; -+ int ret; - - /* allocate the private data struct so that we can probe the switches - * ID register -@@ -1619,24 +1647,11 @@ qca8k_sw_probe(struct mdio_device *mdiod - gpiod_set_value_cansleep(priv->reset_gpio, 0); - } - -- /* get the switches ID from the compatible */ -- data = of_device_get_match_data(&mdiodev->dev); -- if (!data) -- return -ENODEV; -+ /* Check the detected switch id */ -+ ret = qca8k_read_switch_id(priv); -+ if (ret) -+ return ret; - -- /* read the switches ID register */ -- id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); -- if (id < 0) -- return id; -- -- id >>= QCA8K_MASK_CTRL_ID_S; -- id &= QCA8K_MASK_CTRL_ID_M; -- if (id != data->id) { -- dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id); -- return -ENODEV; -- } -- -- priv->switch_id = id; - priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); - if (!priv->ds) - return -ENOMEM; ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -30,8 +30,10 @@ - - /* Global control registers */ - #define QCA8K_REG_MASK_CTRL 0x000 --#define QCA8K_MASK_CTRL_ID_M 0xff --#define QCA8K_MASK_CTRL_ID_S 8 -+#define QCA8K_MASK_CTRL_REV_ID_MASK GENMASK(7, 0) -+#define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0) -+#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8) -+#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8) - #define QCA8K_REG_PORT0_PAD_CTRL 0x004 - #define QCA8K_REG_PORT5_PAD_CTRL 0x008 - #define QCA8K_REG_PORT6_PAD_CTRL 0x00c -@@ -251,6 +253,7 @@ struct qca8k_match_data { - - struct qca8k_priv { - u8 switch_id; -+ u8 switch_revision; - struct regmap *regmap; - struct mii_bus *bus; - struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch b/target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch deleted file mode 100644 index 629cb324e0..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-15-net-dsa-qca8k-add-ethernet-ports-fallback-to-setup_m.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 1ee0591a1093c2448642c33433483e9260275f7b Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:05 +0200 -Subject: [PATCH] net: dsa: qca8k: add ethernet-ports fallback to - setup_mdio_bus - -Dsa now also supports ethernet-ports. Add this new binding as a fallback -if the ports node can't be found. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -719,6 +719,9 @@ qca8k_setup_mdio_bus(struct qca8k_priv * - - ports = of_get_child_by_name(priv->dev->of_node, "ports"); - if (!ports) -+ ports = of_get_child_by_name(priv->dev->of_node, "ethernet-ports"); -+ -+ if (!ports) - return -EINVAL; - - for_each_available_child_of_node(ports, port) { diff --git a/target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch b/target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch deleted file mode 100644 index 6dc2dc6e3e..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-16-net-dsa-qca8k-make-rgmii-delay-configurable.patch +++ /dev/null @@ -1,188 +0,0 @@ -From e4b9977cee1583da38a6e9118078bb728aaccf7b Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:06 +0200 -Subject: [PATCH] net: dsa: qca8k: make rgmii delay configurable - -The legacy qsdk code used a different delay instead of the max value. -Qsdk use 1 ns for rx and 2 ns for tx. Make these values configurable -using the standard rx/tx-internal-delay-ps ethernet binding and apply -qsdk values by default. The connected gmac doesn't add any delay so no -additional delay is added to tx/rx. -On this switch the delay is actually in ns so value should be in the -1000 order. Any value converted from ps to ns by dividing it by 1000 -as the switch max value for delay is 3ns. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 82 ++++++++++++++++++++++++++++++++++++++++- - drivers/net/dsa/qca8k.h | 11 +++--- - 2 files changed, 86 insertions(+), 7 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -778,6 +778,68 @@ qca8k_setup_mdio_bus(struct qca8k_priv * - } - - static int -+qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv) -+{ -+ struct device_node *port_dn; -+ phy_interface_t mode; -+ struct dsa_port *dp; -+ u32 val; -+ -+ /* CPU port is already checked */ -+ dp = dsa_to_port(priv->ds, 0); -+ -+ port_dn = dp->dn; -+ -+ /* Check if port 0 is set to the correct type */ -+ of_get_phy_mode(port_dn, &mode); -+ if (mode != PHY_INTERFACE_MODE_RGMII_ID && -+ mode != PHY_INTERFACE_MODE_RGMII_RXID && -+ mode != PHY_INTERFACE_MODE_RGMII_TXID) { -+ return 0; -+ } -+ -+ switch (mode) { -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val)) -+ val = 2; -+ else -+ /* Switch regs accept value in ns, convert ps to ns */ -+ val = val / 1000; -+ -+ if (val > QCA8K_MAX_DELAY) { -+ dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value"); -+ val = 3; -+ } -+ -+ priv->rgmii_rx_delay = val; -+ /* Stop here if we need to check only for rx delay */ -+ if (mode != PHY_INTERFACE_MODE_RGMII_ID) -+ break; -+ -+ fallthrough; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val)) -+ val = 1; -+ else -+ /* Switch regs accept value in ns, convert ps to ns */ -+ val = val / 1000; -+ -+ if (val > QCA8K_MAX_DELAY) { -+ dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); -+ val = 3; -+ } -+ -+ priv->rgmii_tx_delay = val; -+ break; -+ default: -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static int - qca8k_setup(struct dsa_switch *ds) - { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; -@@ -802,6 +864,10 @@ qca8k_setup(struct dsa_switch *ds) - if (ret) - return ret; - -+ ret = qca8k_setup_of_rgmii_delay(priv); -+ if (ret) -+ return ret; -+ - /* Enable CPU Port */ - ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, - QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); -@@ -970,6 +1036,8 @@ qca8k_phylink_mac_config(struct dsa_swit - case 0: /* 1st CPU port */ - if (state->interface != PHY_INTERFACE_MODE_RGMII && - state->interface != PHY_INTERFACE_MODE_RGMII_ID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && - state->interface != PHY_INTERFACE_MODE_SGMII) - return; - -@@ -985,6 +1053,8 @@ qca8k_phylink_mac_config(struct dsa_swit - case 6: /* 2nd CPU port / external PHY */ - if (state->interface != PHY_INTERFACE_MODE_RGMII && - state->interface != PHY_INTERFACE_MODE_RGMII_ID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && - state->interface != PHY_INTERFACE_MODE_SGMII && - state->interface != PHY_INTERFACE_MODE_1000BASEX) - return; -@@ -1008,14 +1078,18 @@ qca8k_phylink_mac_config(struct dsa_swit - qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN); - break; - case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: - /* RGMII_ID needs internal delay. This is enabled through - * PORT5_PAD_CTRL for all ports, rather than individual port - * registers - */ - qca8k_write(priv, reg, - QCA8K_PORT_PAD_RGMII_EN | -- QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) | -- QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY)); -+ QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) | -+ QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) | -+ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN | -+ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); - /* QCA8337 requires to set rgmii rx delay */ - if (priv->switch_id == QCA8K_ID_QCA8337) - qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, -@@ -1073,6 +1147,8 @@ qca8k_phylink_validate(struct dsa_switch - if (state->interface != PHY_INTERFACE_MODE_NA && - state->interface != PHY_INTERFACE_MODE_RGMII && - state->interface != PHY_INTERFACE_MODE_RGMII_ID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && - state->interface != PHY_INTERFACE_MODE_SGMII) - goto unsupported; - break; -@@ -1090,6 +1166,8 @@ qca8k_phylink_validate(struct dsa_switch - if (state->interface != PHY_INTERFACE_MODE_NA && - state->interface != PHY_INTERFACE_MODE_RGMII && - state->interface != PHY_INTERFACE_MODE_RGMII_ID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID && -+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID && - state->interface != PHY_INTERFACE_MODE_SGMII && - state->interface != PHY_INTERFACE_MODE_1000BASEX) - goto unsupported; ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -38,12 +38,11 @@ - #define QCA8K_REG_PORT5_PAD_CTRL 0x008 - #define QCA8K_REG_PORT6_PAD_CTRL 0x00c - #define QCA8K_PORT_PAD_RGMII_EN BIT(26) --#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) \ -- ((0x8 + (x & 0x3)) << 22) --#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) \ -- ((0x10 + (x & 0x3)) << 20) --#define QCA8K_MAX_DELAY 3 -+#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22) -+#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20) -+#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25) - #define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) -+#define QCA8K_MAX_DELAY 3 - #define QCA8K_PORT_PAD_SGMII_EN BIT(7) - #define QCA8K_REG_PWS 0x010 - #define QCA8K_PWS_SERDES_AEN_DIS BIT(7) -@@ -254,6 +253,8 @@ struct qca8k_match_data { - struct qca8k_priv { - u8 switch_id; - u8 switch_revision; -+ u8 rgmii_tx_delay; -+ u8 rgmii_rx_delay; - struct regmap *regmap; - struct mii_bus *bus; - struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch b/target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch deleted file mode 100644 index 4593da032b..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-17-net-dsa-qca8k-clear-MASTER_EN-after-phy-read-write.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 63c33bbfeb6842a956a0eb12901e28eb335bdb18 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:07 +0200 -Subject: [PATCH] net: dsa: qca8k: clear MASTER_EN after phy read/write - -Clear MDIO_MASTER_EN bit from MDIO_MASTER_CTRL after read/write -operation. The MDIO_MASTER_EN bit is not reset after read/write -operation and the next operation can be wrongly interpreted by the -switch as a mdio operation. This cause a production of wrong/garbage -data from the switch and underfined bheavior. (random port drop, -unplugged port flagged with link up, wrong port speed) -Also on driver remove the MASTER_CTRL can be left set and cause the -malfunction of any next driver using the mdio device. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -649,8 +649,14 @@ qca8k_mdio_write(struct qca8k_priv *priv - if (ret) - return ret; - -- return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_BUSY); -+ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_BUSY); -+ -+ /* even if the busy_wait timeouts try to clear the MASTER_EN */ -+ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_EN); -+ -+ return ret; - } - - static int -@@ -685,6 +691,10 @@ qca8k_mdio_read(struct qca8k_priv *priv, - - val &= QCA8K_MDIO_MASTER_DATA_MASK; - -+ /* even if the busy_wait timeouts try to clear the MASTER_EN */ -+ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_EN); -+ - return val; - } - diff --git a/target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch b/target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch deleted file mode 100644 index b6684d7210..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-18-net-dsa-qca8k-dsa-qca8k-protect-MASTER-busy_wait-wit.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 60df02b6ea4581d72eb7a3ab7204504a54059b72 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:08 +0200 -Subject: [PATCH] net: dsa: qca8k: dsa: qca8k: protect MASTER busy_wait with - mdio mutex - -MDIO_MASTER operation have a dedicated busy wait that is not protected -by the mdio mutex. This can cause situation where the MASTER operation -is done and a normal operation is executed between the MASTER read/write -and the MASTER busy_wait. Rework the qca8k_mdio_read/write function to -address this issue by binding the lock for the whole MASTER operation -and not only the mdio read/write common operation. - -Signed-off-by: Ansuel Smith -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 68 +++++++++++++++++++++++++++++++++-------- - 1 file changed, 55 insertions(+), 13 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -628,8 +628,31 @@ qca8k_port_to_phy(int port) - } - - static int -+qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) -+{ -+ u16 r1, r2, page; -+ u32 val; -+ int ret; -+ -+ qca8k_split_addr(reg, &r1, &r2, &page); -+ -+ ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0, -+ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -+ priv->bus, 0x10 | r2, r1); -+ -+ /* Check if qca8k_read has failed for a different reason -+ * before returnting -ETIMEDOUT -+ */ -+ if (ret < 0 && val < 0) -+ return val; -+ -+ return ret; -+} -+ -+static int - qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) - { -+ u16 r1, r2, page; - u32 phy, val; - int ret; - -@@ -645,12 +668,21 @@ qca8k_mdio_write(struct qca8k_priv *priv - QCA8K_MDIO_MASTER_REG_ADDR(regnum) | - QCA8K_MDIO_MASTER_DATA(data); - -- ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); -+ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); -+ -+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = qca8k_set_page(priv->bus, page); - if (ret) -- return ret; -+ goto exit; -+ -+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); - -- ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_BUSY); -+ ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_BUSY); -+ -+exit: -+ mutex_unlock(&priv->bus->mdio_lock); - - /* even if the busy_wait timeouts try to clear the MASTER_EN */ - qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -@@ -662,6 +694,7 @@ qca8k_mdio_write(struct qca8k_priv *priv - static int - qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) - { -+ u16 r1, r2, page; - u32 phy, val; - int ret; - -@@ -676,21 +709,30 @@ qca8k_mdio_read(struct qca8k_priv *priv, - QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | - QCA8K_MDIO_MASTER_REG_ADDR(regnum); - -- ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val); -- if (ret) -- return ret; -+ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); -+ -+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); - -- ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_BUSY); -+ ret = qca8k_set_page(priv->bus, page); - if (ret) -- return ret; -+ goto exit; - -- val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL); -- if (val < 0) -- return val; -+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); -+ -+ ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -+ QCA8K_MDIO_MASTER_BUSY); -+ if (ret) -+ goto exit; - -+ val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); - val &= QCA8K_MDIO_MASTER_DATA_MASK; - -+exit: -+ mutex_unlock(&priv->bus->mdio_lock); -+ -+ if (val >= 0) -+ val &= QCA8K_MDIO_MASTER_DATA_MASK; -+ - /* even if the busy_wait timeouts try to clear the MASTER_EN */ - qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_EN); diff --git a/target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch b/target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch deleted file mode 100644 index 30eeed361e..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-19-net-dsa-qca8k-enlarge-mdio-delay-and-timeout.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 617960d72e93de0f3fa52407e2d39e8c43e73b0a Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:09 +0200 -Subject: [PATCH] net: dsa: qca8k: enlarge mdio delay and timeout - -The witch require some extra delay after setting page or the next -read/write can use still use the old page. Add a delay after the -set_page function to address this as it's done in QSDK legacy driver. -Some timeouts were notice with VLAN and phy function, enlarge the -mdio busy wait timeout to fix these problems. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 1 + - drivers/net/dsa/qca8k.h | 2 +- - 2 files changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -143,6 +143,7 @@ qca8k_set_page(struct mii_bus *bus, u16 - } - - qca8k_current_page = page; -+ usleep_range(1000, 2000); - return 0; - } - ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -20,7 +20,7 @@ - #define PHY_ID_QCA8337 0x004dd036 - #define QCA8K_ID_QCA8337 0x13 - --#define QCA8K_BUSY_WAIT_TIMEOUT 20 -+#define QCA8K_BUSY_WAIT_TIMEOUT 2000 - - #define QCA8K_NUM_FDB_RECORDS 2048 - diff --git a/target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch b/target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch deleted file mode 100644 index 88d3c1ef43..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-20-net-dsa-qca8k-add-support-for-internal-phy-and-inter.patch +++ /dev/null @@ -1,267 +0,0 @@ -From 759bafb8a3226326ca357613bc90acf738f80c32 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:10 +0200 -Subject: [PATCH] net: dsa: qca8k: add support for internal phy and internal - mdio - -Add support to setup_mdio_bus for internal phy declaration. Introduce a -flag to use the legacy port phy mapping by default and use the direct -mapping if a mdio node is detected in the switch node. Register a -dedicated mdio internal mdio bus to address the different mapping -between port and phy if the mdio node is detected. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 112 +++++++++++++++++++++++++++++----------- - drivers/net/dsa/qca8k.h | 1 + - 2 files changed, 83 insertions(+), 30 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -629,7 +630,7 @@ qca8k_port_to_phy(int port) - } - - static int --qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) -+qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) - { - u16 r1, r2, page; - u32 val; -@@ -639,7 +640,7 @@ qca8k_mdio_busy_wait(struct qca8k_priv * - - ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0, - QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -- priv->bus, 0x10 | r2, r1); -+ bus, 0x10 | r2, r1); - - /* Check if qca8k_read has failed for a different reason - * before returnting -ETIMEDOUT -@@ -651,19 +652,16 @@ qca8k_mdio_busy_wait(struct qca8k_priv * - } - - static int --qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data) -+qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) - { -+ struct qca8k_priv *priv = salve_bus->priv; - u16 r1, r2, page; -- u32 phy, val; -+ u32 val; - int ret; - - if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) - return -EINVAL; - -- /* callee is responsible for not passing bad ports, -- * but we still would like to make spills impossible. -- */ -- phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR; - val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | - QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | - QCA8K_MDIO_MASTER_REG_ADDR(regnum) | -@@ -679,33 +677,29 @@ qca8k_mdio_write(struct qca8k_priv *priv - - qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); - -- ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -+ ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); - - exit: -- mutex_unlock(&priv->bus->mdio_lock); -- - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_EN); -+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); -+ -+ mutex_unlock(&priv->bus->mdio_lock); - - return ret; - } - - static int --qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum) -+qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) - { -+ struct qca8k_priv *priv = salve_bus->priv; - u16 r1, r2, page; -- u32 phy, val; -+ u32 val; - int ret; - - if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) - return -EINVAL; - -- /* callee is responsible for not passing bad ports, -- * but we still would like to make spills impossible. -- */ -- phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR; - val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | - QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) | - QCA8K_MDIO_MASTER_REG_ADDR(regnum); -@@ -720,24 +714,22 @@ qca8k_mdio_read(struct qca8k_priv *priv, - - qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); - -- ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL, -+ ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); - if (ret) - goto exit; - - val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); -- val &= QCA8K_MDIO_MASTER_DATA_MASK; - - exit: -+ /* even if the busy_wait timeouts try to clear the MASTER_EN */ -+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); -+ - mutex_unlock(&priv->bus->mdio_lock); - - if (val >= 0) - val &= QCA8K_MDIO_MASTER_DATA_MASK; - -- /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, -- QCA8K_MDIO_MASTER_EN); -- - return val; - } - -@@ -746,7 +738,14 @@ qca8k_phy_write(struct dsa_switch *ds, i - { - struct qca8k_priv *priv = ds->priv; - -- return qca8k_mdio_write(priv, port, regnum, data); -+ /* Check if the legacy mapping should be used and the -+ * port is not correctly mapped to the right PHY in the -+ * devicetree -+ */ -+ if (priv->legacy_phy_port_mapping) -+ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; -+ -+ return qca8k_mdio_write(priv->bus, port, regnum, data); - } - - static int -@@ -755,7 +754,14 @@ qca8k_phy_read(struct dsa_switch *ds, in - struct qca8k_priv *priv = ds->priv; - int ret; - -- ret = qca8k_mdio_read(priv, port, regnum); -+ /* Check if the legacy mapping should be used and the -+ * port is not correctly mapped to the right PHY in the -+ * devicetree -+ */ -+ if (priv->legacy_phy_port_mapping) -+ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; -+ -+ ret = qca8k_mdio_read(priv->bus, port, regnum); - - if (ret < 0) - return 0xffff; -@@ -764,10 +770,37 @@ qca8k_phy_read(struct dsa_switch *ds, in - } - - static int -+qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio) -+{ -+ struct dsa_switch *ds = priv->ds; -+ struct mii_bus *bus; -+ -+ bus = devm_mdiobus_alloc(ds->dev); -+ -+ if (!bus) -+ return -ENOMEM; -+ -+ bus->priv = (void *)priv; -+ bus->name = "qca8k slave mii"; -+ bus->read = qca8k_mdio_read; -+ bus->write = qca8k_mdio_write; -+ snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d", -+ ds->index); -+ -+ bus->parent = ds->dev; -+ bus->phy_mask = ~ds->phys_mii_mask; -+ -+ ds->slave_mii_bus = bus; -+ -+ return devm_of_mdiobus_register(priv->dev, bus, mdio); -+} -+ -+static int - qca8k_setup_mdio_bus(struct qca8k_priv *priv) - { - u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg; -- struct device_node *ports, *port; -+ struct device_node *ports, *port, *mdio; -+ phy_interface_t mode; - int err; - - ports = of_get_child_by_name(priv->dev->of_node, "ports"); -@@ -788,7 +821,10 @@ qca8k_setup_mdio_bus(struct qca8k_priv * - if (!dsa_is_user_port(priv->ds, reg)) - continue; - -- if (of_property_read_bool(port, "phy-handle")) -+ of_get_phy_mode(port, &mode); -+ -+ if (of_property_read_bool(port, "phy-handle") && -+ mode != PHY_INTERFACE_MODE_INTERNAL) - external_mdio_mask |= BIT(reg); - else - internal_mdio_mask |= BIT(reg); -@@ -825,8 +861,23 @@ qca8k_setup_mdio_bus(struct qca8k_priv * - QCA8K_MDIO_MASTER_EN); - } - -+ /* Check if the devicetree declare the port:phy mapping */ -+ mdio = of_get_child_by_name(priv->dev->of_node, "mdio"); -+ if (of_device_is_available(mdio)) { -+ err = qca8k_mdio_register(priv, mdio); -+ if (err) -+ of_node_put(mdio); -+ -+ return err; -+ } -+ -+ /* If a mapping can't be found the legacy mapping is used, -+ * using the qca8k_port_to_phy function -+ */ -+ priv->legacy_phy_port_mapping = true; - priv->ops.phy_read = qca8k_phy_read; - priv->ops.phy_write = qca8k_phy_write; -+ - return 0; - } - -@@ -1212,7 +1263,8 @@ qca8k_phylink_validate(struct dsa_switch - case 5: - /* Internal PHY */ - if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_GMII) -+ state->interface != PHY_INTERFACE_MODE_GMII && -+ state->interface != PHY_INTERFACE_MODE_INTERNAL) - goto unsupported; - break; - case 6: /* 2nd CPU port / external PHY */ ---- a/drivers/net/dsa/qca8k.h -+++ b/drivers/net/dsa/qca8k.h -@@ -255,6 +255,7 @@ struct qca8k_priv { - u8 switch_revision; - u8 rgmii_tx_delay; - u8 rgmii_rx_delay; -+ bool legacy_phy_port_mapping; - struct regmap *regmap; - struct mii_bus *bus; - struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS]; diff --git a/target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch b/target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch deleted file mode 100644 index 6db01b4b41..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-21-devicetree-bindings-dsa-qca8k-Document-internal-mdio.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0c994a28e7518f098c84a3049cb2915780db873a Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:11 +0200 -Subject: [PATCH] devicetree: bindings: dsa: qca8k: Document internal mdio - definition - -Document new way of declare mapping of internal PHY to port. -The new implementation directly declare the PHY connected to the port -by adding a node in the switch node. The driver detect this and register -an internal mdiobus using the mapping defined in the mdio node. - -Signed-off-by: Ansuel Smith -Reviewed-by: Rob Herring -Signed-off-by: David S. Miller ---- - .../devicetree/bindings/net/dsa/qca8k.txt | 39 +++++++++++++++++++ - 1 file changed, 39 insertions(+) - ---- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt -+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt -@@ -21,6 +21,10 @@ described in dsa/dsa.txt. If the QCA8K s - mdio-bus each subnode describing a port needs to have a valid phandle - referencing the internal PHY it is connected to. This is because there's no - N:N mapping of port and PHY id. -+To declare the internal mdio-bus configuration, declare a mdio node in the -+switch node and declare the phandle for the port referencing the internal -+PHY is connected to. In this config a internal mdio-bus is registered and -+the mdio MASTER is used as communication. - - Don't use mixed external and internal mdio-bus configurations, as this is - not supported by the hardware. -@@ -150,26 +154,61 @@ for the internal master mdio-bus configu - port@1 { - reg = <1>; - label = "lan1"; -+ phy-mode = "internal"; -+ phy-handle = <&phy_port1>; - }; - - port@2 { - reg = <2>; - label = "lan2"; -+ phy-mode = "internal"; -+ phy-handle = <&phy_port2>; - }; - - port@3 { - reg = <3>; - label = "lan3"; -+ phy-mode = "internal"; -+ phy-handle = <&phy_port3>; - }; - - port@4 { - reg = <4>; - label = "lan4"; -+ phy-mode = "internal"; -+ phy-handle = <&phy_port4>; - }; - - port@5 { - reg = <5>; - label = "wan"; -+ phy-mode = "internal"; -+ phy-handle = <&phy_port5>; -+ }; -+ }; -+ -+ mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ phy_port1: phy@0 { -+ reg = <0>; -+ }; -+ -+ phy_port2: phy@1 { -+ reg = <1>; -+ }; -+ -+ phy_port3: phy@2 { -+ reg = <2>; -+ }; -+ -+ phy_port4: phy@3 { -+ reg = <3>; -+ }; -+ -+ phy_port5: phy@4 { -+ reg = <4>; - }; - }; - }; diff --git a/target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch b/target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch deleted file mode 100644 index da8d5b3462..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-22-net-dsa-qca8k-improve-internal-mdio-read-write-bus-a.patch +++ /dev/null @@ -1,95 +0,0 @@ -From b7ebac354d54f1657bb89b7a7ca149db50203e6a Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:12 +0200 -Subject: [PATCH] net: dsa: qca8k: improve internal mdio read/write bus access - -Improve the internal mdio read/write bus access by caching the value -without accessing it for every read/write. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 28 +++++++++++++++------------- - 1 file changed, 15 insertions(+), 13 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -655,6 +655,7 @@ static int - qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) - { - struct qca8k_priv *priv = salve_bus->priv; -+ struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - int ret; -@@ -669,22 +670,22 @@ qca8k_mdio_write(struct mii_bus *salve_b - - qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- ret = qca8k_set_page(priv->bus, page); -+ ret = qca8k_set_page(bus, page); - if (ret) - goto exit; - -- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); -+ qca8k_mii_write32(bus, 0x10 | r2, r1, val); - -- ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, -+ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); -+ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); - -- mutex_unlock(&priv->bus->mdio_lock); -+ mutex_unlock(&bus->mdio_lock); - - return ret; - } -@@ -693,6 +694,7 @@ static int - qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) - { - struct qca8k_priv *priv = salve_bus->priv; -+ struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - int ret; -@@ -706,26 +708,26 @@ qca8k_mdio_read(struct mii_bus *salve_bu - - qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page); - -- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- ret = qca8k_set_page(priv->bus, page); -+ ret = qca8k_set_page(bus, page); - if (ret) - goto exit; - -- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val); -+ qca8k_mii_write32(bus, 0x10 | r2, r1, val); - -- ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL, -+ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, - QCA8K_MDIO_MASTER_BUSY); - if (ret) - goto exit; - -- val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1); -+ val = qca8k_mii_read32(bus, 0x10 | r2, r1); - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0); -+ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); - -- mutex_unlock(&priv->bus->mdio_lock); -+ mutex_unlock(&bus->mdio_lock); - - if (val >= 0) - val &= QCA8K_MDIO_MASTER_DATA_MASK; diff --git a/target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch b/target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch deleted file mode 100644 index 1179cf152d..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-23-net-dsa-qca8k-pass-switch_revision-info-to-phy-dev_f.patch +++ /dev/null @@ -1,48 +0,0 @@ -From a46aec02bc06ac2c33f326339e4ef88c735dc30d Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:13 +0200 -Subject: [PATCH] net: dsa: qca8k: pass switch_revision info to phy dev_flags - -Define get_phy_flags to pass switch_Revision needed to tweak the -internal PHY with debug values based on the revision. - -Signed-off-by: Ansuel Smith -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1740,6 +1740,22 @@ qca8k_port_vlan_del(struct dsa_switch *d - return ret; - } - -+static u32 qca8k_get_phy_flags(struct dsa_switch *ds, int port) -+{ -+ struct qca8k_priv *priv = ds->priv; -+ -+ /* Communicate to the phy internal driver the switch revision. -+ * Based on the switch revision different values needs to be -+ * set to the dbg and mmd reg on the phy. -+ * The first 2 bit are used to communicate the switch revision -+ * to the phy driver. -+ */ -+ if (port > 0 && port < 6) -+ return priv->switch_revision; -+ -+ return 0; -+} -+ - static enum dsa_tag_protocol - qca8k_get_tag_protocol(struct dsa_switch *ds, int port, - enum dsa_tag_protocol mp) -@@ -1774,6 +1790,7 @@ static const struct dsa_switch_ops qca8k - .phylink_mac_config = qca8k_phylink_mac_config, - .phylink_mac_link_down = qca8k_phylink_mac_link_down, - .phylink_mac_link_up = qca8k_phylink_mac_link_up, -+ .get_phy_flags = qca8k_get_phy_flags, - }; - - static int qca8k_read_switch_id(struct qca8k_priv *priv) diff --git a/target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch b/target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch deleted file mode 100644 index 20325f564d..0000000000 --- a/target/linux/generic/backport-5.15/735-v5.14-25-net-phy-add-support-for-qca8k-switch-internal-PHY-in.patch +++ /dev/null @@ -1,229 +0,0 @@ -From 272833b9b3b3969be7a91839121d86662c8c4253 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Fri, 14 May 2021 23:00:15 +0200 -Subject: [PATCH] net: phy: add support for qca8k switch internal PHY in at803x - -Since the at803x share the same regs, it's assumed they are based on the -same implementation. Make it part of the at803x PHY driver to skip -having redudant code. -Add initial support for qca8k internal PHYs. The internal PHYs requires -special mmd and debug values to be set based on the switch revision -passwd using the dev_flags. Supports output of idle, receive and eee_wake -errors stats. -Some debug values sets can't be translated as the documentation lacks any -reference about them. - -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 5 +- - drivers/net/phy/at803x.c | 132 ++++++++++++++++++++++++++++++++++++++- - 2 files changed, 134 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -235,10 +235,11 @@ config NXP_TJA11XX_PHY - Currently supports the NXP TJA1100 and TJA1101 PHY. - - config AT803X_PHY -- tristate "Qualcomm Atheros AR803X PHYs" -+ tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" - depends on REGULATOR - help -- Currently supports the AR8030, AR8031, AR8033 and AR8035 model -+ Currently supports the AR8030, AR8031, AR8033, AR8035 and internal -+ QCA8337(Internal qca8k PHY) model - - config QSEMI_PHY - tristate "Quality Semiconductor PHYs" ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -92,10 +92,16 @@ - #define AT803X_DEBUG_REG_5 0x05 - #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) - -+#define AT803X_DEBUG_REG_3C 0x3C -+ -+#define AT803X_DEBUG_REG_3D 0x3D -+ - #define AT803X_DEBUG_REG_1F 0x1F - #define AT803X_DEBUG_PLL_ON BIT(2) - #define AT803X_DEBUG_RGMII_1V8 BIT(3) - -+#define MDIO_AZ_DEBUG 0x800D -+ - /* AT803x supports either the XTAL input pad, an internal PLL or the - * DSP as clock reference for the clock output pad. The XTAL reference - * is only used for 25 MHz output, all other frequencies need the PLL. -@@ -142,10 +148,34 @@ - #define AT803X_PAGE_FIBER 0 - #define AT803X_PAGE_COPPER 1 - -+#define QCA8327_PHY_ID 0x004dd034 -+#define QCA8337_PHY_ID 0x004dd036 -+#define QCA8K_PHY_ID_MASK 0xffffffff -+ -+#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) -+ - MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi"); - MODULE_LICENSE("GPL"); - -+enum stat_access_type { -+ PHY, -+ MMD -+}; -+ -+struct at803x_hw_stat { -+ const char *string; -+ u8 reg; -+ u32 mask; -+ enum stat_access_type access_type; -+}; -+ -+static struct at803x_hw_stat at803x_hw_stats[] = { -+ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, -+ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, -+ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, -+}; -+ - struct at803x_priv { - int flags; - #define AT803X_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */ -@@ -154,6 +184,7 @@ struct at803x_priv { - struct regulator_dev *vddio_rdev; - struct regulator_dev *vddh_rdev; - struct regulator *vddio; -+ u64 stats[ARRAY_SIZE(at803x_hw_stats)]; - }; - - struct at803x_context { -@@ -165,6 +196,17 @@ struct at803x_context { - u16 led_control; - }; - -+static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) -+{ -+ int ret; -+ -+ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); -+ if (ret < 0) -+ return ret; -+ -+ return phy_write(phydev, AT803X_DEBUG_DATA, data); -+} -+ - static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) - { - int ret; -@@ -327,6 +369,53 @@ static void at803x_get_wol(struct phy_de - wol->wolopts |= WAKE_MAGIC; - } - -+static int at803x_get_sset_count(struct phy_device *phydev) -+{ -+ return ARRAY_SIZE(at803x_hw_stats); -+} -+ -+static void at803x_get_strings(struct phy_device *phydev, u8 *data) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) { -+ strscpy(data + i * ETH_GSTRING_LEN, -+ at803x_hw_stats[i].string, ETH_GSTRING_LEN); -+ } -+} -+ -+static u64 at803x_get_stat(struct phy_device *phydev, int i) -+{ -+ struct at803x_hw_stat stat = at803x_hw_stats[i]; -+ struct at803x_priv *priv = phydev->priv; -+ int val; -+ u64 ret; -+ -+ if (stat.access_type == MMD) -+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); -+ else -+ val = phy_read(phydev, stat.reg); -+ -+ if (val < 0) { -+ ret = U64_MAX; -+ } else { -+ val = val & stat.mask; -+ priv->stats[i] += val; -+ ret = priv->stats[i]; -+ } -+ -+ return ret; -+} -+ -+static void at803x_get_stats(struct phy_device *phydev, -+ struct ethtool_stats *stats, u64 *data) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) -+ data[i] = at803x_get_stat(phydev, i); -+} -+ - static int at803x_suspend(struct phy_device *phydev) - { - int value; -@@ -1102,6 +1191,34 @@ static int at803x_cable_test_start(struc - return 0; - } - -+static int qca83xx_config_init(struct phy_device *phydev) -+{ -+ u8 switch_revision; -+ -+ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; -+ -+ switch (switch_revision) { -+ case 1: -+ /* For 100M waveform */ -+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_0, 0x02ea); -+ /* Turn on Gigabit clock */ -+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x68a0); -+ break; -+ -+ case 2: -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); -+ fallthrough; -+ case 4: -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); -+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x6860); -+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_5, 0x2c46); -+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); -+ break; -+ } -+ -+ return 0; -+} -+ - static struct phy_driver at803x_driver[] = { - { - /* Qualcomm Atheros AR8035 */ -@@ -1198,7 +1315,20 @@ static struct phy_driver at803x_driver[] - .read_status = at803x_read_status, - .soft_reset = genphy_soft_reset, - .config_aneg = at803x_config_aneg, --} }; -+}, { -+ /* QCA8337 */ -+ .phy_id = QCA8337_PHY_ID, -+ .phy_id_mask = QCA8K_PHY_ID_MASK, -+ .name = "QCA PHY 8337", -+ /* PHY_GBIT_FEATURES */ -+ .probe = at803x_probe, -+ .flags = PHY_IS_INTERNAL, -+ .config_init = qca83xx_config_init, -+ .soft_reset = genphy_soft_reset, -+ .get_sset_count = at803x_get_sset_count, -+ .get_strings = at803x_get_strings, -+ .get_stats = at803x_get_stats, -+}, }; - - module_phy_driver(at803x_driver); - diff --git a/target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch b/target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch deleted file mode 100644 index a68e3b1821..0000000000 --- a/target/linux/generic/backport-5.15/736-v5.14-net-dsa-qca8k-fix-missing-unlock-on-error-in-qca8k-vlan.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0d56e5c191b197e1d30a0a4c92628836dafced0f Mon Sep 17 00:00:00 2001 -From: Wei Yongjun -Date: Tue, 18 May 2021 11:24:13 +0000 -Subject: [PATCH] net: dsa: qca8k: fix missing unlock on error in - qca8k_vlan_(add|del) - -Add the missing unlock before return from function qca8k_vlan_add() -and qca8k_vlan_del() in the error handling case. - -Fixes: 028f5f8ef44f ("net: dsa: qca8k: handle error with qca8k_read operation") -Reported-by: Hulk Robot -Signed-off-by: Wei Yongjun -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 16 ++++++++++------ - 1 file changed, 10 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -506,8 +506,10 @@ qca8k_vlan_add(struct qca8k_priv *priv, - goto out; - - reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); -- if (reg < 0) -- return reg; -+ if (reg < 0) { -+ ret = reg; -+ goto out; -+ } - reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; - reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); - if (untagged) -@@ -519,7 +521,7 @@ qca8k_vlan_add(struct qca8k_priv *priv, - - ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); - if (ret) -- return ret; -+ goto out; - ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); - - out: -@@ -541,8 +543,10 @@ qca8k_vlan_del(struct qca8k_priv *priv, - goto out; - - reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); -- if (reg < 0) -- return reg; -+ if (reg < 0) { -+ ret = reg; -+ goto out; -+ } - reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); - reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << - QCA8K_VTU_FUNC0_EG_MODE_S(port); -@@ -564,7 +568,7 @@ qca8k_vlan_del(struct qca8k_priv *priv, - } else { - ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); - if (ret) -- return ret; -+ goto out; - ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid); - } - diff --git a/target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch b/target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch deleted file mode 100644 index 451b0e9446..0000000000 --- a/target/linux/generic/backport-5.15/737-v5.14-01-net-dsa-qca8k-check-return-value-of-read-functions-c.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 7c9896e37807862e276064dd9331860f5d27affc Mon Sep 17 00:00:00 2001 -From: Yang Yingliang -Date: Sat, 29 May 2021 11:04:38 +0800 -Subject: [PATCH] net: dsa: qca8k: check return value of read functions - correctly - -Current return type of qca8k_mii_read32() and qca8k_read() are -unsigned, it can't be negative, so the return value check is -unuseful. For check the return value correctly, change return -type of the read functions and add a output parameter to store -the read value. - -Signed-off-by: Yang Yingliang -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/qca8k.c | 130 +++++++++++++++++++--------------------- - 1 file changed, 60 insertions(+), 70 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -89,26 +89,26 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u - *page = regaddr & 0x3ff; - } - --static u32 --qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum) -+static int -+qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) - { -- u32 val; - int ret; - - ret = bus->read(bus, phy_id, regnum); - if (ret >= 0) { -- val = ret; -+ *val = ret; - ret = bus->read(bus, phy_id, regnum + 1); -- val |= ret << 16; -+ *val |= ret << 16; - } - - if (ret < 0) { - dev_err_ratelimited(&bus->dev, - "failed to read qca8k 32bit register\n"); -+ *val = 0; - return ret; - } - -- return val; -+ return 0; - } - - static void -@@ -148,26 +148,26 @@ qca8k_set_page(struct mii_bus *bus, u16 - return 0; - } - --static u32 --qca8k_read(struct qca8k_priv *priv, u32 reg) -+static int -+qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) - { - struct mii_bus *bus = priv->bus; - u16 r1, r2, page; -- u32 val; -+ int ret; - - qca8k_split_addr(reg, &r1, &r2, &page); - - mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); - -- val = qca8k_set_page(bus, page); -- if (val < 0) -+ ret = qca8k_set_page(bus, page); -+ if (ret < 0) - goto exit; - -- val = qca8k_mii_read32(bus, 0x10 | r2, r1); -+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, val); - - exit: - mutex_unlock(&bus->mdio_lock); -- return val; -+ return ret; - } - - static int -@@ -208,11 +208,9 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r - if (ret < 0) - goto exit; - -- val = qca8k_mii_read32(bus, 0x10 | r2, r1); -- if (val < 0) { -- ret = val; -+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); -+ if (ret < 0) - goto exit; -- } - - val &= ~mask; - val |= write_val; -@@ -240,15 +238,8 @@ static int - qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) - { - struct qca8k_priv *priv = (struct qca8k_priv *)ctx; -- int ret; -- -- ret = qca8k_read(priv, reg); -- if (ret < 0) -- return ret; -- -- *val = ret; - -- return 0; -+ return qca8k_read(priv, reg, val); - } - - static int -@@ -296,18 +287,18 @@ static struct regmap_config qca8k_regmap - static int - qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) - { -+ int ret, ret1; - u32 val; -- int ret; - -- ret = read_poll_timeout(qca8k_read, val, !(val & mask), -+ ret = read_poll_timeout(qca8k_read, ret1, !(val & mask), - 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -- priv, reg); -+ priv, reg, &val); - - /* Check if qca8k_read has failed for a different reason - * before returning -ETIMEDOUT - */ -- if (ret < 0 && val < 0) -- return val; -+ if (ret < 0 && ret1 < 0) -+ return ret1; - - return ret; - } -@@ -316,13 +307,13 @@ static int - qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) - { - u32 reg[4], val; -- int i; -+ int i, ret; - - /* load the ARL table into an array */ - for (i = 0; i < 4; i++) { -- val = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4)); -- if (val < 0) -- return val; -+ ret = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4), &val); -+ if (ret < 0) -+ return ret; - - reg[i] = val; - } -@@ -396,9 +387,9 @@ qca8k_fdb_access(struct qca8k_priv *priv - - /* Check for table full violation when adding an entry */ - if (cmd == QCA8K_FDB_LOAD) { -- reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC); -- if (reg < 0) -- return reg; -+ ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, ®); -+ if (ret < 0) -+ return ret; - if (reg & QCA8K_ATU_FUNC_FULL) - return -1; - } -@@ -477,9 +468,9 @@ qca8k_vlan_access(struct qca8k_priv *pri - - /* Check for table full violation when adding an entry */ - if (cmd == QCA8K_VLAN_LOAD) { -- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1); -- if (reg < 0) -- return reg; -+ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, ®); -+ if (ret < 0) -+ return ret; - if (reg & QCA8K_VTU_FUNC1_FULL) - return -ENOMEM; - } -@@ -505,11 +496,9 @@ qca8k_vlan_add(struct qca8k_priv *priv, - if (ret < 0) - goto out; - -- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); -- if (reg < 0) { -- ret = reg; -+ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); -+ if (ret < 0) - goto out; -- } - reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; - reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port)); - if (untagged) -@@ -542,11 +531,9 @@ qca8k_vlan_del(struct qca8k_priv *priv, - if (ret < 0) - goto out; - -- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0); -- if (reg < 0) { -- ret = reg; -+ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); -+ if (ret < 0) - goto out; -- } - reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port)); - reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT << - QCA8K_VTU_FUNC0_EG_MODE_S(port); -@@ -638,19 +625,19 @@ qca8k_mdio_busy_wait(struct mii_bus *bus - { - u16 r1, r2, page; - u32 val; -- int ret; -+ int ret, ret1; - - qca8k_split_addr(reg, &r1, &r2, &page); - -- ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0, -+ ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0, - QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, -- bus, 0x10 | r2, r1); -+ bus, 0x10 | r2, r1, &val); - - /* Check if qca8k_read has failed for a different reason - * before returnting -ETIMEDOUT - */ -- if (ret < 0 && val < 0) -- return val; -+ if (ret < 0 && ret1 < 0) -+ return ret1; - - return ret; - } -@@ -725,7 +712,7 @@ qca8k_mdio_read(struct mii_bus *salve_bu - if (ret) - goto exit; - -- val = qca8k_mii_read32(bus, 0x10 | r2, r1); -+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val); - - exit: - /* even if the busy_wait timeouts try to clear the MASTER_EN */ -@@ -733,10 +720,10 @@ exit: - - mutex_unlock(&bus->mdio_lock); - -- if (val >= 0) -- val &= QCA8K_MDIO_MASTER_DATA_MASK; -+ if (ret >= 0) -+ ret = val & QCA8K_MDIO_MASTER_DATA_MASK; - -- return val; -+ return ret; - } - - static int -@@ -1211,7 +1198,7 @@ qca8k_phylink_mac_config(struct dsa_swit - qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); - - /* Enable/disable SerDes auto-negotiation as necessary */ -- val = qca8k_read(priv, QCA8K_REG_PWS); -+ qca8k_read(priv, QCA8K_REG_PWS, &val); - if (phylink_autoneg_inband(mode)) - val &= ~QCA8K_PWS_SERDES_AEN_DIS; - else -@@ -1219,7 +1206,7 @@ qca8k_phylink_mac_config(struct dsa_swit - qca8k_write(priv, QCA8K_REG_PWS, val); - - /* Configure the SGMII parameters */ -- val = qca8k_read(priv, QCA8K_REG_SGMII_CTRL); -+ qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); - - val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | - QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD; -@@ -1314,10 +1301,11 @@ qca8k_phylink_mac_link_state(struct dsa_ - { - struct qca8k_priv *priv = ds->priv; - u32 reg; -+ int ret; - -- reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port)); -- if (reg < 0) -- return reg; -+ ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), ®); -+ if (ret < 0) -+ return ret; - - state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); - state->an_complete = state->link; -@@ -1419,19 +1407,20 @@ qca8k_get_ethtool_stats(struct dsa_switc - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - const struct qca8k_mib_desc *mib; - u32 reg, i, val; -- u64 hi; -+ u64 hi = 0; -+ int ret; - - for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { - mib = &ar8327_mib[i]; - reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; - -- val = qca8k_read(priv, reg); -- if (val < 0) -+ ret = qca8k_read(priv, reg, &val); -+ if (ret < 0) - continue; - - if (mib->size == 2) { -- hi = qca8k_read(priv, reg + 4); -- if (hi < 0) -+ ret = qca8k_read(priv, reg + 4, (u32 *)&hi); -+ if (ret < 0) - continue; - } - -@@ -1459,7 +1448,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds, - int ret; - - mutex_lock(&priv->reg_mutex); -- reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL); -+ ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®); - if (reg < 0) { - ret = reg; - goto exit; -@@ -1802,14 +1791,15 @@ static int qca8k_read_switch_id(struct q - const struct qca8k_match_data *data; - u32 val; - u8 id; -+ int ret; - - /* get the switches ID from the compatible */ - data = of_device_get_match_data(priv->dev); - if (!data) - return -ENODEV; - -- val = qca8k_read(priv, QCA8K_REG_MASK_CTRL); -- if (val < 0) -+ ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val); -+ if (ret < 0) - return -ENODEV; - - id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK); diff --git a/target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch b/target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch deleted file mode 100644 index d20da5b85e..0000000000 --- a/target/linux/generic/backport-5.15/737-v5.14-02-net-dsa-qca8k-add-missing-check-return-value-in-qca8.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 9fe99de01440d9ede74d447ac76e9c445d8daae9 Mon Sep 17 00:00:00 2001 -From: Yang Yingliang -Date: Sat, 29 May 2021 11:04:39 +0800 -Subject: [PATCH] net: dsa: qca8k: add missing check return value in - qca8k_phylink_mac_config() - -Now we can check qca8k_read() return value correctly, so if -it fails, we need return directly. - -Signed-off-by: Yang Yingliang -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/qca8k.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1128,6 +1128,7 @@ qca8k_phylink_mac_config(struct dsa_swit - { - struct qca8k_priv *priv = ds->priv; - u32 reg, val; -+ int ret; - - switch (port) { - case 0: /* 1st CPU port */ -@@ -1198,7 +1199,9 @@ qca8k_phylink_mac_config(struct dsa_swit - qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); - - /* Enable/disable SerDes auto-negotiation as necessary */ -- qca8k_read(priv, QCA8K_REG_PWS, &val); -+ ret = qca8k_read(priv, QCA8K_REG_PWS, &val); -+ if (ret) -+ return; - if (phylink_autoneg_inband(mode)) - val &= ~QCA8K_PWS_SERDES_AEN_DIS; - else -@@ -1206,7 +1209,9 @@ qca8k_phylink_mac_config(struct dsa_swit - qca8k_write(priv, QCA8K_REG_PWS, val); - - /* Configure the SGMII parameters */ -- qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); -+ ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); -+ if (ret) -+ return; - - val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX | - QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD; diff --git a/target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch b/target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch deleted file mode 100644 index aed97d0549..0000000000 --- a/target/linux/generic/backport-5.15/738-v5.14-01-net-dsa-qca8k-fix-an-endian-bug-in-qca8k-get-ethtool.patch +++ /dev/null @@ -1,47 +0,0 @@ -From aa3d020b22cb844ab7bdbb9e5d861a64666e2b74 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 9 Jun 2021 12:52:12 +0300 -Subject: [PATCH] net: dsa: qca8k: fix an endian bug in - qca8k_get_ethtool_stats() - -The "hi" variable is a u64 but the qca8k_read() writes to the top 32 -bits of it. That will work on little endian systems but it's a bit -subtle. It's cleaner to make declare "hi" as a u32. We will still need -to cast it when we shift it later on in the function but that's fine. - -Fixes: 7c9896e37807 ("net: dsa: qca8k: check return value of read functions correctly") -Signed-off-by: Dan Carpenter -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1412,7 +1412,7 @@ qca8k_get_ethtool_stats(struct dsa_switc - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; - const struct qca8k_mib_desc *mib; - u32 reg, i, val; -- u64 hi = 0; -+ u32 hi = 0; - int ret; - - for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) { -@@ -1424,14 +1424,14 @@ qca8k_get_ethtool_stats(struct dsa_switc - continue; - - if (mib->size == 2) { -- ret = qca8k_read(priv, reg + 4, (u32 *)&hi); -+ ret = qca8k_read(priv, reg + 4, &hi); - if (ret < 0) - continue; - } - - data[i] = val; - if (mib->size == 2) -- data[i] |= hi << 32; -+ data[i] |= (u64)hi << 32; - } - } - diff --git a/target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch b/target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch deleted file mode 100644 index c58f79cd8b..0000000000 --- a/target/linux/generic/backport-5.15/738-v5.14-02-net-dsa-qca8k-check-the-correct-variable-in-qca8k-se.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 3d0167f2a627528032821cdeb78b4eab0510460f Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Wed, 9 Jun 2021 12:53:03 +0300 -Subject: [PATCH] net: dsa: qca8k: check the correct variable in - qca8k_set_mac_eee() - -This code check "reg" but "ret" was intended so the error handling will -never trigger. - -Fixes: 7c9896e37807 ("net: dsa: qca8k: check return value of read functions correctly") -Signed-off-by: Dan Carpenter -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -1454,10 +1454,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds, - - mutex_lock(&priv->reg_mutex); - ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®); -- if (reg < 0) { -- ret = reg; -+ if (ret < 0) - goto exit; -- } - - if (eee->eee_enabled) - reg |= lpi_en; diff --git a/target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch b/target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch deleted file mode 100644 index 1e293d3a0b..0000000000 --- a/target/linux/generic/backport-5.15/739-v5.15-net-dsa-qca8k-fix-kernel-panic-with-legacy-mdio-mapping.patch +++ /dev/null @@ -1,80 +0,0 @@ -From ce062a0adbfe933b1932235fdfd874c4c91d1bb0 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Sat, 11 Sep 2021 17:50:09 +0200 -Subject: net: dsa: qca8k: fix kernel panic with legacy mdio mapping - -When the mdio legacy mapping is used the mii_bus priv registered by DSA -refer to the dsa switch struct instead of the qca8k_priv struct and -causes a kernel panic. Create dedicated function when the internal -dedicated mdio driver is used to properly handle the 2 different -implementation. - -Fixes: 759bafb8a322 ("net: dsa: qca8k: add support for internal phy and internal mdio") -Signed-off-by: Ansuel Smith -Signed-off-by: David S. Miller ---- - drivers/net/dsa/qca8k.c | 30 ++++++++++++++++++++++-------- - 1 file changed, 22 insertions(+), 8 deletions(-) - ---- a/drivers/net/dsa/qca8k.c -+++ b/drivers/net/dsa/qca8k.c -@@ -643,10 +643,8 @@ qca8k_mdio_busy_wait(struct mii_bus *bus - } - - static int --qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data) -+qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) - { -- struct qca8k_priv *priv = salve_bus->priv; -- struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - int ret; -@@ -682,10 +680,8 @@ exit: - } - - static int --qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum) -+qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) - { -- struct qca8k_priv *priv = salve_bus->priv; -- struct mii_bus *bus = priv->bus; - u16 r1, r2, page; - u32 val; - int ret; -@@ -727,6 +723,24 @@ exit: - } - - static int -+qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data) -+{ -+ struct qca8k_priv *priv = slave_bus->priv; -+ struct mii_bus *bus = priv->bus; -+ -+ return qca8k_mdio_write(bus, phy, regnum, data); -+} -+ -+static int -+qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) -+{ -+ struct qca8k_priv *priv = slave_bus->priv; -+ struct mii_bus *bus = priv->bus; -+ -+ return qca8k_mdio_read(bus, phy, regnum); -+} -+ -+static int - qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) - { - struct qca8k_priv *priv = ds->priv; -@@ -775,8 +789,8 @@ qca8k_mdio_register(struct qca8k_priv *p - - bus->priv = (void *)priv; - bus->name = "qca8k slave mii"; -- bus->read = qca8k_mdio_read; -- bus->write = qca8k_mdio_write; -+ bus->read = qca8k_internal_mdio_read; -+ bus->write = qca8k_internal_mdio_write; - snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d", - ds->index); - diff --git a/target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch b/target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch deleted file mode 100644 index 91cf55b18a..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0001-net-dsa-b53-Add-debug-prints-in-b53_vlan_enable.patch +++ /dev/null @@ -1,65 +0,0 @@ -From ee47ed08d75e8f16b3cf882061ee19c2ea19dd6c Mon Sep 17 00:00:00 2001 -From: Florian Fainelli -Date: Wed, 10 Mar 2021 10:52:26 -0800 -Subject: [PATCH] net: dsa: b53: Add debug prints in b53_vlan_enable() - -Having dynamic debug prints in b53_vlan_enable() has been helpful to -uncover a recent but update the function to indicate the port being -configured (or -1 for initial setup) and include the global VLAN enabled -and VLAN filtering enable status. - -Signed-off-by: Florian Fainelli -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_common.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -349,7 +349,7 @@ static void b53_set_forwarding(struct b5 - b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); - } - --static void b53_enable_vlan(struct b53_device *dev, bool enable, -+static void b53_enable_vlan(struct b53_device *dev, int port, bool enable, - bool enable_filtering) - { - u8 mgmt, vc0, vc1, vc4 = 0, vc5; -@@ -431,6 +431,9 @@ static void b53_enable_vlan(struct b53_d - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); - - dev->vlan_enabled = enable; -+ -+ dev_dbg(dev->dev, "Port %d VLAN enabled: %d, filtering: %d\n", -+ port, enable, enable_filtering); - } - - static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100) -@@ -708,7 +711,7 @@ int b53_configure_vlan(struct dsa_switch - b53_do_vlan_op(dev, VTA_CMD_CLEAR); - } - -- b53_enable_vlan(dev, dev->vlan_enabled, ds->vlan_filtering); -+ b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering); - - b53_for_each_port(dev, i) - b53_write16(dev, B53_VLAN_PAGE, -@@ -1390,7 +1393,7 @@ int b53_vlan_filtering(struct dsa_switch - if (switchdev_trans_ph_prepare(trans)) - return 0; - -- b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); -+ b53_enable_vlan(dev, port, dev->vlan_enabled, vlan_filtering); - - return 0; - } -@@ -1415,7 +1418,7 @@ int b53_vlan_prepare(struct dsa_switch * - if (vlan->vid_end >= dev->num_vlans) - return -ERANGE; - -- b53_enable_vlan(dev, true, ds->vlan_filtering); -+ b53_enable_vlan(dev, port, true, ds->vlan_filtering); - - return 0; - } diff --git a/target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch b/target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch deleted file mode 100644 index 56579b2d36..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0002-net-dsa-b53-spi-allow-device-tree-probing.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 6d16eadab6db0c1d61e59fee7ed1ecc2d10269be Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 15 Mar 2021 15:14:23 +0100 -Subject: [PATCH] net: dsa: b53: spi: allow device tree probing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add missing of_match_table to allow device tree probing. - -Signed-off-by: Álvaro Fernández Rojas -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_spi.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/net/dsa/b53/b53_spi.c -+++ b/drivers/net/dsa/b53/b53_spi.c -@@ -324,9 +324,22 @@ static int b53_spi_remove(struct spi_dev - return 0; - } - -+static const struct of_device_id b53_spi_of_match[] = { -+ { .compatible = "brcm,bcm5325" }, -+ { .compatible = "brcm,bcm5365" }, -+ { .compatible = "brcm,bcm5395" }, -+ { .compatible = "brcm,bcm5397" }, -+ { .compatible = "brcm,bcm5398" }, -+ { .compatible = "brcm,bcm53115" }, -+ { .compatible = "brcm,bcm53125" }, -+ { .compatible = "brcm,bcm53128" }, -+ { /* sentinel */ } -+}; -+ - static struct spi_driver b53_spi_driver = { - .driver = { - .name = "b53-switch", -+ .of_match_table = b53_spi_of_match, - }, - .probe = b53_spi_probe, - .remove = b53_spi_remove, diff --git a/target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch b/target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch deleted file mode 100644 index 99eced1b6a..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0003-net-dsa-b53-relax-is63xx-condition.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ad426d7d966b525b73ed5a1842dd830312bbba71 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 Mar 2021 09:42:01 +0100 -Subject: [PATCH] net: dsa: b53: relax is63xx() condition -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM63xx switches are present on bcm63xx and bmips devices. - -Signed-off-by: Álvaro Fernández Rojas -Acked-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_priv.h | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -186,11 +186,7 @@ static inline int is531x5(struct b53_dev - - static inline int is63xx(struct b53_device *dev) - { --#ifdef CONFIG_BCM63XX - return dev->chip_id == BCM63XX_DEVICE_ID; --#else -- return 0; --#endif - } - - static inline int is5301x(struct b53_device *dev) diff --git a/target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch b/target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch deleted file mode 100644 index 3b7d8f37cd..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0004-net-dsa-tag_brcm-add-support-for-legacy-tags.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 964dbf186eaa84d409c359ddf09c827a3fbe8228 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 Mar 2021 11:29:26 +0100 -Subject: [PATCH] net: dsa: tag_brcm: add support for legacy tags -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add support for legacy Broadcom tags, which are similar to DSA_TAG_PROTO_BRCM. -These tags are used on BCM5325, BCM5365 and BCM63xx switches. - -Signed-off-by: Álvaro Fernández Rojas -Signed-off-by: David S. Miller ---- - include/net/dsa.h | 2 + - net/dsa/Kconfig | 7 +++ - net/dsa/tag_brcm.c | 107 +++++++++++++++++++++++++++++++++++++++++++-- - 3 files changed, 113 insertions(+), 3 deletions(-) - ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -45,10 +45,12 @@ struct phylink_link_state; - #define DSA_TAG_PROTO_OCELOT_VALUE 15 - #define DSA_TAG_PROTO_AR9331_VALUE 16 - #define DSA_TAG_PROTO_RTL4_A_VALUE 17 -+#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 - - enum dsa_tag_protocol { - DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, - DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, -+ DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE, - DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, - DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, - DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, ---- a/net/dsa/Kconfig -+++ b/net/dsa/Kconfig -@@ -47,6 +47,13 @@ config NET_DSA_TAG_BRCM - Say Y if you want to enable support for tagging frames for the - Broadcom switches which place the tag after the MAC source address. - -+config NET_DSA_TAG_BRCM_LEGACY -+ tristate "Tag driver for Broadcom legacy switches using in-frame headers" -+ select NET_DSA_TAG_BRCM_COMMON -+ help -+ Say Y if you want to enable support for tagging frames for the -+ Broadcom legacy switches which place the tag after the MAC source -+ address. - - config NET_DSA_TAG_BRCM_PREPEND - tristate "Tag driver for Broadcom switches using prepended headers" ---- a/net/dsa/tag_brcm.c -+++ b/net/dsa/tag_brcm.c -@@ -11,9 +11,26 @@ - - #include "dsa_priv.h" - --/* This tag length is 4 bytes, older ones were 6 bytes, we do not -- * handle them -- */ -+/* Legacy Broadcom tag (6 bytes) */ -+#define BRCM_LEG_TAG_LEN 6 -+ -+/* Type fields */ -+/* 1st byte in the tag */ -+#define BRCM_LEG_TYPE_HI 0x88 -+/* 2nd byte in the tag */ -+#define BRCM_LEG_TYPE_LO 0x74 -+ -+/* Tag fields */ -+/* 3rd byte in the tag */ -+#define BRCM_LEG_UNICAST (0 << 5) -+#define BRCM_LEG_MULTICAST (1 << 5) -+#define BRCM_LEG_EGRESS (2 << 5) -+#define BRCM_LEG_INGRESS (3 << 5) -+ -+/* 6th byte in the tag */ -+#define BRCM_LEG_PORT_ID (0xf) -+ -+/* Newer Broadcom tag (4 bytes) */ - #define BRCM_TAG_LEN 4 - - /* Tag is constructed and desconstructed using byte by byte access -@@ -194,6 +211,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops); - MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM); - #endif - -+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) -+static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct dsa_port *dp = dsa_slave_to_port(dev); -+ u8 *brcm_tag; -+ -+ /* The Ethernet switch we are interfaced with needs packets to be at -+ * least 64 bytes (including FCS) otherwise they will be discarded when -+ * they enter the switch port logic. When Broadcom tags are enabled, we -+ * need to make sure that packets are at least 70 bytes -+ * (including FCS and tag) because the length verification is done after -+ * the Broadcom tag is stripped off the ingress packet. -+ * -+ * Let dsa_slave_xmit() free the SKB -+ */ -+ if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false)) -+ return NULL; -+ -+ skb_push(skb, BRCM_LEG_TAG_LEN); -+ -+ memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN); -+ -+ brcm_tag = skb->data + 2 * ETH_ALEN; -+ -+ /* Broadcom tag type */ -+ brcm_tag[0] = BRCM_LEG_TYPE_HI; -+ brcm_tag[1] = BRCM_LEG_TYPE_LO; -+ -+ /* Broadcom tag value */ -+ brcm_tag[2] = BRCM_LEG_EGRESS; -+ brcm_tag[3] = 0; -+ brcm_tag[4] = 0; -+ brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID; -+ -+ return skb; -+} -+ -+static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, -+ struct net_device *dev, -+ struct packet_type *pt) -+{ -+ int source_port; -+ u8 *brcm_tag; -+ -+ if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID))) -+ return NULL; -+ -+ brcm_tag = skb->data - 2; -+ -+ source_port = brcm_tag[5] & BRCM_LEG_PORT_ID; -+ -+ skb->dev = dsa_master_find_slave(dev, 0, source_port); -+ if (!skb->dev) -+ return NULL; -+ -+ /* Remove Broadcom tag and update checksum */ -+ skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN); -+ -+ skb->offload_fwd_mark = 1; -+ -+ /* Move the Ethernet DA and SA */ -+ memmove(skb->data - ETH_HLEN, -+ skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN, -+ 2 * ETH_ALEN); -+ -+ return skb; -+} -+ -+static const struct dsa_device_ops brcm_legacy_netdev_ops = { -+ .name = "brcm-legacy", -+ .proto = DSA_TAG_PROTO_BRCM_LEGACY, -+ .xmit = brcm_leg_tag_xmit, -+ .rcv = brcm_leg_tag_rcv, -+ .overhead = BRCM_LEG_TAG_LEN, -+}; -+ -+DSA_TAG_DRIVER(brcm_legacy_netdev_ops); -+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY); -+#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */ -+ - #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) - static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, - struct net_device *dev) -@@ -226,6 +324,9 @@ static struct dsa_tag_driver *dsa_tag_dr - #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) - &DSA_TAG_DRIVER_NAME(brcm_netdev_ops), - #endif -+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) -+ &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops), -+#endif - #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) - &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), - #endif diff --git a/target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch b/target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch deleted file mode 100644 index 838e78a057..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0005-net-dsa-b53-support-legacy-tags.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 46c5176c586c81306bf9e7024c13b95da775490f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 Mar 2021 11:29:27 +0100 -Subject: [PATCH] net: dsa: b53: support legacy tags -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These tags are used on BCM5325, BCM5365 and BCM63xx switches. - -Signed-off-by: Álvaro Fernández Rojas -Acked-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/Kconfig | 1 + - drivers/net/dsa/b53/b53_common.c | 12 +++++++----- - 2 files changed, 8 insertions(+), 5 deletions(-) - ---- a/drivers/net/dsa/b53/Kconfig -+++ b/drivers/net/dsa/b53/Kconfig -@@ -3,6 +3,7 @@ menuconfig B53 - tristate "Broadcom BCM53xx managed switch support" - depends on NET_DSA - select NET_DSA_TAG_BRCM -+ select NET_DSA_TAG_BRCM_LEGACY - select NET_DSA_TAG_BRCM_PREPEND - help - This driver adds support for Broadcom managed switch chips. It supports ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2024,15 +2024,17 @@ enum dsa_tag_protocol b53_get_tag_protoc - { - struct b53_device *dev = ds->priv; - -- /* Older models (5325, 5365) support a different tag format that we do -- * not support in net/dsa/tag_brcm.c yet. -- */ -- if (is5325(dev) || is5365(dev) || -- !b53_can_enable_brcm_tags(ds, port, mprot)) { -+ if (!b53_can_enable_brcm_tags(ds, port, mprot)) { - dev->tag_protocol = DSA_TAG_PROTO_NONE; - goto out; - } - -+ /* Older models require a different 6 byte tag */ -+ if (is5325(dev) || is5365(dev) || is63xx(dev)) { -+ dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY; -+ goto out; -+ } -+ - /* Broadcom BCM58xx chips have a flow accelerator on Port 8 - * which requires us to use the prepended Broadcom tag type - */ diff --git a/target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch b/target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch deleted file mode 100644 index c1014b20bc..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0006-net-dsa-b53-mmap-Add-device-tree-support.patch +++ /dev/null @@ -1,92 +0,0 @@ -From a5538a777b73b35750ed1ffff8c1ef539e861624 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 Mar 2021 10:23:17 +0100 -Subject: [PATCH] net: dsa: b53: mmap: Add device tree support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add device tree support to b53_mmap.c while keeping platform devices support. - -Signed-off-by: Álvaro Fernández Rojas -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_mmap.c | 55 ++++++++++++++++++++++++++++++++++ - 1 file changed, 55 insertions(+) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -16,6 +16,7 @@ - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -+#include - #include - #include - #include -@@ -228,11 +229,65 @@ static const struct b53_io_ops b53_mmap_ - .write64 = b53_mmap_write64, - }; - -+static int b53_mmap_probe_of(struct platform_device *pdev, -+ struct b53_platform_data **ppdata) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *of_ports, *of_port; -+ struct device *dev = &pdev->dev; -+ struct b53_platform_data *pdata; -+ void __iomem *mem; -+ -+ mem = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(mem)) -+ return PTR_ERR(mem); -+ -+ pdata = devm_kzalloc(dev, sizeof(struct b53_platform_data), -+ GFP_KERNEL); -+ if (!pdata) -+ return -ENOMEM; -+ -+ pdata->regs = mem; -+ pdata->chip_id = BCM63XX_DEVICE_ID; -+ pdata->big_endian = of_property_read_bool(np, "big-endian"); -+ -+ of_ports = of_get_child_by_name(np, "ports"); -+ if (!of_ports) { -+ dev_err(dev, "no ports child node found\n"); -+ return -EINVAL; -+ } -+ -+ for_each_available_child_of_node(of_ports, of_port) { -+ u32 reg; -+ -+ if (of_property_read_u32(of_port, "reg", ®)) -+ continue; -+ -+ if (reg < B53_CPU_PORT) -+ pdata->enabled_ports |= BIT(reg); -+ } -+ -+ of_node_put(of_ports); -+ *ppdata = pdata; -+ -+ return 0; -+} -+ - static int b53_mmap_probe(struct platform_device *pdev) - { -+ struct device_node *np = pdev->dev.of_node; - struct b53_platform_data *pdata = pdev->dev.platform_data; - struct b53_mmap_priv *priv; - struct b53_device *dev; -+ int ret; -+ -+ if (!pdata && np) { -+ ret = b53_mmap_probe_of(pdev, &pdata); -+ if (ret) { -+ dev_err(&pdev->dev, "OF probe error\n"); -+ return ret; -+ } -+ } - - if (!pdata) - return -EINVAL; diff --git a/target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch b/target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch deleted file mode 100644 index ea36755732..0000000000 --- a/target/linux/generic/backport-5.15/740-v5.13-0007-net-dsa-b53-spi-add-missing-MODULE_DEVICE_TABLE.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 866f1577ba69bde2b9f36c300f603596c7d84a62 Mon Sep 17 00:00:00 2001 -From: Qinglang Miao -Date: Thu, 25 Mar 2021 17:19:54 +0800 -Subject: [PATCH] net: dsa: b53: spi: add missing MODULE_DEVICE_TABLE - -This patch adds missing MODULE_DEVICE_TABLE definition which generates -correct modalias for automatic loading of this driver when it is built -as an external module. - -Reported-by: Hulk Robot -Signed-off-by: Qinglang Miao -Acked-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_spi.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/dsa/b53/b53_spi.c -+++ b/drivers/net/dsa/b53/b53_spi.c -@@ -335,6 +335,7 @@ static const struct of_device_id b53_spi - { .compatible = "brcm,bcm53128" }, - { /* sentinel */ } - }; -+MODULE_DEVICE_TABLE(of, b53_spi_of_match); - - static struct spi_driver b53_spi_driver = { - .driver = { diff --git a/target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch b/target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch deleted file mode 100644 index 2a8def39b8..0000000000 --- a/target/linux/generic/backport-5.15/741-v5.14-0001-net-dsa-b53-Do-not-force-CPU-to-be-always-tagged.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 2c32a3d3c233b855943677609fe388f82b1f0975 Mon Sep 17 00:00:00 2001 -From: Florian Fainelli -Date: Tue, 8 Jun 2021 14:22:04 -0700 -Subject: [PATCH] net: dsa: b53: Do not force CPU to be always tagged - -Commit ca8931948344 ("net: dsa: b53: Keep CPU port as tagged in all -VLANs") forced the CPU port to be always tagged in any VLAN membership. -This was necessary back then because we did not support Broadcom tags -for all configurations so the only way to differentiate tagged and -untagged traffic while DSA_TAG_PROTO_NONE was used was to force the CPU -port into being always tagged. - -With most configurations enabling Broadcom tags, especially after -8fab459e69ab ("net: dsa: b53: Enable Broadcom tags for 531x5/539x -families") we do not need to apply this unconditional force tagging of -the CPU port in all VLANs. - -A helper function is introduced to faciliate the encapsulation of the -specific condition requiring the CPU port to be tagged in all VLANs and -the dsa_switch_ops::untag_bridge_pvid boolean is moved to when -dsa_switch_ops::setup is called when we have already determined the -tagging protocol we will be using. - -Reported-by: Matthew Hagan -Signed-off-by: Florian Fainelli -Reviewed-by: Vladimir Oltean -Tested-by: Matthew Hagan -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_common.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1049,6 +1049,11 @@ static int b53_setup(struct dsa_switch * - unsigned int port; - int ret; - -+ /* Request bridge PVID untagged when DSA_TAG_PROTO_NONE is set -+ * which forces the CPU port to be tagged in all VLANs. -+ */ -+ ds->untag_bridge_pvid = dev->tag_protocol == DSA_TAG_PROTO_NONE; -+ - ret = b53_reset_switch(dev); - if (ret) { - dev_err(ds->dev, "failed to reset switch\n"); -@@ -1423,6 +1428,13 @@ int b53_vlan_prepare(struct dsa_switch * - return 0; - } - EXPORT_SYMBOL(b53_vlan_prepare); -+ -+static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) -+{ -+ struct b53_device *dev = ds->priv; -+ -+ return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); -+} - - void b53_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) -@@ -1442,7 +1454,7 @@ void b53_vlan_add(struct dsa_switch *ds, - untagged = true; - - vl->members |= BIT(port); -- if (untagged && !dsa_is_cpu_port(ds, port)) -+ if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port)) - vl->untag |= BIT(port); - else - vl->untag &= ~BIT(port); -@@ -1480,7 +1492,7 @@ int b53_vlan_del(struct dsa_switch *ds, - if (pvid == vid) - pvid = b53_default_pvid(dev); - -- if (untagged && !dsa_is_cpu_port(ds, port)) -+ if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port)) - vl->untag &= ~(BIT(port)); - - b53_set_vlan_entry(dev, vid, vl); -@@ -2644,7 +2656,6 @@ struct b53_device *b53_switch_alloc(stru - dev->ops = ops; - ds->ops = &b53_switch_ops; - ds->configure_vlan_while_not_filtering = true; -- ds->untag_bridge_pvid = true; - dev->vlan_enabled = ds->configure_vlan_while_not_filtering; - /* Let DSA handle the case were multiple bridges span the same switch - * device and different VLAN awareness settings are requested, which diff --git a/target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch b/target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch deleted file mode 100644 index ee3a71ffa5..0000000000 --- a/target/linux/generic/backport-5.15/741-v5.14-0002-net-dsa-b53-remove-redundant-null-check-on-dev.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 11b57faf951cd3a570e3d9e463fc7c41023bc8c6 Mon Sep 17 00:00:00 2001 -From: Colin Ian King -Date: Tue, 15 Jun 2021 10:05:16 +0100 -Subject: [PATCH] net: dsa: b53: remove redundant null check on dev - -The pointer dev can never be null, the null check is redundant -and can be removed. Cleans up a static analysis warning that -pointer priv is dereferencing dev before dev is being null -checked. - -Addresses-Coverity: ("Dereference before null check") -Signed-off-by: Colin Ian King -Acked-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_srab.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/dsa/b53/b53_srab.c -+++ b/drivers/net/dsa/b53/b53_srab.c -@@ -632,8 +632,7 @@ static int b53_srab_remove(struct platfo - struct b53_srab_priv *priv = dev->priv; - - b53_srab_intr_set(priv, false); -- if (dev) -- b53_switch_remove(dev); -+ b53_switch_remove(dev); - - return 0; - } diff --git a/target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch b/target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch deleted file mode 100644 index df891d68ab..0000000000 --- a/target/linux/generic/backport-5.15/741-v5.14-0003-net-dsa-b53-Create-default-VLAN-entry-explicitly.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 64a81b24487f0d2fba0f033029eec2abc7d82cee Mon Sep 17 00:00:00 2001 -From: Florian Fainelli -Date: Mon, 21 Jun 2021 15:10:55 -0700 -Subject: [PATCH] net: dsa: b53: Create default VLAN entry explicitly - -In case CONFIG_VLAN_8021Q is not set, there will be no call down to the -b53 driver to ensure that the default PVID VLAN entry will be configured -with the appropriate untagged attribute towards the CPU port. We were -implicitly relying on dsa_slave_vlan_rx_add_vid() to do that for us, -instead make it explicit. - -Reported-by: Vladimir Oltean -Signed-off-by: Florian Fainelli -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_common.c | 27 +++++++++++++++++++-------- - 1 file changed, 19 insertions(+), 8 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -693,6 +693,13 @@ static u16 b53_default_pvid(struct b53_d - return 0; - } - -+static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) -+{ -+ struct b53_device *dev = ds->priv; -+ -+ return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); -+} -+ - int b53_configure_vlan(struct dsa_switch *ds) - { - struct b53_device *dev = ds->priv; -@@ -713,9 +720,20 @@ int b53_configure_vlan(struct dsa_switch - - b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering); - -- b53_for_each_port(dev, i) -+ /* Create an untagged VLAN entry for the default PVID in case -+ * CONFIG_VLAN_8021Q is disabled and there are no calls to -+ * dsa_slave_vlan_rx_add_vid() to create the default VLAN -+ * entry. Do this only when the tagging protocol is not -+ * DSA_TAG_PROTO_NONE -+ */ -+ b53_for_each_port(dev, i) { -+ v = &dev->vlans[def_vid]; -+ v->members |= BIT(i); -+ if (!b53_vlan_port_needs_forced_tagged(ds, i)) -+ v->untag = v->members; - b53_write16(dev, B53_VLAN_PAGE, - B53_VLAN_PORT_DEF_TAG(i), def_vid); -+ } - - /* Upon initial call we have not set-up any VLANs, but upon - * system resume, we need to restore all VLAN entries. -@@ -1429,13 +1447,6 @@ int b53_vlan_prepare(struct dsa_switch * - } - EXPORT_SYMBOL(b53_vlan_prepare); - --static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) --{ -- struct b53_device *dev = ds->priv; -- -- return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); --} -- - void b53_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) - { diff --git a/target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch b/target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch deleted file mode 100644 index ab4fdf8509..0000000000 --- a/target/linux/generic/backport-5.15/744-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch +++ /dev/null @@ -1,138 +0,0 @@ -From bea7907837c57a0aaac009931eb14efb056dafab Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Thu, 29 Jul 2021 17:56:00 +0300 -Subject: [PATCH] net: dsa: don't set skb->offload_fwd_mark when not offloading - the bridge - -DSA has gained the recent ability to deal gracefully with upper -interfaces it cannot offload, such as the bridge, bonding or team -drivers. When such uppers exist, the ports are still in standalone mode -as far as the hardware is concerned. - -But when we deliver packets to the software bridge in order for that to -do the forwarding, there is an unpleasant surprise in that the bridge -will refuse to forward them. This is because we unconditionally set -skb->offload_fwd_mark = true, meaning that the bridge thinks the frames -were already forwarded in hardware by us. - -Since dp->bridge_dev is populated only when there is hardware offload -for it, but not in the software fallback case, let's introduce a new -helper that can be called from the tagger data path which sets the -skb->offload_fwd_mark accordingly to zero when there is no hardware -offload for bridging. This lets the bridge forward packets back to other -interfaces of our switch, if needed. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Tobias Waldekranz -Signed-off-by: David S. Miller ---- - net/dsa/dsa_priv.h | 14 ++++++++++++++ - net/dsa/tag_brcm.c | 4 ++-- - net/dsa/tag_dsa.c | 15 +++++++++++---- - net/dsa/tag_ksz.c | 2 +- - net/dsa/tag_lan9303.c | 3 ++- - net/dsa/tag_mtk.c | 2 +- - net/dsa/tag_ocelot.c | 2 +- - net/dsa/tag_rtl4_a.c | 2 +- - net/dsa/tag_sja1105.c | 20 ++++++++++++++------ - 9 files changed, 47 insertions(+), 17 deletions(-) - ---- a/net/dsa/dsa_priv.h -+++ b/net/dsa/dsa_priv.h -@@ -266,6 +266,20 @@ static inline struct sk_buff *dsa_untag_ - return skb; - } - -+/* If the ingress port offloads the bridge, we mark the frame as autonomously -+ * forwarded by hardware, so the software bridge doesn't forward in twice, back -+ * to us, because we already did. However, if we're in fallback mode and we do -+ * software bridging, we are not offloading it, therefore the dp->bridge_dev -+ * pointer is not populated, and flooding needs to be done by software (we are -+ * effectively operating in standalone ports mode). -+ */ -+static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb) -+{ -+ struct dsa_port *dp = dsa_slave_to_port(skb->dev); -+ -+ skb->offload_fwd_mark = !!(dp->bridge_dev); -+} -+ - /* switch.c */ - int dsa_switch_register_notifier(struct dsa_switch *ds); - void dsa_switch_unregister_notifier(struct dsa_switch *ds); ---- a/net/dsa/tag_brcm.c -+++ b/net/dsa/tag_brcm.c -@@ -166,7 +166,7 @@ static struct sk_buff *brcm_tag_rcv_ll(s - /* Remove Broadcom tag and update checksum */ - skb_pull_rcsum(skb, BRCM_TAG_LEN); - -- skb->offload_fwd_mark = 1; -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } -@@ -270,7 +270,7 @@ static struct sk_buff *brcm_leg_tag_rcv( - /* Remove Broadcom tag and update checksum */ - skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN); - -- skb->offload_fwd_mark = 1; -+ dsa_default_offload_fwd_mark(skb); - - /* Move the Ethernet DA and SA */ - memmove(skb->data - ETH_HLEN, ---- a/net/dsa/tag_ksz.c -+++ b/net/dsa/tag_ksz.c -@@ -24,7 +24,7 @@ static struct sk_buff *ksz_common_rcv(st - - pskb_trim_rcsum(skb, skb->len - len); - -- skb->offload_fwd_mark = true; -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } ---- a/net/dsa/tag_lan9303.c -+++ b/net/dsa/tag_lan9303.c -@@ -115,7 +115,8 @@ static struct sk_buff *lan9303_rcv(struc - skb_pull_rcsum(skb, 2 + 2); - memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN), - 2 * ETH_ALEN); -- skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU); -+ if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU)) -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } ---- a/net/dsa/tag_mtk.c -+++ b/net/dsa/tag_mtk.c -@@ -104,7 +104,7 @@ static struct sk_buff *mtk_tag_rcv(struc - - /* Only unicast or broadcast frames are offloaded */ - if (likely(!is_multicast_skb)) -- skb->offload_fwd_mark = 1; -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } ---- a/net/dsa/tag_ocelot.c -+++ b/net/dsa/tag_ocelot.c -@@ -225,7 +225,7 @@ static struct sk_buff *ocelot_rcv(struct - */ - return NULL; - -- skb->offload_fwd_mark = 1; -+ dsa_default_offload_fwd_mark(skb); - skb->priority = qos_class; - - /* Ocelot switches copy frames unmodified to the CPU. However, it is ---- a/net/dsa/tag_rtl4_a.c -+++ b/net/dsa/tag_rtl4_a.c -@@ -115,7 +115,7 @@ static struct sk_buff *rtl4a_tag_rcv(str - skb->data - ETH_HLEN - RTL4_A_HDR_LEN, - 2 * ETH_ALEN); - -- skb->offload_fwd_mark = 1; -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } diff --git a/target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch b/target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch deleted file mode 100644 index eb487cdfb5..0000000000 --- a/target/linux/generic/backport-5.15/762-v5.11-net-dsa-mt7530-support-setting-MTU.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 9470174e7581e75a8ebd78964997314dfc2e706c Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Tue, 3 Nov 2020 13:06:18 +0800 -Subject: [PATCH] net: dsa: mt7530: support setting MTU - -MT7530/7531 has a global RX packet length register, which can be used -to set MTU. - -Supported packet length values are 1522 (1518 if untagged), 1536, -1552, and multiple of 1024 (from 2048 to 15360). - -Signed-off-by: DENG Qingfang -Link: https://lore.kernel.org/r/20201103050618.11419-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.h | 12 ++++++++++ - 2 files changed, 61 insertions(+) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1015,6 +1015,53 @@ mt7530_port_disable(struct dsa_switch *d - mutex_unlock(&priv->reg_mutex); - } - -+static int -+mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct mii_bus *bus = priv->bus; -+ int length; -+ u32 val; -+ -+ /* When a new MTU is set, DSA always set the CPU port's MTU to the -+ * largest MTU of the slave ports. Because the switch only has a global -+ * RX length register, only allowing CPU port here is enough. -+ */ -+ if (!dsa_is_cpu_port(ds, port)) -+ return 0; -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ val = mt7530_mii_read(priv, MT7530_GMACCR); -+ val &= ~MAX_RX_PKT_LEN_MASK; -+ -+ /* RX length also includes Ethernet header, MTK tag, and FCS length */ -+ length = new_mtu + ETH_HLEN + MTK_HDR_LEN + ETH_FCS_LEN; -+ if (length <= 1522) { -+ val |= MAX_RX_PKT_LEN_1522; -+ } else if (length <= 1536) { -+ val |= MAX_RX_PKT_LEN_1536; -+ } else if (length <= 1552) { -+ val |= MAX_RX_PKT_LEN_1552; -+ } else { -+ val &= ~MAX_RX_JUMBO_MASK; -+ val |= MAX_RX_JUMBO(DIV_ROUND_UP(length, 1024)); -+ val |= MAX_RX_PKT_LEN_JUMBO; -+ } -+ -+ mt7530_mii_write(priv, MT7530_GMACCR, val); -+ -+ mutex_unlock(&bus->mdio_lock); -+ -+ return 0; -+} -+ -+static int -+mt7530_port_max_mtu(struct dsa_switch *ds, int port) -+{ -+ return MT7530_MAX_MTU; -+} -+ - static void - mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state) - { -@@ -2652,6 +2699,8 @@ static const struct dsa_switch_ops mt753 - .get_sset_count = mt7530_get_sset_count, - .port_enable = mt7530_port_enable, - .port_disable = mt7530_port_disable, -+ .port_change_mtu = mt7530_port_change_mtu, -+ .port_max_mtu = mt7530_port_max_mtu, - .port_stp_state_set = mt7530_stp_state_set, - .port_bridge_join = mt7530_port_bridge_join, - .port_bridge_leave = mt7530_port_bridge_leave, ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -11,6 +11,9 @@ - #define MT7530_NUM_FDB_RECORDS 2048 - #define MT7530_ALL_MEMBERS 0xff - -+#define MTK_HDR_LEN 4 -+#define MT7530_MAX_MTU (15 * 1024 - ETH_HLEN - ETH_FCS_LEN - MTK_HDR_LEN) -+ - enum mt753x_id { - ID_MT7530 = 0, - ID_MT7621 = 1, -@@ -301,6 +304,15 @@ enum mt7530_vlan_port_attr { - #define MT7531_DBG_CNT(x) (0x3018 + (x) * 0x100) - #define MT7531_DIS_CLR BIT(31) - -+#define MT7530_GMACCR 0x30e0 -+#define MAX_RX_JUMBO(x) ((x) << 2) -+#define MAX_RX_JUMBO_MASK GENMASK(5, 2) -+#define MAX_RX_PKT_LEN_MASK GENMASK(1, 0) -+#define MAX_RX_PKT_LEN_1522 0x0 -+#define MAX_RX_PKT_LEN_1536 0x1 -+#define MAX_RX_PKT_LEN_1552 0x2 -+#define MAX_RX_PKT_LEN_JUMBO 0x3 -+ - /* Register for MIB */ - #define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100) - #define MT7530_MIB_CCR 0x4fe0 diff --git a/target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch b/target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch deleted file mode 100644 index b0ad7b9f87..0000000000 --- a/target/linux/generic/backport-5.15/763-v5.11-net-dsa-mt7530-enable-MTU-normalization.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 771c8901568dd8776a260aa93db41be88a60389e Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Fri, 11 Dec 2020 01:03:22 +0800 -Subject: [PATCH] net: dsa: mt7530: enable MTU normalization - -MT7530 has a global RX length register, so we are actually changing its -MRU. -Enable MTU normalization for this reason. - -Signed-off-by: DENG Qingfang -Acked-by: Landen Chao -Reviewed-by: Vladimir Oltean -Link: https://lore.kernel.org/r/20201210170322.3433-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mt7530.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1703,6 +1703,7 @@ mt7530_setup(struct dsa_switch *ds) - */ - dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent; - ds->configure_vlan_while_not_filtering = true; -+ ds->mtu_enforcement_ingress = true; - - if (priv->id == ID_MT7530) { - regulator_set_voltage(priv->core_pwr, 1000000, 1000000); -@@ -1947,6 +1948,7 @@ mt7531_setup(struct dsa_switch *ds) - } - - ds->configure_vlan_while_not_filtering = true; -+ ds->mtu_enforcement_ingress = true; - - /* Flush the FDB table */ - ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); diff --git a/target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch b/target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch deleted file mode 100644 index 44fa40eabe..0000000000 --- a/target/linux/generic/backport-5.15/764-v5.11-net-dsa-mt7530-support-setting-ageing-time.patch +++ /dev/null @@ -1,99 +0,0 @@ -From ea6d5c924e391872d402acac38461a5f8261e57f Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Tue, 8 Dec 2020 15:00:28 +0800 -Subject: [PATCH] net: dsa: mt7530: support setting ageing time - -MT7530 has a global address age control register, so use it to set -ageing time. - -The applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds - -Signed-off-by: DENG Qingfang -Reviewed-by: Andrew Lunn -Reviewed-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 41 ++++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.h | 13 +++++++++++++ - 2 files changed, 54 insertions(+) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -870,6 +870,46 @@ mt7530_get_sset_count(struct dsa_switch - return ARRAY_SIZE(mt7530_mib); - } - -+static int -+mt7530_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ unsigned int secs = msecs / 1000; -+ unsigned int tmp_age_count; -+ unsigned int error = -1; -+ unsigned int age_count; -+ unsigned int age_unit; -+ -+ /* Applied timer is (AGE_CNT + 1) * (AGE_UNIT + 1) seconds */ -+ if (secs < 1 || secs > (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1)) -+ return -ERANGE; -+ -+ /* iterate through all possible age_count to find the closest pair */ -+ for (tmp_age_count = 0; tmp_age_count <= AGE_CNT_MAX; ++tmp_age_count) { -+ unsigned int tmp_age_unit = secs / (tmp_age_count + 1) - 1; -+ -+ if (tmp_age_unit <= AGE_UNIT_MAX) { -+ unsigned int tmp_error = secs - -+ (tmp_age_count + 1) * (tmp_age_unit + 1); -+ -+ /* found a closer pair */ -+ if (error > tmp_error) { -+ error = tmp_error; -+ age_count = tmp_age_count; -+ age_unit = tmp_age_unit; -+ } -+ -+ /* found the exact match, so break the loop */ -+ if (!error) -+ break; -+ } -+ } -+ -+ mt7530_write(priv, MT7530_AAC, AGE_CNT(age_count) | AGE_UNIT(age_unit)); -+ -+ return 0; -+} -+ - static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) - { - struct mt7530_priv *priv = ds->priv; -@@ -2699,6 +2739,7 @@ static const struct dsa_switch_ops mt753 - .phy_write = mt753x_phy_write, - .get_ethtool_stats = mt7530_get_ethtool_stats, - .get_sset_count = mt7530_get_sset_count, -+ .set_ageing_time = mt7530_set_ageing_time, - .port_enable = mt7530_port_enable, - .port_disable = mt7530_port_disable, - .port_change_mtu = mt7530_port_change_mtu, ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -161,6 +161,19 @@ enum mt7530_vlan_egress_attr { - MT7530_VLAN_EGRESS_STACK = 3, - }; - -+/* Register for address age control */ -+#define MT7530_AAC 0xa0 -+/* Disable ageing */ -+#define AGE_DIS BIT(20) -+/* Age count */ -+#define AGE_CNT_MASK GENMASK(19, 12) -+#define AGE_CNT_MAX 0xff -+#define AGE_CNT(x) (AGE_CNT_MASK & ((x) << 12)) -+/* Age unit */ -+#define AGE_UNIT_MASK GENMASK(11, 0) -+#define AGE_UNIT_MAX 0xfff -+#define AGE_UNIT(x) (AGE_UNIT_MASK & (x)) -+ - /* Register for port STP state control */ - #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) - #define FID_PST(x) ((x) & 0x3) diff --git a/target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch b/target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch deleted file mode 100644 index a0bb7fa888..0000000000 --- a/target/linux/generic/backport-5.15/765-v5.15-net-dsa-mt7530-disable-learning-on-standalone-ports.patch +++ /dev/null @@ -1,65 +0,0 @@ -From ba2203f36b981235556504fb7b62baee28512a40 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Tue, 24 Aug 2021 11:37:50 +0800 -Subject: [PATCH] net: dsa: mt7530: disable learning on standalone ports - -This is a partial backport of commit 5a30833b9a16f8d1aa15de06636f9317ca51f9df -("net: dsa: mt7530: support MDB and bridge flag operations") upstream. - -Make sure that the standalone ports start up with learning disabled. - -Signed-off-by: DENG Qingfang ---- - drivers/net/dsa/mt7530.c | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1163,6 +1163,8 @@ mt7530_port_bridge_join(struct dsa_switc - PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap)); - priv->ports[port].pm |= PCR_MATRIX(port_bitmap); - -+ mt7530_clear(priv, MT7530_PSC_P(port), SA_DIS); -+ - mutex_unlock(&priv->reg_mutex); - - return 0; -@@ -1260,6 +1262,8 @@ mt7530_port_bridge_leave(struct dsa_swit - PCR_MATRIX(BIT(MT7530_CPU_PORT))); - priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); - -+ mt7530_set(priv, MT7530_PSC_P(port), SA_DIS); -+ - mutex_unlock(&priv->reg_mutex); - } - -@@ -1817,9 +1821,13 @@ mt7530_setup(struct dsa_switch *ds) - ret = mt753x_cpu_port_enable(ds, i); - if (ret) - return ret; -- } else -+ } else { - mt7530_port_disable(ds, i); - -+ /* Disable learning by default on all user ports */ -+ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); -+ } -+ - /* Enable consistent egress tag */ - mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, - PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); -@@ -1979,9 +1987,13 @@ mt7531_setup(struct dsa_switch *ds) - ret = mt753x_cpu_port_enable(ds, i); - if (ret) - return ret; -- } else -+ } else { - mt7530_port_disable(ds, i); - -+ /* Disable learning by default on all user ports */ -+ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); -+ } -+ - /* Enable consistent egress tag */ - mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, - PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); diff --git a/target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch b/target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch deleted file mode 100644 index f376ff949a..0000000000 --- a/target/linux/generic/backport-5.15/766-v5.15-net-dsa-mt7530-enable-assisted-learning-on-CPU-port.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 59c8adbc8e2c7f6b46385f36962eadaad3ea2daa Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Wed, 4 Aug 2021 00:04:01 +0800 -Subject: [PATCH] net: dsa: mt7530: enable assisted learning on CPU port - -Consider the following bridge configuration, where bond0 is not -offloaded: - - +-- br0 --+ - / / | \ - / / | \ - / | | bond0 - / | | / \ - swp0 swp1 swp2 swp3 swp4 - . . . - . . . - A B C - -Address learning is enabled on offloaded ports (swp0~2) and the CPU -port, so when client A sends a packet to C, the following will happen: - -1. The switch learns that client A can be reached at swp0. -2. The switch probably already knows that client C can be reached at the - CPU port, so it forwards the packet to the CPU. -3. The bridge core knows client C can be reached at bond0, so it - forwards the packet back to the switch. -4. The switch learns that client A can be reached at the CPU port. -5. The switch forwards the packet to either swp3 or swp4, according to - the packet's tag. - -That makes client A's MAC address flap between swp0 and the CPU port. If -client B sends a packet to A, it is possible that the packet is -forwarded to the CPU. With offload_fwd_mark = 1, the bridge core won't -forward it back to the switch, resulting in packet loss. - -As we have the assisted_learning_on_cpu_port in DSA core now, enable -that and disable hardware learning on the CPU port. - -Signed-off-by: DENG Qingfang -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1747,6 +1747,7 @@ mt7530_setup(struct dsa_switch *ds) - */ - dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent; - ds->configure_vlan_while_not_filtering = true; -+ ds->assisted_learning_on_cpu_port = true; - ds->mtu_enforcement_ingress = true; - - if (priv->id == ID_MT7530) { -@@ -1817,15 +1818,15 @@ mt7530_setup(struct dsa_switch *ds) - mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, - PCR_MATRIX_CLR); - -+ /* Disable learning by default on all ports */ -+ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); -+ - if (dsa_is_cpu_port(ds, i)) { - ret = mt753x_cpu_port_enable(ds, i); - if (ret) - return ret; - } else { - mt7530_port_disable(ds, i); -- -- /* Disable learning by default on all user ports */ -- mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); - } - - /* Enable consistent egress tag */ -@@ -1981,6 +1982,9 @@ mt7531_setup(struct dsa_switch *ds) - mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, - PCR_MATRIX_CLR); - -+ /* Disable learning by default on all ports */ -+ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); -+ - mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); - - if (dsa_is_cpu_port(ds, i)) { -@@ -1989,9 +1993,6 @@ mt7531_setup(struct dsa_switch *ds) - return ret; - } else { - mt7530_port_disable(ds, i); -- -- /* Disable learning by default on all user ports */ -- mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); - } - - /* Enable consistent egress tag */ -@@ -2000,6 +2001,7 @@ mt7531_setup(struct dsa_switch *ds) - } - - ds->configure_vlan_while_not_filtering = true; -+ ds->assisted_learning_on_cpu_port = true; - ds->mtu_enforcement_ingress = true; - - /* Flush the FDB table */ diff --git a/target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch b/target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch deleted file mode 100644 index f9fe0ef858..0000000000 --- a/target/linux/generic/backport-5.15/767-v5.15-net-dsa-mt7530-use-independent-VLAN-learning-on-VLAN.patch +++ /dev/null @@ -1,262 +0,0 @@ -From e3a402764c5753698e7a9e45d4d21f093faa7852 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Wed, 4 Aug 2021 00:04:02 +0800 -Subject: [PATCH] net: dsa: mt7530: use independent VLAN learning on - VLAN-unaware bridges - -Consider the following bridge configuration, where bond0 is not -offloaded: - - +-- br0 --+ - / / | \ - / / | \ - / | | bond0 - / | | / \ - swp0 swp1 swp2 swp3 swp4 - . . . - . . . - A B C - -Ideally, when the switch receives a packet from swp3 or swp4, it should -forward the packet to the CPU, according to the port matrix and unknown -unicast flood settings. - -But packet loss will happen if the destination address is at one of the -offloaded ports (swp0~2). For example, when client C sends a packet to -A, the FDB lookup will indicate that it should be forwarded to swp0, but -the port matrix of swp3 and swp4 is configured to only allow the CPU to -be its destination, so it is dropped. - -However, this issue does not happen if the bridge is VLAN-aware. That is -because VLAN-aware bridges use independent VLAN learning, i.e. use VID -for FDB lookup, on offloaded ports. As swp3 and swp4 are not offloaded, -shared VLAN learning with default filter ID of 0 is used instead. So the -lookup for A with filter ID 0 never hits and the packet can be forwarded -to the CPU. - -In the current code, only two combinations were used to toggle user -ports' VLAN awareness: one is PCR.PORT_VLAN set to port matrix mode with -PVC.VLAN_ATTR set to transparent port, the other is PCR.PORT_VLAN set to -security mode with PVC.VLAN_ATTR set to user port. - -It turns out that only PVC.VLAN_ATTR contributes to VLAN awareness, and -port matrix mode just skips the VLAN table lookup. The reference manual -is somehow misleading when describing PORT_VLAN modes. It states that -PORT_MEM (VLAN port member) is used for destination if the VLAN table -lookup hits, but actually **PORT_MEM & PORT_MATRIX** (bitwise AND of -VLAN port member and port matrix) is used instead, which means we can -have two or more separate VLAN-aware bridges with the same PVID and -traffic won't leak between them. - -Therefore, to solve this, enable independent VLAN learning with PVID 0 -on VLAN-unaware bridges, by setting their PCR.PORT_VLAN to fallback -mode, while leaving standalone ports in port matrix mode. The CPU port -is always set to fallback mode to serve those bridges. - -During testing, it is found that FDB lookup with filter ID of 0 will -also hit entries with VID 0 even with independent VLAN learning. To -avoid that, install all VLANs with filter ID of 1. - -Signed-off-by: DENG Qingfang -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 72 +++++++++++++++++++++++++++++----------- - drivers/net/dsa/mt7530.h | 9 ++++- - 2 files changed, 60 insertions(+), 21 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1011,6 +1011,10 @@ mt753x_cpu_port_enable(struct dsa_switch - mt7530_write(priv, MT7530_PCR_P(port), - PCR_MATRIX(dsa_user_ports(priv->ds))); - -+ /* Set to fallback mode for independent VLAN learning */ -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, -+ MT7530_PORT_FALLBACK_MODE); -+ - return 0; - } - -@@ -1165,6 +1169,10 @@ mt7530_port_bridge_join(struct dsa_switc - - mt7530_clear(priv, MT7530_PSC_P(port), SA_DIS); - -+ /* Set to fallback mode for independent VLAN learning */ -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, -+ MT7530_PORT_FALLBACK_MODE); -+ - mutex_unlock(&priv->reg_mutex); - - return 0; -@@ -1177,16 +1185,21 @@ mt7530_port_set_vlan_unaware(struct dsa_ - bool all_user_ports_removed = true; - int i; - -- /* When a port is removed from the bridge, the port would be set up -- * back to the default as is at initial boot which is a VLAN-unaware -- * port. -+ /* This is called after .port_bridge_leave when leaving a VLAN-aware -+ * bridge. Don't set standalone ports to fallback mode. - */ -- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, -- MT7530_PORT_MATRIX_MODE); -+ if (dsa_to_port(ds, port)->bridge_dev) -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, -+ MT7530_PORT_FALLBACK_MODE); -+ - mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK, - VLAN_ATTR(MT7530_VLAN_TRANSPARENT) | - PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); - -+ /* Set PVID to 0 */ -+ mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, -+ G0_PORT_VID_DEF); -+ - for (i = 0; i < MT7530_NUM_PORTS; i++) { - if (dsa_is_user_port(ds, i) && - dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) { -@@ -1212,15 +1225,14 @@ mt7530_port_set_vlan_aware(struct dsa_sw - struct mt7530_priv *priv = ds->priv; - - /* Trapped into security mode allows packet forwarding through VLAN -- * table lookup. CPU port is set to fallback mode to let untagged -- * frames pass through. -+ * table lookup. - */ -- if (dsa_is_cpu_port(ds, port)) -- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, -- MT7530_PORT_FALLBACK_MODE); -- else -+ if (dsa_is_user_port(ds, port)) { - mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, - MT7530_PORT_SECURITY_MODE); -+ mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, -+ G0_PORT_VID(priv->ports[port].pvid)); -+ } - - /* Set the port as a user port which is to be able to recognize VID - * from incoming packets before fetching entry within the VLAN table. -@@ -1264,6 +1276,13 @@ mt7530_port_bridge_leave(struct dsa_swit - - mt7530_set(priv, MT7530_PSC_P(port), SA_DIS); - -+ /* When a port is removed from the bridge, the port would be set up -+ * back to the default as is at initial boot which is a VLAN-unaware -+ * port. -+ */ -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, -+ MT7530_PORT_MATRIX_MODE); -+ - mutex_unlock(&priv->reg_mutex); - } - -@@ -1406,7 +1425,8 @@ mt7530_hw_vlan_add(struct mt7530_priv *p - /* Validate the entry with independent learning, create egress tag per - * VLAN and joining the port as one of the port members. - */ -- val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID; -+ val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | FID(FID_BRIDGED) | -+ VLAN_VALID; - mt7530_write(priv, MT7530_VAWD1, val); - - /* Decide whether adding tag or not for those outgoing packets from the -@@ -1499,9 +1519,13 @@ mt7530_port_vlan_add(struct dsa_switch * - } - - if (pvid) { -- mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, -- G0_PORT_VID(vlan->vid_end)); - priv->ports[port].pvid = vlan->vid_end; -+ -+ /* Only configure PVID if VLAN filtering is enabled */ -+ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) -+ mt7530_rmw(priv, MT7530_PPBV1_P(port), -+ G0_PORT_VID_MASK, -+ G0_PORT_VID(vlan->vid_end)); - } - - mutex_unlock(&priv->reg_mutex); -@@ -1513,11 +1537,10 @@ mt7530_port_vlan_del(struct dsa_switch * - { - struct mt7530_hw_vlan_entry target_entry; - struct mt7530_priv *priv = ds->priv; -- u16 vid, pvid; -+ u16 vid; - - mutex_lock(&priv->reg_mutex); - -- pvid = priv->ports[port].pvid; - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - mt7530_hw_vlan_entry_init(&target_entry, port, 0); - mt7530_hw_vlan_update(priv, vid, &target_entry, -@@ -1526,12 +1549,13 @@ mt7530_port_vlan_del(struct dsa_switch * - /* PVID is being restored to the default whenever the PVID port - * is being removed from the VLAN. - */ -- if (pvid == vid) -- pvid = G0_PORT_VID_DEF; -+ if (priv->ports[port].pvid == vid) { -+ priv->ports[port].pvid = G0_PORT_VID_DEF; -+ mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, -+ G0_PORT_VID_DEF); -+ } - } - -- mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, pvid); -- priv->ports[port].pvid = pvid; - - mutex_unlock(&priv->reg_mutex); - -@@ -1827,6 +1851,10 @@ mt7530_setup(struct dsa_switch *ds) - return ret; - } else { - mt7530_port_disable(ds, i); -+ -+ /* Set default PVID to 0 on all user ports */ -+ mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK, -+ G0_PORT_VID_DEF); - } - - /* Enable consistent egress tag */ -@@ -1993,6 +2021,10 @@ mt7531_setup(struct dsa_switch *ds) - return ret; - } else { - mt7530_port_disable(ds, i); -+ -+ /* Set default PVID to 0 on all user ports */ -+ mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK, -+ G0_PORT_VID_DEF); - } - - /* Enable consistent egress tag */ ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -145,11 +145,18 @@ enum mt7530_vlan_cmd { - #define VTAG_EN BIT(28) - /* VLAN Member Control */ - #define PORT_MEM(x) (((x) & 0xff) << 16) -+/* Filter ID */ -+#define FID(x) (((x) & 0x7) << 1) - /* VLAN Entry Valid */ - #define VLAN_VALID BIT(0) - #define PORT_MEM_SHFT 16 - #define PORT_MEM_MASK 0xff - -+enum mt7530_fid { -+ FID_STANDALONE = 0, -+ FID_BRIDGED = 1, -+}; -+ - #define MT7530_VAWD2 0x98 - /* Egress Tag Control */ - #define ETAG_CTRL_P(p, x) (((x) & 0x3) << ((p) << 1)) -@@ -244,7 +251,7 @@ enum mt7530_vlan_port_attr { - #define MT7530_PPBV1_P(x) (0x2014 + ((x) * 0x100)) - #define G0_PORT_VID(x) (((x) & 0xfff) << 0) - #define G0_PORT_VID_MASK G0_PORT_VID(0xfff) --#define G0_PORT_VID_DEF G0_PORT_VID(1) -+#define G0_PORT_VID_DEF G0_PORT_VID(0) - - /* Register for port MAC control register */ - #define MT7530_PMCR_P(x) (0x3000 + ((x) * 0x100)) diff --git a/target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch b/target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch deleted file mode 100644 index 2c1958bd43..0000000000 --- a/target/linux/generic/backport-5.15/768-v5.15-net-dsa-mt7530-set-STP-state-on-filter-ID-1.patch +++ /dev/null @@ -1,40 +0,0 @@ -From c5ffcefcb40420528d04c63e7dfc88f2845c9831 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Wed, 4 Aug 2021 00:04:03 +0800 -Subject: [PATCH] net: dsa: mt7530: set STP state on filter ID 1 - -As filter ID 1 is the only one used for bridges, set STP state on it. - -Signed-off-by: DENG Qingfang -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 3 ++- - drivers/net/dsa/mt7530.h | 4 ++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1131,7 +1131,8 @@ mt7530_stp_state_set(struct dsa_switch * - break; - } - -- mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK, stp_state); -+ mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK(FID_BRIDGED), -+ FID_PST(FID_BRIDGED, stp_state)); - } - - static int ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -183,8 +183,8 @@ enum mt7530_vlan_egress_attr { - - /* Register for port STP state control */ - #define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) --#define FID_PST(x) ((x) & 0x3) --#define FID_PST_MASK FID_PST(0x3) -+#define FID_PST(fid, state) (((state) & 0x3) << ((fid) * 2)) -+#define FID_PST_MASK(fid) FID_PST(fid, 0x3) - - enum mt7530_stp_state { - MT7530_STP_DISABLED = 0, diff --git a/target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch b/target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch deleted file mode 100644 index 97824068f0..0000000000 --- a/target/linux/generic/backport-5.15/769-v5.15-net-dsa-mt7530-always-install-FDB-entries-with-IVL-a.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 138c126a33f7564edb66b1da5b847e4a60740bfc Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Wed, 4 Aug 2021 00:04:04 +0800 -Subject: [PATCH] net: dsa: mt7530: always install FDB entries with IVL and FID - 1 - -This reverts commit 7e777021780e ("mt7530 mt7530_fdb_write only set ivl -bit vid larger than 1"). - -Before this series, the default value of all ports' PVID is 1, which is -copied into the FDB entry, even if the ports are VLAN unaware. So -`bridge fdb show` will show entries like `dev swp0 vlan 1 self` even on -a VLAN-unaware bridge. - -The blamed commit does not solve that issue completely, instead it may -cause a new issue that FDB is inaccessible in a VLAN-aware bridge with -PVID 1. - -This series sets PVID to 0 on VLAN-unaware ports, so `bridge fdb show` -will no longer print `vlan 1` on VLAN-unaware bridges, and that special -case in fdb_write is not required anymore. - -Set FDB entries' filter ID to 1 to match the VLAN table. - -Signed-off-by: DENG Qingfang -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 2 ++ - drivers/net/dsa/mt7530.h | 2 ++ - 2 files changed, 4 insertions(+) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -361,6 +361,8 @@ mt7530_fdb_write(struct mt7530_priv *pri - int i; - - reg[1] |= vid & CVID_MASK; -+ reg[1] |= ATA2_IVL; -+ reg[1] |= ATA2_FID(FID_BRIDGED); - reg[2] |= (aging & AGE_TIMER_MASK) << AGE_TIMER; - reg[2] |= (port_mask & PORT_MAP_MASK) << PORT_MAP; - /* STATIC_ENT indicate that entry is static wouldn't ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -77,6 +77,8 @@ enum mt753x_bpdu_port_fw { - #define STATIC_EMP 0 - #define STATIC_ENT 3 - #define MT7530_ATA2 0x78 -+#define ATA2_IVL BIT(15) -+#define ATA2_FID(x) (((x) & 0x7) << 12) - - /* Register for address table write data */ - #define MT7530_ATWD 0x7c diff --git a/target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch b/target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch deleted file mode 100644 index 5d91d5a657..0000000000 --- a/target/linux/generic/backport-5.15/770-v5.15-net-dsa-mt7530-support-MDB-operations.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 1f11a07a33bc26997c18b633d63f088bf75d11f2 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Tue, 24 Aug 2021 11:37:50 +0800 -Subject: [PATCH] net: dsa: mt7530: support MDB operations - -This is a partial backport of commit 5a30833b9a16f8d1aa15de06636f9317ca51f9df -("net: dsa: mt7530: support MDB and bridge flag operations") upstream. - -Signed-off-by: DENG Qingfang ---- - drivers/net/dsa/mt7530.c | 78 ++++++++++++++++++++++++++++++++++++++-- - net/dsa/tag_mtk.c | 14 +------- - 2 files changed, 76 insertions(+), 16 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1000,9 +1000,6 @@ mt753x_cpu_port_enable(struct dsa_switch - mt7530_write(priv, MT7530_PVC_P(port), - PORT_SPEC_TAG); - -- /* Unknown multicast frame forwarding to the cpu port */ -- mt7530_rmw(priv, MT7530_MFC, UNM_FFP_MASK, UNM_FFP(BIT(port))); -- - /* Set CPU port number */ - if (priv->id == ID_MT7621) - mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); -@@ -1138,6 +1135,20 @@ mt7530_stp_state_set(struct dsa_switch * - } - - static int -+mt7530_port_egress_floods(struct dsa_switch *ds, int port, -+ bool unicast, bool multicast) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ mt7530_rmw(priv, MT7530_MFC, -+ UNU_FFP(BIT(port)) | UNM_FFP(BIT(port)), -+ (unicast ? UNU_FFP(BIT(port)) : 0) | -+ (multicast ? UNM_FFP(BIT(port)) : 0)); -+ -+ return 0; -+} -+ -+static int - mt7530_port_bridge_join(struct dsa_switch *ds, int port, - struct net_device *bridge) - { -@@ -1357,6 +1368,63 @@ err: - } - - static int -+mt7530_port_mdb_prepare(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_mdb *mdb) -+{ -+ return 0; -+} -+ -+static void -+mt7530_port_mdb_add(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_mdb *mdb) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ const u8 *addr = mdb->addr; -+ u16 vid = mdb->vid; -+ u8 port_mask = 0; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ mt7530_fdb_write(priv, vid, 0, addr, 0, STATIC_EMP); -+ if (!mt7530_fdb_cmd(priv, MT7530_FDB_READ, NULL)) -+ port_mask = (mt7530_read(priv, MT7530_ATRD) >> PORT_MAP) -+ & PORT_MAP_MASK; -+ -+ port_mask |= BIT(port); -+ mt7530_fdb_write(priv, vid, port_mask, addr, -1, STATIC_ENT); -+ mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, NULL); -+ -+ mutex_unlock(&priv->reg_mutex); -+} -+ -+static int -+mt7530_port_mdb_del(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_mdb *mdb) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ const u8 *addr = mdb->addr; -+ u16 vid = mdb->vid; -+ u8 port_mask = 0; -+ int ret; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ mt7530_fdb_write(priv, vid, 0, addr, 0, STATIC_EMP); -+ if (!mt7530_fdb_cmd(priv, MT7530_FDB_READ, NULL)) -+ port_mask = (mt7530_read(priv, MT7530_ATRD) >> PORT_MAP) -+ & PORT_MAP_MASK; -+ -+ port_mask &= ~BIT(port); -+ mt7530_fdb_write(priv, vid, port_mask, addr, -1, -+ port_mask ? STATIC_ENT : STATIC_EMP); -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, NULL); -+ -+ mutex_unlock(&priv->reg_mutex); -+ -+ return ret; -+} -+ -+static int - mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid) - { - struct mt7530_dummy_poll p; -@@ -2794,11 +2862,15 @@ static const struct dsa_switch_ops mt753 - .port_change_mtu = mt7530_port_change_mtu, - .port_max_mtu = mt7530_port_max_mtu, - .port_stp_state_set = mt7530_stp_state_set, -+ .port_egress_floods = mt7530_port_egress_floods, - .port_bridge_join = mt7530_port_bridge_join, - .port_bridge_leave = mt7530_port_bridge_leave, - .port_fdb_add = mt7530_port_fdb_add, - .port_fdb_del = mt7530_port_fdb_del, - .port_fdb_dump = mt7530_port_fdb_dump, -+ .port_mdb_prepare = mt7530_port_mdb_prepare, -+ .port_mdb_add = mt7530_port_mdb_add, -+ .port_mdb_del = mt7530_port_mdb_del, - .port_vlan_filtering = mt7530_port_vlan_filtering, - .port_vlan_prepare = mt7530_port_vlan_prepare, - .port_vlan_add = mt7530_port_vlan_add, ---- a/net/dsa/tag_mtk.c -+++ b/net/dsa/tag_mtk.c -@@ -24,9 +24,6 @@ static struct sk_buff *mtk_tag_xmit(stru - struct dsa_port *dp = dsa_slave_to_port(dev); - u8 xmit_tpid; - u8 *mtk_tag; -- unsigned char *dest = eth_hdr(skb)->h_dest; -- bool is_multicast_skb = is_multicast_ether_addr(dest) && -- !is_broadcast_ether_addr(dest); - - /* Build the special tag after the MAC Source Address. If VLAN header - * is present, it's required that VLAN header and special tag is -@@ -55,10 +52,6 @@ static struct sk_buff *mtk_tag_xmit(stru - mtk_tag[0] = xmit_tpid; - mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; - -- /* Disable SA learning for multicast frames */ -- if (unlikely(is_multicast_skb)) -- mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS; -- - /* Tag control information is kept for 802.1Q */ - if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) { - mtk_tag[2] = 0; -@@ -74,9 +67,6 @@ static struct sk_buff *mtk_tag_rcv(struc - u16 hdr; - int port; - __be16 *phdr; -- unsigned char *dest = eth_hdr(skb)->h_dest; -- bool is_multicast_skb = is_multicast_ether_addr(dest) && -- !is_broadcast_ether_addr(dest); - - if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) - return NULL; -@@ -102,9 +92,7 @@ static struct sk_buff *mtk_tag_rcv(struc - if (!skb->dev) - return NULL; - -- /* Only unicast or broadcast frames are offloaded */ -- if (likely(!is_multicast_skb)) -- dsa_default_offload_fwd_mark(skb); -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } diff --git a/target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch b/target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch deleted file mode 100644 index 67e3ca91ed..0000000000 --- a/target/linux/generic/backport-5.15/771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch +++ /dev/null @@ -1,159 +0,0 @@ -From e40d2cca01893c1941f5959b14bb0cd0d4f4d099 Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Wed, 19 May 2021 11:31:59 +0800 -Subject: [PATCH] net: phy: add MediaTek Gigabit Ethernet PHY driver - -Add support for MediaTek Gigabit Ethernet PHYs found in MT7530 and -MT7531 switches. -The initialization procedure is from the vendor driver, but due to lack -of documentation, the function of some register values remains unknown. - -Signed-off-by: DENG Qingfang -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 5 ++ - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mediatek-ge.c | 116 ++++++++++++++++++++++++++++++++++ - 3 files changed, 122 insertions(+) - create mode 100644 drivers/net/phy/mediatek-ge.c - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -201,6 +201,11 @@ config MARVELL_10G_PHY - help - Support for the Marvell Alaska MV88X3310 and compatible PHYs. - -+config MEDIATEK_GE_PHY -+ tristate "MediaTek PHYs" -+ help -+ Supports the MediaTek switch integrated PHYs. -+ - config MICREL_PHY - tristate "Micrel PHYs" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c - obj-$(CONFIG_LXT_PHY) += lxt.o - obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o - obj-$(CONFIG_MARVELL_PHY) += marvell.o -+obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o - obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o - obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o - obj-$(CONFIG_MICREL_PHY) += micrel.o ---- /dev/null -+++ b/drivers/net/phy/mediatek-ge.c -@@ -0,0 +1,113 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+#include -+#include -+#include -+ -+#define MTK_T10_TEST_CONTROL 0x145 -+#define MTK_PHY_TP_MASK GENMASK(4, 3) -+#define MTK_PHY_TP_AUTO 0 -+#define MTK_PHY_TP_MDI 2 -+#define MTK_PHY_TP_MDIX 3 -+ -+#define MTK_EXT_PAGE_ACCESS 0x1f -+#define MTK_PHY_PAGE_STANDARD 0x0000 -+#define MTK_PHY_PAGE_EXTENDED 0x0001 -+#define MTK_PHY_PAGE_EXTENDED_2 0x0002 -+#define MTK_PHY_PAGE_EXTENDED_3 0x0003 -+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 -+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 -+ -+static int mtk_gephy_read_page(struct phy_device *phydev) -+{ -+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -+} -+ -+static int mtk_gephy_write_page(struct phy_device *phydev, int page) -+{ -+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); -+} -+ -+static void mtk_gephy_config_init(struct phy_device *phydev) -+{ -+ /* Disable EEE */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); -+ -+ /* Enable HW auto downshift */ -+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4)); -+ -+ /* Increase SlvDPSready time */ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ __phy_write(phydev, 0x10, 0xafae); -+ __phy_write(phydev, 0x12, 0x2f); -+ __phy_write(phydev, 0x10, 0x8fae); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ /* Adjust 100_mse_threshold */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff); -+ -+ /* Disable mcc */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300); -+} -+ -+static int mt7530_phy_config_init(struct phy_device *phydev) -+{ -+ mtk_gephy_config_init(phydev); -+ -+ /* Increase post_update_timer */ -+ phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b); -+ -+ return 0; -+} -+ -+static int mt7531_phy_config_init(struct phy_device *phydev) -+{ -+ mtk_gephy_config_init(phydev); -+ -+ /* PHY link down power saving enable */ -+ phy_set_bits(phydev, 0x17, BIT(4)); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300); -+ -+ /* Set TX Pair delay selection */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404); -+ -+ return 0; -+} -+ -+static struct phy_driver mtk_gephy_driver[] = { -+ { -+ PHY_ID_MATCH_EXACT(0x03a29412), -+ .name = "MediaTek MT7530 PHY", -+ .config_init = mt7530_phy_config_init, -+ /* Interrupts are handled by the switch, not the PHY -+ * itself. -+ */ -+ .config_intr = genphy_no_config_intr, -+ .ack_interrupt = genphy_no_ack_interrupt, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_gephy_read_page, -+ .write_page = mtk_gephy_write_page, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(0x03a29441), -+ .name = "MediaTek MT7531 PHY", -+ .config_init = mt7531_phy_config_init, -+ /* Interrupts are handled by the switch, not the PHY -+ * itself. -+ */ -+ .config_intr = genphy_no_config_intr, -+ .ack_interrupt = genphy_no_ack_interrupt, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_gephy_read_page, -+ .write_page = mtk_gephy_write_page, -+ }, -+}; -+ -+module_phy_driver(mtk_gephy_driver); -+ -+static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { -+ { PHY_ID_MATCH_VENDOR(0x03a29400) }, -+ { } -+}; diff --git a/target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch b/target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch deleted file mode 100644 index 9890015301..0000000000 --- a/target/linux/generic/backport-5.15/772-v5.14-net-dsa-mt7530-add-interrupt-support.patch +++ /dev/null @@ -1,425 +0,0 @@ -From ba751e28d44255744a30190faad0ca09b455c44d Mon Sep 17 00:00:00 2001 -From: DENG Qingfang -Date: Wed, 19 May 2021 11:32:00 +0800 -Subject: [PATCH] net: dsa: mt7530: add interrupt support - -Add support for MT7530 interrupt controller to handle internal PHYs. -In order to assign an IRQ number to each PHY, the registration of MDIO bus -is also done in this driver. - -Signed-off-by: DENG Qingfang -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Reviewed-by: Vladimir Oltean -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mt7530.c | 264 +++++++++++++++++++++++++++++++++++---- - drivers/net/dsa/mt7530.h | 20 ++- - 2 files changed, 256 insertions(+), 28 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -602,18 +603,14 @@ mt7530_mib_reset(struct dsa_switch *ds) - mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE); - } - --static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum) -+static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum) - { -- struct mt7530_priv *priv = ds->priv; -- - return mdiobus_read_nested(priv->bus, port, regnum); - } - --static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum, -+static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum, - u16 val) - { -- struct mt7530_priv *priv = ds->priv; -- - return mdiobus_write_nested(priv->bus, port, regnum, val); - } - -@@ -791,9 +788,8 @@ out: - } - - static int --mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) -+mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum) - { -- struct mt7530_priv *priv = ds->priv; - int devad; - int ret; - -@@ -809,10 +805,9 @@ mt7531_ind_phy_read(struct dsa_switch *d - } - - static int --mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, -+mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum, - u16 data) - { -- struct mt7530_priv *priv = ds->priv; - int devad; - int ret; - -@@ -828,6 +823,22 @@ mt7531_ind_phy_write(struct dsa_switch * - return ret; - } - -+static int -+mt753x_phy_read(struct mii_bus *bus, int port, int regnum) -+{ -+ struct mt7530_priv *priv = bus->priv; -+ -+ return priv->info->phy_read(priv, port, regnum); -+} -+ -+static int -+mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val) -+{ -+ struct mt7530_priv *priv = bus->priv; -+ -+ return priv->info->phy_write(priv, port, regnum, val); -+} -+ - static void - mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, - uint8_t *data) -@@ -1824,6 +1835,210 @@ mt7530_setup_gpio(struct mt7530_priv *pr - return devm_gpiochip_add_data(dev, gc, priv); - } - -+static irqreturn_t -+mt7530_irq_thread_fn(int irq, void *dev_id) -+{ -+ struct mt7530_priv *priv = dev_id; -+ bool handled = false; -+ u32 val; -+ int p; -+ -+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+ val = mt7530_mii_read(priv, MT7530_SYS_INT_STS); -+ mt7530_mii_write(priv, MT7530_SYS_INT_STS, val); -+ mutex_unlock(&priv->bus->mdio_lock); -+ -+ for (p = 0; p < MT7530_NUM_PHYS; p++) { -+ if (BIT(p) & val) { -+ unsigned int irq; -+ -+ irq = irq_find_mapping(priv->irq_domain, p); -+ handle_nested_irq(irq); -+ handled = true; -+ } -+ } -+ -+ return IRQ_RETVAL(handled); -+} -+ -+static void -+mt7530_irq_mask(struct irq_data *d) -+{ -+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); -+ -+ priv->irq_enable &= ~BIT(d->hwirq); -+} -+ -+static void -+mt7530_irq_unmask(struct irq_data *d) -+{ -+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); -+ -+ priv->irq_enable |= BIT(d->hwirq); -+} -+ -+static void -+mt7530_irq_bus_lock(struct irq_data *d) -+{ -+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); -+ -+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); -+} -+ -+static void -+mt7530_irq_bus_sync_unlock(struct irq_data *d) -+{ -+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); -+ -+ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); -+ mutex_unlock(&priv->bus->mdio_lock); -+} -+ -+static struct irq_chip mt7530_irq_chip = { -+ .name = KBUILD_MODNAME, -+ .irq_mask = mt7530_irq_mask, -+ .irq_unmask = mt7530_irq_unmask, -+ .irq_bus_lock = mt7530_irq_bus_lock, -+ .irq_bus_sync_unlock = mt7530_irq_bus_sync_unlock, -+}; -+ -+static int -+mt7530_irq_map(struct irq_domain *domain, unsigned int irq, -+ irq_hw_number_t hwirq) -+{ -+ irq_set_chip_data(irq, domain->host_data); -+ irq_set_chip_and_handler(irq, &mt7530_irq_chip, handle_simple_irq); -+ irq_set_nested_thread(irq, true); -+ irq_set_noprobe(irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops mt7530_irq_domain_ops = { -+ .map = mt7530_irq_map, -+ .xlate = irq_domain_xlate_onecell, -+}; -+ -+static void -+mt7530_setup_mdio_irq(struct mt7530_priv *priv) -+{ -+ struct dsa_switch *ds = priv->ds; -+ int p; -+ -+ for (p = 0; p < MT7530_NUM_PHYS; p++) { -+ if (BIT(p) & ds->phys_mii_mask) { -+ unsigned int irq; -+ -+ irq = irq_create_mapping(priv->irq_domain, p); -+ ds->slave_mii_bus->irq[p] = irq; -+ } -+ } -+} -+ -+static int -+mt7530_setup_irq(struct mt7530_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ struct device_node *np = dev->of_node; -+ int ret; -+ -+ if (!of_property_read_bool(np, "interrupt-controller")) { -+ dev_info(dev, "no interrupt support\n"); -+ return 0; -+ } -+ -+ priv->irq = of_irq_get(np, 0); -+ if (priv->irq <= 0) { -+ dev_err(dev, "failed to get parent IRQ: %d\n", priv->irq); -+ return priv->irq ? : -EINVAL; -+ } -+ -+ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, -+ &mt7530_irq_domain_ops, priv); -+ if (!priv->irq_domain) { -+ dev_err(dev, "failed to create IRQ domain\n"); -+ return -ENOMEM; -+ } -+ -+ /* This register must be set for MT7530 to properly fire interrupts */ -+ if (priv->id != ID_MT7531) -+ mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL); -+ -+ ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn, -+ IRQF_ONESHOT, KBUILD_MODNAME, priv); -+ if (ret) { -+ irq_domain_remove(priv->irq_domain); -+ dev_err(dev, "failed to request IRQ: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void -+mt7530_free_mdio_irq(struct mt7530_priv *priv) -+{ -+ int p; -+ -+ for (p = 0; p < MT7530_NUM_PHYS; p++) { -+ if (BIT(p) & priv->ds->phys_mii_mask) { -+ unsigned int irq; -+ -+ irq = irq_find_mapping(priv->irq_domain, p); -+ irq_dispose_mapping(irq); -+ } -+ } -+} -+ -+static void -+mt7530_free_irq_common(struct mt7530_priv *priv) -+{ -+ free_irq(priv->irq, priv); -+ irq_domain_remove(priv->irq_domain); -+} -+ -+static void -+mt7530_free_irq(struct mt7530_priv *priv) -+{ -+ mt7530_free_mdio_irq(priv); -+ mt7530_free_irq_common(priv); -+} -+ -+static int -+mt7530_setup_mdio(struct mt7530_priv *priv) -+{ -+ struct dsa_switch *ds = priv->ds; -+ struct device *dev = priv->dev; -+ struct mii_bus *bus; -+ static int idx; -+ int ret; -+ -+ bus = devm_mdiobus_alloc(dev); -+ if (!bus) -+ return -ENOMEM; -+ -+ ds->slave_mii_bus = bus; -+ bus->priv = priv; -+ bus->name = KBUILD_MODNAME "-mii"; -+ snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++); -+ bus->read = mt753x_phy_read; -+ bus->write = mt753x_phy_write; -+ bus->parent = dev; -+ bus->phy_mask = ~ds->phys_mii_mask; -+ -+ if (priv->irq) -+ mt7530_setup_mdio_irq(priv); -+ -+ ret = devm_mdiobus_register(dev, bus); -+ if (ret) { -+ dev_err(dev, "failed to register MDIO bus: %d\n", ret); -+ if (priv->irq) -+ mt7530_free_mdio_irq(priv); -+ } -+ -+ return ret; -+} -+ - static int - mt7530_setup(struct dsa_switch *ds) - { -@@ -2798,24 +3013,20 @@ static int - mt753x_setup(struct dsa_switch *ds) - { - struct mt7530_priv *priv = ds->priv; -+ int ret = priv->info->sw_setup(ds); - -- return priv->info->sw_setup(ds); --} -- --static int --mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) --{ -- struct mt7530_priv *priv = ds->priv; -+ if (ret) -+ return ret; - -- return priv->info->phy_read(ds, port, regnum); --} -+ ret = mt7530_setup_irq(priv); -+ if (ret) -+ return ret; - --static int --mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) --{ -- struct mt7530_priv *priv = ds->priv; -+ ret = mt7530_setup_mdio(priv); -+ if (ret && priv->irq) -+ mt7530_free_irq_common(priv); - -- return priv->info->phy_write(ds, port, regnum, val); -+ return ret; - } - - static int mt753x_get_mac_eee(struct dsa_switch *ds, int port, -@@ -2852,8 +3063,6 @@ static const struct dsa_switch_ops mt753 - .get_tag_protocol = mtk_get_tag_protocol, - .setup = mt753x_setup, - .get_strings = mt7530_get_strings, -- .phy_read = mt753x_phy_read, -- .phy_write = mt753x_phy_write, - .get_ethtool_stats = mt7530_get_ethtool_stats, - .get_sset_count = mt7530_get_sset_count, - .set_ageing_time = mt7530_set_ageing_time, -@@ -3036,6 +3245,9 @@ mt7530_remove(struct mdio_device *mdiode - dev_err(priv->dev, "Failed to disable io pwr: %d\n", - ret); - -+ if (priv->irq) -+ mt7530_free_irq(priv); -+ - dsa_unregister_switch(priv->ds); - mutex_destroy(&priv->reg_mutex); - } ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -7,6 +7,7 @@ - #define __MT7530_H - - #define MT7530_NUM_PORTS 7 -+#define MT7530_NUM_PHYS 5 - #define MT7530_CPU_PORT 6 - #define MT7530_NUM_FDB_RECORDS 2048 - #define MT7530_ALL_MEMBERS 0xff -@@ -401,6 +402,12 @@ enum mt7531_sgmii_force_duplex { - #define SYS_CTRL_SW_RST BIT(1) - #define SYS_CTRL_REG_RST BIT(0) - -+/* Register for system interrupt */ -+#define MT7530_SYS_INT_EN 0x7008 -+ -+/* Register for system interrupt status */ -+#define MT7530_SYS_INT_STS 0x700c -+ - /* Register for PHY Indirect Access Control */ - #define MT7531_PHY_IAC 0x701C - #define MT7531_PHY_ACS_ST BIT(31) -@@ -722,6 +729,8 @@ static const char *p5_intf_modes(unsigne - } - } - -+struct mt7530_priv; -+ - /* struct mt753x_info - This is the main data structure for holding the specific - * part for each supported device - * @sw_setup: Holding the handler to a device initialization -@@ -746,8 +755,8 @@ struct mt753x_info { - enum mt753x_id id; - - int (*sw_setup)(struct dsa_switch *ds); -- int (*phy_read)(struct dsa_switch *ds, int port, int regnum); -- int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); -+ int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); -+ int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); - int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); - int (*cpu_port_config)(struct dsa_switch *ds, int port); - bool (*phy_mode_supported)(struct dsa_switch *ds, int port, -@@ -781,6 +790,10 @@ struct mt753x_info { - * registers - * @p6_interface Holding the current port 6 interface - * @p5_intf_sel: Holding the current port 5 interface select -+ * -+ * @irq: IRQ number of the switch -+ * @irq_domain: IRQ domain of the switch irq_chip -+ * @irq_enable: IRQ enable bits, synced to SYS_INT_EN - */ - struct mt7530_priv { - struct device *dev; -@@ -802,6 +815,9 @@ struct mt7530_priv { - struct mt7530_port ports[MT7530_NUM_PORTS]; - /* protect among processes for registers access*/ - struct mutex reg_mutex; -+ int irq; -+ struct irq_domain *irq_domain; -+ u32 irq_enable; - }; - - struct mt7530_hw_vlan_entry { diff --git a/target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch b/target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch deleted file mode 100644 index d7df0685dd..0000000000 --- a/target/linux/generic/backport-5.15/774-v5.15-1-igc-remove-_I_PHY_ID-checking.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 7c496de538eebd8212dc2a3c9a468386b264d0d4 Mon Sep 17 00:00:00 2001 -From: Sasha Neftin -Date: Wed, 7 Jul 2021 08:14:40 +0300 -Subject: igc: Remove _I_PHY_ID checking - -i225 devices have only one PHY vendor. There is no point checking -_I_PHY_ID during the link establishment and auto-negotiation process. -This patch comes to clean up these pointless checkings. - -Signed-off-by: Sasha Neftin -Tested-by: Dvora Fuxbrumer -Signed-off-by: Tony Nguyen ---- - drivers/net/ethernet/intel/igc/igc_base.c | 10 +--------- - drivers/net/ethernet/intel/igc/igc_main.c | 3 +-- - drivers/net/ethernet/intel/igc/igc_phy.c | 6 ++---- - 3 files changed, 4 insertions(+), 15 deletions(-) - -(limited to 'drivers/net/ethernet/intel/igc') - ---- a/drivers/net/ethernet/intel/igc/igc_base.c -+++ b/drivers/net/ethernet/intel/igc/igc_base.c -@@ -187,15 +187,7 @@ static s32 igc_init_phy_params_base(stru - - igc_check_for_copper_link(hw); - -- /* Verify phy id and set remaining function pointers */ -- switch (phy->id) { -- case I225_I_PHY_ID: -- phy->type = igc_phy_i225; -- break; -- default: -- ret_val = -IGC_ERR_PHY; -- goto out; -- } -+ phy->type = igc_phy_i225; - - out: - return ret_val; ---- a/drivers/net/ethernet/intel/igc/igc_main.c -+++ b/drivers/net/ethernet/intel/igc/igc_main.c -@@ -4189,8 +4189,7 @@ bool igc_has_link(struct igc_adapter *ad - break; - } - -- if (hw->mac.type == igc_i225 && -- hw->phy.id == I225_I_PHY_ID) { -+ if (hw->mac.type == igc_i225) { - if (!netif_carrier_ok(adapter->netdev)) { - adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; - } else if (!(adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)) { ---- a/drivers/net/ethernet/intel/igc/igc_phy.c -+++ b/drivers/net/ethernet/intel/igc/igc_phy.c -@@ -249,8 +249,7 @@ static s32 igc_phy_setup_autoneg(struct - return ret_val; - } - -- if ((phy->autoneg_mask & ADVERTISE_2500_FULL) && -- hw->phy.id == I225_I_PHY_ID) { -+ if (phy->autoneg_mask & ADVERTISE_2500_FULL) { - /* Read the MULTI GBT AN Control Register - reg 7.32 */ - ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK << - MMD_DEVADDR_SHIFT) | -@@ -390,8 +389,7 @@ static s32 igc_phy_setup_autoneg(struct - ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, - mii_1000t_ctrl_reg); - -- if ((phy->autoneg_mask & ADVERTISE_2500_FULL) && -- hw->phy.id == I225_I_PHY_ID) -+ if (phy->autoneg_mask & ADVERTISE_2500_FULL) - ret_val = phy->ops.write_reg(hw, - (STANDARD_AN_REG_MASK << - MMD_DEVADDR_SHIFT) | diff --git a/target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch b/target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch deleted file mode 100644 index ad4d1bb0dc..0000000000 --- a/target/linux/generic/backport-5.15/774-v5.15-2-igc-remove-phy-type-checking.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 47bca7de6a4fb8dcb564c7ca14d885c91ed19e03 Mon Sep 17 00:00:00 2001 -From: Sasha Neftin -Date: Sat, 10 Jul 2021 20:57:50 +0300 -Subject: igc: Remove phy->type checking - -i225 devices have only one phy->type: copper. There is no point checking -phy->type during the igc_has_link method from the watchdog that -invoked every 2 seconds. -This patch comes to clean up these pointless checkings. - -Signed-off-by: Sasha Neftin -Tested-by: Dvora Fuxbrumer -Signed-off-by: Tony Nguyen ---- - drivers/net/ethernet/intel/igc/igc_main.c | 15 ++++----------- - 1 file changed, 4 insertions(+), 11 deletions(-) - -(limited to 'drivers/net/ethernet/intel/igc') - ---- a/drivers/net/ethernet/intel/igc/igc_main.c -+++ b/drivers/net/ethernet/intel/igc/igc_main.c -@@ -4177,17 +4177,10 @@ bool igc_has_link(struct igc_adapter *ad - * false until the igc_check_for_link establishes link - * for copper adapters ONLY - */ -- switch (hw->phy.media_type) { -- case igc_media_type_copper: -- if (!hw->mac.get_link_status) -- return true; -- hw->mac.ops.check_for_link(hw); -- link_active = !hw->mac.get_link_status; -- break; -- default: -- case igc_media_type_unknown: -- break; -- } -+ if (!hw->mac.get_link_status) -+ return true; -+ hw->mac.ops.check_for_link(hw); -+ link_active = !hw->mac.get_link_status; - - if (hw->mac.type == igc_i225) { - if (!netif_carrier_ok(adapter->netdev)) { diff --git a/target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch b/target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch deleted file mode 100644 index bec2867a48..0000000000 --- a/target/linux/generic/backport-5.15/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 586f04ce6a391419ca3cc9cef6b6f38570cede88 Mon Sep 17 00:00:00 2001 -From: Lee Jones -Date: Mon, 2 Nov 2020 11:45:04 +0000 -Subject: [PATCH] net: usb: r8152: Provide missing documentation for - some struct members - -commit 34e653efb602e0651867fb5ab14369b555a61dcd upstream. - -Fixes the following W=1 kernel build warning(s): - - drivers/net/usb/r8152.c:934: warning: Function parameter or member 'blk_hdr' not described in 'fw_mac' - drivers/net/usb/r8152.c:934: warning: Function parameter or member 'reserved' not described in 'fw_mac' - drivers/net/usb/r8152.c:947: warning: Function parameter or member 'blk_hdr' not described in 'fw_phy_patch_key' - drivers/net/usb/r8152.c:947: warning: Function parameter or member 'reserved' not described in 'fw_phy_patch_key' - drivers/net/usb/r8152.c:986: warning: Function parameter or member 'blk_hdr' not described in 'fw_phy_nc' - drivers/net/usb/r8152.c:986: warning: Function parameter or member 'mode_pre' not described in 'fw_phy_nc' - drivers/net/usb/r8152.c:986: warning: Function parameter or member 'mode_post' not described in 'fw_phy_nc' - drivers/net/usb/r8152.c:986: warning: Function parameter or member 'reserved' not described in 'fw_phy_nc' - -Signed-off-by: Lee Jones -Acked-by: Hayes Wang -Link: https://lore.kernel.org/r/20201102114512.1062724-23-lee.jones@linaro.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -899,6 +899,7 @@ struct fw_header { - * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. - * The layout of the firmware block is: - * + + . -+ * @blk_hdr: firmware descriptor (type, length) - * @fw_offset: offset of the firmware binary data. The start address of - * the data would be the address of struct fw_mac + @fw_offset. - * @fw_reg: the register to load the firmware. Depends on chip. -@@ -912,6 +913,7 @@ struct fw_header { - * @bp_num: the break point number which needs to be set for this firmware. - * Depends on the firmware. - * @bp: break points. Depends on firmware. -+ * @reserved: reserved space (unused) - * @fw_ver_reg: the register to store the fw version. - * @fw_ver_data: the firmware version of the current type. - * @info: additional information for debugging, and is followed by the -@@ -937,8 +939,10 @@ struct fw_mac { - /** - * struct fw_phy_patch_key - a firmware block used by RTL_FW_PHY_START. - * This is used to set patch key when loading the firmware of PHY. -+ * @blk_hdr: firmware descriptor (type, length) - * @key_reg: the register to write the patch key. - * @key_data: patch key. -+ * @reserved: reserved space (unused) - */ - struct fw_phy_patch_key { - struct fw_block blk_hdr; -@@ -951,6 +955,7 @@ struct fw_phy_patch_key { - * struct fw_phy_nc - a firmware block used by RTL_FW_PHY_NC. - * The layout of the firmware block is: - * + + . -+ * @blk_hdr: firmware descriptor (type, length) - * @fw_offset: offset of the firmware binary data. The start address of - * the data would be the address of struct fw_phy_nc + @fw_offset. - * @fw_reg: the register to load the firmware. Depends on chip. -@@ -961,6 +966,7 @@ struct fw_phy_patch_key { - * @mode_reg: the regitster of switching the mode. - * @mod_pre: the mode needing to be set before loading the firmware. - * @mod_post: the mode to be set when finishing to load the firmware. -+ * @reserved: reserved space (unused) - * @bp_start: the start register of break points. Depends on chip. - * @bp_num: the break point number which needs to be set for this firmware. - * Depends on the firmware. diff --git a/target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch b/target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch deleted file mode 100644 index aa2763e7de..0000000000 --- a/target/linux/generic/backport-5.15/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 5fcfa846181de6676509696c4cd7b60a22e74077 Mon Sep 17 00:00:00 2001 -From: Lee Jones -Date: Mon, 2 Nov 2020 11:45:09 +0000 -Subject: [PATCH] net: usb: r8152: Fix a couple of spelling errors in - fw_phy_nc's docs - -commit 9f07814d01ad085b2d9f1d55b4ce532fb2c27110 upstream. - -Fixes the following W=1 kernel build warning(s): - - drivers/net/usb/r8152.c:992: warning: Function parameter or member 'mode_pre' not described in 'fw_phy_nc' - drivers/net/usb/r8152.c:992: warning: Function parameter or member 'mode_post' not described in 'fw_phy_nc' - -Signed-off-by: Lee Jones -Acked-by: Hayes Wang -Link: https://lore.kernel.org/r/20201102114512.1062724-28-lee.jones@linaro.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -964,8 +964,8 @@ struct fw_phy_patch_key { - * @patch_en_addr: the register of enabling patch mode. Depends on chip. - * @patch_en_value: patch mode enabled mask. Depends on the firmware. - * @mode_reg: the regitster of switching the mode. -- * @mod_pre: the mode needing to be set before loading the firmware. -- * @mod_post: the mode to be set when finishing to load the firmware. -+ * @mode_pre: the mode needing to be set before loading the firmware. -+ * @mode_post: the mode to be set when finishing to load the firmware. - * @reserved: reserved space (unused) - * @bp_start: the start register of break points. Depends on chip. - * @bp_num: the break point number which needs to be set for this firmware. diff --git a/target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch b/target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch deleted file mode 100644 index 789de8e6fd..0000000000 --- a/target/linux/generic/backport-5.15/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch +++ /dev/null @@ -1,320 +0,0 @@ -From 0ef50460f7f053bd2a911ec53e01bfda646a5574 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 4 Nov 2020 10:19:22 +0800 -Subject: [PATCH] net/usb/r8153_ecm: support ECM mode for RTL8153 - -commit c1aedf015ebdd0232757a66e2daccf1246bd609c upstream. - -Support ECM mode based on cdc_ether with relative mii functions, -when CONFIG_USB_RTL8152 is not set, or the device is not supported -by r8152 driver. - -Both r8152 and r8153_ecm would check the return value of -rtl8152_get_version() in porbe(). If rtl8152_get_version() -return none zero value, the r8152 is used for the device -with vendor mode. Otherwise, the r8153_ecm is used for the -device with ECM mode. - -Signed-off-by: Hayes Wang -Link: https://lore.kernel.org/r/1394712342-15778-392-Taiwan-albertk@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/Makefile | 2 +- - drivers/net/usb/r8152.c | 30 +------ - drivers/net/usb/r8153_ecm.c | 162 ++++++++++++++++++++++++++++++++++++ - include/linux/usb/r8152.h | 37 ++++++++ - 4 files changed, 204 insertions(+), 27 deletions(-) - create mode 100644 drivers/net/usb/r8153_ecm.c - create mode 100644 include/linux/usb/r8152.h - ---- a/drivers/net/usb/Makefile -+++ b/drivers/net/usb/Makefile -@@ -13,7 +13,7 @@ obj-$(CONFIG_USB_LAN78XX) += lan78xx.o - obj-$(CONFIG_USB_NET_AX8817X) += asix.o - asix-y := asix_devices.o asix_common.o ax88172a.o - obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o --obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o -+obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r8153_ecm.o - obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o - obj-$(CONFIG_USB_NET_DM9601) += dm9601.o - obj-$(CONFIG_USB_NET_SR9700) += sr9700.o ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - /* Information for net-next */ - #define NETNEXT_VERSION "11" -@@ -654,18 +655,6 @@ enum rtl_register_content { - - #define INTR_LINK 0x0004 - --#define RTL8152_REQT_READ 0xc0 --#define RTL8152_REQT_WRITE 0x40 --#define RTL8152_REQ_GET_REGS 0x05 --#define RTL8152_REQ_SET_REGS 0x05 -- --#define BYTE_EN_DWORD 0xff --#define BYTE_EN_WORD 0x33 --#define BYTE_EN_BYTE 0x11 --#define BYTE_EN_SIX_BYTES 0x3f --#define BYTE_EN_START_MASK 0x0f --#define BYTE_EN_END_MASK 0xf0 -- - #define RTL8153_MAX_PACKET 9216 /* 9K */ - #define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \ - ETH_FCS_LEN) -@@ -690,21 +679,9 @@ enum rtl8152_flags { - LENOVO_MACPASSTHRU, - }; - --/* Define these values to match your device */ --#define VENDOR_ID_REALTEK 0x0bda --#define VENDOR_ID_MICROSOFT 0x045e --#define VENDOR_ID_SAMSUNG 0x04e8 --#define VENDOR_ID_LENOVO 0x17ef --#define VENDOR_ID_LINKSYS 0x13b1 --#define VENDOR_ID_NVIDIA 0x0955 --#define VENDOR_ID_TPLINK 0x2357 -- - #define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2 0x3082 - #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2 0xa387 - --#define MCU_TYPE_PLA 0x0100 --#define MCU_TYPE_USB 0x0000 -- - struct tally_counter { - __le64 tx_packets; - __le64 rx_packets; -@@ -6625,7 +6602,7 @@ static int rtl_fw_init(struct r8152 *tp) - return 0; - } - --static u8 rtl_get_version(struct usb_interface *intf) -+u8 rtl8152_get_version(struct usb_interface *intf) - { - struct usb_device *udev = interface_to_usbdev(intf); - u32 ocp_data = 0; -@@ -6683,12 +6660,13 @@ static u8 rtl_get_version(struct usb_int - - return version; - } -+EXPORT_SYMBOL_GPL(rtl8152_get_version); - - static int rtl8152_probe(struct usb_interface *intf, - const struct usb_device_id *id) - { - struct usb_device *udev = interface_to_usbdev(intf); -- u8 version = rtl_get_version(intf); -+ u8 version = rtl8152_get_version(intf); - struct r8152 *tp; - struct net_device *netdev; - int ret; ---- /dev/null -+++ b/drivers/net/usb/r8153_ecm.c -@@ -0,0 +1,162 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define OCP_BASE 0xe86c -+ -+static int pla_read_word(struct usbnet *dev, u16 index) -+{ -+ u16 byen = BYTE_EN_WORD; -+ u8 shift = index & 2; -+ __le32 tmp; -+ int ret; -+ -+ if (shift) -+ byen <<= shift; -+ -+ index &= ~3; -+ -+ ret = usbnet_read_cmd(dev, RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, index, -+ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp)); -+ if (ret < 0) -+ goto out; -+ -+ ret = __le32_to_cpu(tmp); -+ ret >>= (shift * 8); -+ ret &= 0xffff; -+ -+out: -+ return ret; -+} -+ -+static int pla_write_word(struct usbnet *dev, u16 index, u32 data) -+{ -+ u32 mask = 0xffff; -+ u16 byen = BYTE_EN_WORD; -+ u8 shift = index & 2; -+ __le32 tmp; -+ int ret; -+ -+ data &= mask; -+ -+ if (shift) { -+ byen <<= shift; -+ mask <<= (shift * 8); -+ data <<= (shift * 8); -+ } -+ -+ index &= ~3; -+ -+ ret = usbnet_read_cmd(dev, RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, index, -+ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp)); -+ -+ if (ret < 0) -+ goto out; -+ -+ data |= __le32_to_cpu(tmp) & ~mask; -+ tmp = __cpu_to_le32(data); -+ -+ ret = usbnet_write_cmd(dev, RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, index, -+ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp)); -+ -+out: -+ return ret; -+} -+ -+static int r8153_ecm_mdio_read(struct net_device *netdev, int phy_id, int reg) -+{ -+ struct usbnet *dev = netdev_priv(netdev); -+ int ret; -+ -+ ret = pla_write_word(dev, OCP_BASE, 0xa000); -+ if (ret < 0) -+ goto out; -+ -+ ret = pla_read_word(dev, 0xb400 + reg * 2); -+ -+out: -+ return ret; -+} -+ -+static void r8153_ecm_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) -+{ -+ struct usbnet *dev = netdev_priv(netdev); -+ int ret; -+ -+ ret = pla_write_word(dev, OCP_BASE, 0xa000); -+ if (ret < 0) -+ return; -+ -+ ret = pla_write_word(dev, 0xb400 + reg * 2, val); -+} -+ -+static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) -+{ -+ int status; -+ -+ status = usbnet_cdc_bind(dev, intf); -+ if (status < 0) -+ return status; -+ -+ dev->mii.dev = dev->net; -+ dev->mii.mdio_read = r8153_ecm_mdio_read; -+ dev->mii.mdio_write = r8153_ecm_mdio_write; -+ dev->mii.reg_num_mask = 0x1f; -+ dev->mii.supports_gmii = 1; -+ -+ return status; -+} -+ -+static const struct driver_info r8153_info = { -+ .description = "RTL8153 ECM Device", -+ .flags = FLAG_ETHER, -+ .bind = r8153_bind, -+ .unbind = usbnet_cdc_unbind, -+ .status = usbnet_cdc_status, -+ .manage_power = usbnet_manage_power, -+}; -+ -+static const struct usb_device_id products[] = { -+{ -+ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_REALTEK, 0x8153, USB_CLASS_COMM, -+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -+ .driver_info = (unsigned long)&r8153_info, -+}, -+ -+ { }, /* END */ -+}; -+MODULE_DEVICE_TABLE(usb, products); -+ -+static int rtl8153_ecm_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+#if IS_REACHABLE(CONFIG_USB_RTL8152) -+ if (rtl8152_get_version(intf)) -+ return -ENODEV; -+#endif -+ -+ return usbnet_probe(intf, id); -+} -+ -+static struct usb_driver r8153_ecm_driver = { -+ .name = "r8153_ecm", -+ .id_table = products, -+ .probe = rtl8153_ecm_probe, -+ .disconnect = usbnet_disconnect, -+ .suspend = usbnet_suspend, -+ .resume = usbnet_resume, -+ .reset_resume = usbnet_resume, -+ .supports_autosuspend = 1, -+ .disable_hub_initiated_lpm = 1, -+}; -+ -+module_usb_driver(r8153_ecm_driver); -+ -+MODULE_AUTHOR("Hayes Wang"); -+MODULE_DESCRIPTION("Realtek USB ECM device"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/include/linux/usb/r8152.h -@@ -0,0 +1,37 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2020 Realtek Semiconductor Corp. All rights reserved. -+ */ -+ -+#ifndef __LINUX_R8152_H -+#define __LINUX_R8152_H -+ -+#define RTL8152_REQT_READ 0xc0 -+#define RTL8152_REQT_WRITE 0x40 -+#define RTL8152_REQ_GET_REGS 0x05 -+#define RTL8152_REQ_SET_REGS 0x05 -+ -+#define BYTE_EN_DWORD 0xff -+#define BYTE_EN_WORD 0x33 -+#define BYTE_EN_BYTE 0x11 -+#define BYTE_EN_SIX_BYTES 0x3f -+#define BYTE_EN_START_MASK 0x0f -+#define BYTE_EN_END_MASK 0xf0 -+ -+#define MCU_TYPE_PLA 0x0100 -+#define MCU_TYPE_USB 0x0000 -+ -+/* Define these values to match your device */ -+#define VENDOR_ID_REALTEK 0x0bda -+#define VENDOR_ID_MICROSOFT 0x045e -+#define VENDOR_ID_SAMSUNG 0x04e8 -+#define VENDOR_ID_LENOVO 0x17ef -+#define VENDOR_ID_LINKSYS 0x13b1 -+#define VENDOR_ID_NVIDIA 0x0955 -+#define VENDOR_ID_TPLINK 0x2357 -+ -+#if IS_REACHABLE(CONFIG_USB_RTL8152) -+extern u8 rtl8152_get_version(struct usb_interface *intf); -+#endif -+ -+#endif /* __LINUX_R8152_H */ diff --git a/target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch b/target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch deleted file mode 100644 index b625d5ea99..0000000000 --- a/target/linux/generic/backport-5.15/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 90f1afc7f96c8f7cf19c82e5f4b39e61a63b053d Mon Sep 17 00:00:00 2001 -From: Emil Renner Berthing -Date: Sun, 31 Jan 2021 00:47:29 +0100 -Subject: [PATCH] net: usb: r8152: use new tasklet API - -commit f3163f1cb87141c7a41a15a5d4c98b353f807b04 upstream. - -This converts the driver to use the new tasklet API introduced in -commit 12cc923f1ccc ("tasklet: Introduce new initialization API") - -Signed-off-by: Emil Renner Berthing -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -2394,11 +2394,9 @@ static void tx_bottom(struct r8152 *tp) - } while (res == 0); - } - --static void bottom_half(unsigned long data) -+static void bottom_half(struct tasklet_struct *t) - { -- struct r8152 *tp; -- -- tp = (struct r8152 *)data; -+ struct r8152 *tp = from_tasklet(tp, t, tx_tl); - - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - return; -@@ -6718,7 +6716,7 @@ static int rtl8152_probe(struct usb_inte - mutex_init(&tp->control); - INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); - INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); -- tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp); -+ tasklet_setup(&tp->tx_tl, bottom_half); - tasklet_disable(&tp->tx_tl); - - netdev->netdev_ops = &rtl8152_netdev_ops; diff --git a/target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch b/target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch deleted file mode 100644 index bbb2b5c0c9..0000000000 --- a/target/linux/generic/backport-5.15/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 86b98abf4f8c691c260c5113d6a2d32f5377caca Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 3 Feb 2021 17:14:28 +0800 -Subject: [PATCH] r8152: replace several functions about phy patch - request - -commit a08c0d309d8c078d22717d815cf9853f6f2c07bd upstream. - -Replace r8153_patch_request() with rtl_phy_patch_request(). -Replace r8153_pre_ram_code() with rtl_pre_ram_code(). -Replace r8153_post_ram_code() with rtl_post_ram_code(). -Add rtl_patch_key_set(). - -The new functions have an additional parameter. It is used to wait -the patch request command finished. When the PHY is resumed from -the state of power cut, the PHY is at a safe mode and the -OCP_PHY_PATCH_STAT wouldn't be updated. For this situation, it is -safe to set patch request command without waiting OCP_PHY_PATCH_STAT. - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 84 ++++++++++++++++++++++++----------------- - 1 file changed, 50 insertions(+), 34 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -3444,59 +3444,76 @@ static void rtl_clear_bp(struct r8152 *t - ocp_write_word(tp, type, PLA_BP_BA, 0); - } - --static int r8153_patch_request(struct r8152 *tp, bool request) -+static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) - { -- u16 data; -+ u16 data, check; - int i; - - data = ocp_reg_read(tp, OCP_PHY_PATCH_CMD); -- if (request) -+ if (request) { - data |= PATCH_REQUEST; -- else -+ check = 0; -+ } else { - data &= ~PATCH_REQUEST; -+ check = PATCH_READY; -+ } - ocp_reg_write(tp, OCP_PHY_PATCH_CMD, data); - -- for (i = 0; request && i < 5000; i++) { -+ for (i = 0; wait && i < 5000; i++) { -+ u32 ocp_data; -+ - usleep_range(1000, 2000); -- if (ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY) -+ ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT); -+ if ((ocp_data & PATCH_READY) ^ check) - break; - } - -- if (request && !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { -- netif_err(tp, drv, tp->netdev, "patch request fail\n"); -- r8153_patch_request(tp, false); -+ if (request && wait && -+ !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { -+ dev_err(&tp->intf->dev, "PHY patch request fail\n"); -+ rtl_phy_patch_request(tp, false, false); - return -ETIME; - } else { - return 0; - } - } - --static int r8153_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key) -+static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key) - { -- if (r8153_patch_request(tp, true)) { -- dev_err(&tp->intf->dev, "patch request fail\n"); -- return -ETIME; -- } -+ if (patch_key && key_addr) { -+ sram_write(tp, key_addr, patch_key); -+ sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); -+ } else if (key_addr) { -+ u16 data; - -- sram_write(tp, key_addr, patch_key); -- sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); -+ sram_write(tp, 0x0000, 0x0000); - -- return 0; -+ data = ocp_reg_read(tp, OCP_PHY_LOCK); -+ data &= ~PATCH_LOCK; -+ ocp_reg_write(tp, OCP_PHY_LOCK, data); -+ -+ sram_write(tp, key_addr, 0x0000); -+ } else { -+ WARN_ON_ONCE(1); -+ } - } - --static int r8153_post_ram_code(struct r8152 *tp, u16 key_addr) -+static int -+rtl_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key, bool wait) - { -- u16 data; -+ if (rtl_phy_patch_request(tp, true, wait)) -+ return -ETIME; - -- sram_write(tp, 0x0000, 0x0000); -+ rtl_patch_key_set(tp, key_addr, patch_key); - -- data = ocp_reg_read(tp, OCP_PHY_LOCK); -- data &= ~PATCH_LOCK; -- ocp_reg_write(tp, OCP_PHY_LOCK, data); -+ return 0; -+} - -- sram_write(tp, key_addr, 0x0000); -+static int rtl_post_ram_code(struct r8152 *tp, u16 key_addr, bool wait) -+{ -+ rtl_patch_key_set(tp, key_addr, 0); - -- r8153_patch_request(tp, false); -+ rtl_phy_patch_request(tp, false, wait); - - ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); - -@@ -3981,7 +3998,7 @@ static void rtl8152_fw_mac_apply(struct - dev_dbg(&tp->intf->dev, "successfully applied %s\n", mac->info); - } - --static void rtl8152_apply_firmware(struct r8152 *tp) -+static void rtl8152_apply_firmware(struct r8152 *tp, bool power_cut) - { - struct rtl_fw *rtl_fw = &tp->rtl_fw; - const struct firmware *fw; -@@ -4012,12 +4029,11 @@ static void rtl8152_apply_firmware(struc - case RTL_FW_PHY_START: - key = (struct fw_phy_patch_key *)block; - key_addr = __le16_to_cpu(key->key_reg); -- r8153_pre_ram_code(tp, key_addr, -- __le16_to_cpu(key->key_data)); -+ rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); - break; - case RTL_FW_PHY_STOP: - WARN_ON(!key_addr); -- r8153_post_ram_code(tp, key_addr); -+ rtl_post_ram_code(tp, key_addr, !power_cut); - break; - case RTL_FW_PHY_NC: - rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); -@@ -4222,7 +4238,7 @@ static void rtl8152_disable(struct r8152 - - static void r8152b_hw_phy_cfg(struct r8152 *tp) - { -- rtl8152_apply_firmware(tp); -+ rtl8152_apply_firmware(tp, false); - rtl_eee_enable(tp, tp->eee_en); - r8152_aldps_en(tp, true); - r8152b_enable_fc(tp); -@@ -4504,7 +4520,7 @@ static void r8153_hw_phy_cfg(struct r815 - /* disable EEE before updating the PHY parameters */ - rtl_eee_enable(tp, false); - -- rtl8152_apply_firmware(tp); -+ rtl8152_apply_firmware(tp, false); - - if (tp->version == RTL_VER_03) { - data = ocp_reg_read(tp, OCP_EEE_CFG); -@@ -4578,7 +4594,7 @@ static void r8153b_hw_phy_cfg(struct r81 - /* disable EEE before updating the PHY parameters */ - rtl_eee_enable(tp, false); - -- rtl8152_apply_firmware(tp); -+ rtl8152_apply_firmware(tp, false); - - r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); - -@@ -4619,7 +4635,7 @@ static void r8153b_hw_phy_cfg(struct r81 - ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); - - /* Advnace EEE */ -- if (!r8153_patch_request(tp, true)) { -+ if (!rtl_phy_patch_request(tp, true, true)) { - data = ocp_reg_read(tp, OCP_POWER_CFG); - data |= EEE_CLKDIV_EN; - ocp_reg_write(tp, OCP_POWER_CFG, data); -@@ -4636,7 +4652,7 @@ static void r8153b_hw_phy_cfg(struct r81 - ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5)); - tp->ups_info._250m_ckdiv = true; - -- r8153_patch_request(tp, false); -+ rtl_phy_patch_request(tp, false, true); - } - - if (tp->eee_en) diff --git a/target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch b/target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch deleted file mode 100644 index b28e89a43f..0000000000 --- a/target/linux/generic/backport-5.15/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 29a61d8564ad3439d03c7ec135016a4e70072af1 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Wed, 3 Feb 2021 17:14:29 +0800 -Subject: [PATCH] r8152: adjust the flow of power cut for RTL8153B - -commit 80fd850b31f09263ad175b2f640d5c5c6f76ed41 upstream. - -For runtime resuming, the RTL8153B may be resumed from the state -of power cut, when enabling the feature of UPS. Then, the PHY -would be reset, so it is necessary to be initailized again. - -Besides, the USB_U1U2_TIMER also has to be set again, so I move -it from r8153b_init() to r8153b_hw_phy_cfg(). - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 68 ++++++++++++++++++++++++----------------- - 1 file changed, 40 insertions(+), 28 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -1372,6 +1372,10 @@ void write_mii_word(struct net_device *n - static int - r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags); - -+static int -+rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, -+ u32 advertising); -+ - static int rtl8152_set_mac_address(struct net_device *netdev, void *p) - { - struct r8152 *tp = netdev_priv(netdev); -@@ -3183,8 +3187,6 @@ static void r8153b_ups_en(struct r8152 * - ocp_data |= BIT(0); - ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); - } else { -- u16 data; -- - ocp_data &= ~(UPS_EN | USP_PREWAKE); - ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); - -@@ -3192,31 +3194,20 @@ static void r8153b_ups_en(struct r8152 * - ocp_data &= ~BIT(0); - ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); - -- ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); -- ocp_data &= ~PCUT_STATUS; -- ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); -+ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { -+ int i; - -- data = r8153_phy_status(tp, 0); -+ for (i = 0; i < 500; i++) { -+ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & -+ AUTOLOAD_DONE) -+ break; -+ msleep(20); -+ } - -- switch (data) { -- case PHY_STAT_PWRDN: -- case PHY_STAT_EXT_INIT: -- r8153b_green_en(tp, -- test_bit(GREEN_ETHERNET, &tp->flags)); -- -- data = r8152_mdio_read(tp, MII_BMCR); -- data &= ~BMCR_PDOWN; -- data |= BMCR_RESET; -- r8152_mdio_write(tp, MII_BMCR, data); -+ tp->rtl_ops.hw_phy_cfg(tp); - -- data = r8153_phy_status(tp, PHY_STAT_LAN_ON); -- fallthrough; -- -- default: -- if (data != PHY_STAT_LAN_ON) -- netif_warn(tp, link, tp->netdev, -- "PHY not ready"); -- break; -+ rtl8152_set_speed(tp, tp->autoneg, tp->speed, -+ tp->duplex, tp->advertising); - } - } - } -@@ -4588,13 +4579,37 @@ static void r8153b_hw_phy_cfg(struct r81 - u32 ocp_data; - u16 data; - -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); -+ if (ocp_data & PCUT_STATUS) { -+ ocp_data &= ~PCUT_STATUS; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); -+ } -+ - /* disable ALDPS before updating the PHY parameters */ - r8153_aldps_en(tp, false); - - /* disable EEE before updating the PHY parameters */ - rtl_eee_enable(tp, false); - -- rtl8152_apply_firmware(tp, false); -+ /* U1/U2/L1 idle timer. 500 us */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); -+ -+ data = r8153_phy_status(tp, 0); -+ -+ switch (data) { -+ case PHY_STAT_PWRDN: -+ case PHY_STAT_EXT_INIT: -+ rtl8152_apply_firmware(tp, true); -+ -+ data = r8152_mdio_read(tp, MII_BMCR); -+ data &= ~BMCR_PDOWN; -+ r8152_mdio_write(tp, MII_BMCR, data); -+ break; -+ case PHY_STAT_LAN_ON: -+ default: -+ rtl8152_apply_firmware(tp, false); -+ break; -+ } - - r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); - -@@ -5543,9 +5558,6 @@ static void r8153b_init(struct r8152 *tp - /* MSC timer = 0xfff * 8ms = 32760 ms */ - ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); - -- /* U1/U2/L1 idle timer. 500 us */ -- ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); -- - r8153b_power_cut_en(tp, false); - r8153b_ups_en(tp, false); - r8153_queue_wake(tp, false); diff --git a/target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch b/target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch deleted file mode 100644 index 8cf91c3893..0000000000 --- a/target/linux/generic/backport-5.15/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 69b4339c0b9f3edc6a8f681f05efaaf4add1bb0e Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 19 Feb 2021 17:04:40 +0800 -Subject: [PATCH] r8152: enable U1/U2 for USB_SPEED_SUPER - -commit 7a0ae61acde2cebd69665837170405eced86a6c7 upstream. - -U1/U2 shoued be enabled for USB 3.0 or later. The USB 2.0 doesn't -support it. - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -3336,7 +3336,7 @@ static void rtl8153b_runtime_enable(stru - r8153b_ups_en(tp, false); - r8153_queue_wake(tp, false); - rtl_runtime_suspend_enable(tp, false); -- if (tp->udev->speed != USB_SPEED_HIGH) -+ if (tp->udev->speed >= USB_SPEED_SUPER) - r8153b_u1u2en(tp, true); - } - } -@@ -5029,7 +5029,7 @@ static void rtl8153b_up(struct r8152 *tp - - r8153_aldps_en(tp, true); - -- if (tp->udev->speed != USB_SPEED_HIGH) -+ if (tp->udev->speed >= USB_SPEED_SUPER) - r8153b_u1u2en(tp, true); - } - -@@ -5571,8 +5571,9 @@ static void r8153b_init(struct r8152 *tp - ocp_data |= POLL_LINK_CHG; - ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); - -- if (tp->udev->speed != USB_SPEED_HIGH) -+ if (tp->udev->speed >= USB_SPEED_SUPER) - r8153b_u1u2en(tp, true); -+ - usb_enable_lpm(tp->udev); - - /* MAC clock speed down */ diff --git a/target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch b/target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch deleted file mode 100644 index 5bc4e2b0a1..0000000000 --- a/target/linux/generic/backport-5.15/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e78b75f5be204a0a235da995d01c778dc282bb42 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 19 Feb 2021 17:04:41 +0800 -Subject: [PATCH] r8152: check if the pointer of the function exists - -commit c79515e47935c747282c6ed2ee5b2ef039756eeb upstream. - -Return error code if autosuspend_en, eee_get, or eee_set don't exist. - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -5758,6 +5758,9 @@ static int rtl8152_runtime_suspend(struc - struct net_device *netdev = tp->netdev; - int ret = 0; - -+ if (!tp->rtl_ops.autosuspend_en) -+ return -EBUSY; -+ - set_bit(SELECTIVE_SUSPEND, &tp->flags); - smp_mb__after_atomic(); - -@@ -6157,6 +6160,11 @@ rtl_ethtool_get_eee(struct net_device *n - struct r8152 *tp = netdev_priv(net); - int ret; - -+ if (!tp->rtl_ops.eee_get) { -+ ret = -EOPNOTSUPP; -+ goto out; -+ } -+ - ret = usb_autopm_get_interface(tp->intf); - if (ret < 0) - goto out; -@@ -6179,6 +6187,11 @@ rtl_ethtool_set_eee(struct net_device *n - struct r8152 *tp = netdev_priv(net); - int ret; - -+ if (!tp->rtl_ops.eee_set) { -+ ret = -EOPNOTSUPP; -+ goto out; -+ } -+ - ret = usb_autopm_get_interface(tp->intf); - if (ret < 0) - goto out; diff --git a/target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch b/target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch deleted file mode 100644 index 967b4ccc16..0000000000 --- a/target/linux/generic/backport-5.15/788-v5.12-r8152-replace-netif_err-with-dev_err.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 38e44c7926512cff0b2809dc329de2a8e769e523 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 19 Feb 2021 17:04:42 +0800 -Subject: [PATCH] r8152: replace netif_err with dev_err - -commit 156c3207611262266f0eea589ac3f00c5657320e upstream. - -Some messages are before calling register_netdev(), so replace -netif_err() with dev_err(). - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -6594,7 +6594,7 @@ static int rtl_ops_init(struct r8152 *tp - - default: - ret = -ENODEV; -- netif_err(tp, probe, tp->netdev, "Unknown Device\n"); -+ dev_err(&tp->intf->dev, "Unknown Device\n"); - break; - } - -@@ -6851,7 +6851,7 @@ static int rtl8152_probe(struct usb_inte - - ret = register_netdev(netdev); - if (ret != 0) { -- netif_err(tp, probe, netdev, "couldn't register the device\n"); -+ dev_err(&intf->dev, "couldn't register the device\n"); - goto out1; - } - diff --git a/target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch b/target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch deleted file mode 100644 index c49a4ce5b6..0000000000 --- a/target/linux/generic/backport-5.15/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 260814de2d6cb958767785ffcb2e76915d1be32b Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 19 Feb 2021 17:04:43 +0800 -Subject: [PATCH] r8152: spilt rtl_set_eee_plus and r8153b_green_en - -commit 40fa7568ac230446d888b7ad402cff9e20fe3ad5 upstream. - -Add rtl_eee_plus_en() and rtl_green_en(). - -Signed-off-by: Hayes Wang -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/r8152.c | 43 ++++++++++++++++++++++++++--------------- - 1 file changed, 27 insertions(+), 16 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -2633,21 +2633,24 @@ static inline u8 rtl8152_get_speed(struc - return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); - } - --static void rtl_set_eee_plus(struct r8152 *tp) -+static void rtl_eee_plus_en(struct r8152 *tp, bool enable) - { - u32 ocp_data; -- u8 speed; - -- speed = rtl8152_get_speed(tp); -- if (speed & _10bps) { -- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); -+ if (enable) - ocp_data |= EEEP_CR_EEEP_TX; -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); -- } else { -- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); -+ else - ocp_data &= ~EEEP_CR_EEEP_TX; -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); -- } -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); -+} -+ -+static void rtl_set_eee_plus(struct r8152 *tp) -+{ -+ if (rtl8152_get_speed(tp) & _10bps) -+ rtl_eee_plus_en(tp, true); -+ else -+ rtl_eee_plus_en(tp, false); - } - - static void rxdy_gated_en(struct r8152 *tp, bool enable) -@@ -3128,10 +3131,22 @@ static void r8153b_ups_flags(struct r815 - ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); - } - --static void r8153b_green_en(struct r8152 *tp, bool enable) -+static void rtl_green_en(struct r8152 *tp, bool enable) - { - u16 data; - -+ data = sram_read(tp, SRAM_GREEN_CFG); -+ if (enable) -+ data |= GREEN_ETH_EN; -+ else -+ data &= ~GREEN_ETH_EN; -+ sram_write(tp, SRAM_GREEN_CFG, data); -+ -+ tp->ups_info.green = enable; -+} -+ -+static void r8153b_green_en(struct r8152 *tp, bool enable) -+{ - if (enable) { - sram_write(tp, 0x8045, 0); /* 10M abiq&ldvbias */ - sram_write(tp, 0x804d, 0x1222); /* 100M short abiq&ldvbias */ -@@ -3142,11 +3157,7 @@ static void r8153b_green_en(struct r8152 - sram_write(tp, 0x805d, 0x2444); /* 1000M short abiq&ldvbias */ - } - -- data = sram_read(tp, SRAM_GREEN_CFG); -- data |= GREEN_ETH_EN; -- sram_write(tp, SRAM_GREEN_CFG, data); -- -- tp->ups_info.green = enable; -+ rtl_green_en(tp, true); - } - - static u16 r8153_phy_status(struct r8152 *tp, u16 desired) diff --git a/target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch b/target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch deleted file mode 100644 index f2593e8f00..0000000000 --- a/target/linux/generic/backport-5.15/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch +++ /dev/null @@ -1,75 +0,0 @@ -From f1bbbb260a8016373adf239c716d2da90e6ced0b Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 16 Apr 2021 16:04:32 +0800 -Subject: [PATCH] r8152: set inter fram gap time depending on speed - -commit 5133bcc7481528e36fff0a3b056601efb704fb32 upstream. - -Set the maximum inter frame gap time (144ns) for speed 10M/half and -100M/half. It improves the performance for those speeds. And, there -is no effect for the other speeds. - -For 10M/half and 100M/half, the fast inter frame gap time let the -device couldn't use the feature of the aggregation effectively, -because the transfer would be completed fastly. Therefore, use the -maximum value to improve the effect of the aggregation. However, you -may not feel the improvement for fast CPUs, because they compensate -for the effect of the aggregation. - -Signed-off-by: Hayes Wang -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -250,6 +250,9 @@ - - /* PLA_TCR1 */ - #define VERSION_MASK 0x7cf0 -+#define IFG_MASK (BIT(3) | BIT(9) | BIT(8)) -+#define IFG_144NS BIT(9) -+#define IFG_96NS (BIT(9) | BIT(8)) - - /* PLA_MTPS */ - #define MTPS_JUMBO (12 * 1024 / 64) -@@ -2748,6 +2751,29 @@ static int rtl_stop_rx(struct r8152 *tp) - return 0; - } - -+static void rtl_set_ifg(struct r8152 *tp, u16 speed) -+{ -+ u32 ocp_data; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1); -+ ocp_data &= ~IFG_MASK; -+ if ((speed & (_10bps | _100bps)) && !(speed & FULL_DUP)) { -+ ocp_data |= IFG_144NS; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR1, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); -+ ocp_data &= ~TX10MIDLE_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); -+ } else { -+ ocp_data |= IFG_96NS; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR1, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); -+ ocp_data |= TX10MIDLE_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); -+ } -+} -+ - static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp) - { - ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN, -@@ -2851,6 +2877,8 @@ static int rtl8153_enable(struct r8152 * - r8153_set_rx_early_timeout(tp); - r8153_set_rx_early_size(tp); - -+ rtl_set_ifg(tp, rtl8152_get_speed(tp)); -+ - if (tp->version == RTL_VER_09) { - u32 ocp_data; - diff --git a/target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch b/target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch deleted file mode 100644 index cddd39ea94..0000000000 --- a/target/linux/generic/backport-5.15/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch +++ /dev/null @@ -1,152 +0,0 @@ -From f10c9edf47d3fa240d965e151a48c670f5035b73 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 16 Apr 2021 16:04:33 +0800 -Subject: [PATCH] r8152: adjust rtl8152_check_firmware function - -commit a8a7be178e81a3d4b6972cbeb0ccd091ca2f9f89 upstream. - -Use bits operations to record and check the firmware. - -Signed-off-by: Hayes Wang -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 51 +++++++++++++++++++++++------------------ - 1 file changed, 29 insertions(+), 22 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -875,6 +875,14 @@ struct fw_header { - struct fw_block blocks[]; - } __packed; - -+enum rtl8152_fw_flags { -+ FW_FLAGS_USB = 0, -+ FW_FLAGS_PLA, -+ FW_FLAGS_START, -+ FW_FLAGS_STOP, -+ FW_FLAGS_NC, -+}; -+ - /** - * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. - * The layout of the firmware block is: -@@ -3801,10 +3809,7 @@ static long rtl8152_check_firmware(struc - { - const struct firmware *fw = rtl_fw->fw; - struct fw_header *fw_hdr = (struct fw_header *)fw->data; -- struct fw_mac *pla = NULL, *usb = NULL; -- struct fw_phy_patch_key *start = NULL; -- struct fw_phy_nc *phy_nc = NULL; -- struct fw_block *stop = NULL; -+ unsigned long fw_flags = 0; - long ret = -EFAULT; - int i; - -@@ -3833,50 +3838,52 @@ static long rtl8152_check_firmware(struc - goto fail; - goto fw_end; - case RTL_FW_PLA: -- if (pla) { -+ if (test_bit(FW_FLAGS_PLA, &fw_flags)) { - dev_err(&tp->intf->dev, - "multiple PLA firmware encountered"); - goto fail; - } - -- pla = (struct fw_mac *)block; -- if (!rtl8152_is_fw_mac_ok(tp, pla)) { -+ if (!rtl8152_is_fw_mac_ok(tp, (struct fw_mac *)block)) { - dev_err(&tp->intf->dev, - "check PLA firmware failed\n"); - goto fail; - } -+ __set_bit(FW_FLAGS_PLA, &fw_flags); - break; - case RTL_FW_USB: -- if (usb) { -+ if (test_bit(FW_FLAGS_USB, &fw_flags)) { - dev_err(&tp->intf->dev, - "multiple USB firmware encountered"); - goto fail; - } - -- usb = (struct fw_mac *)block; -- if (!rtl8152_is_fw_mac_ok(tp, usb)) { -+ if (!rtl8152_is_fw_mac_ok(tp, (struct fw_mac *)block)) { - dev_err(&tp->intf->dev, - "check USB firmware failed\n"); - goto fail; - } -+ __set_bit(FW_FLAGS_USB, &fw_flags); - break; - case RTL_FW_PHY_START: -- if (start || phy_nc || stop) { -+ if (test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_NC, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { - dev_err(&tp->intf->dev, - "check PHY_START fail\n"); - goto fail; - } - -- if (__le32_to_cpu(block->length) != sizeof(*start)) { -+ if (__le32_to_cpu(block->length) != sizeof(struct fw_phy_patch_key)) { - dev_err(&tp->intf->dev, - "Invalid length for PHY_START\n"); - goto fail; - } -- -- start = (struct fw_phy_patch_key *)block; -+ __set_bit(FW_FLAGS_START, &fw_flags); - break; - case RTL_FW_PHY_STOP: -- if (stop || !start) { -+ if (test_bit(FW_FLAGS_STOP, &fw_flags) || -+ !test_bit(FW_FLAGS_START, &fw_flags)) { - dev_err(&tp->intf->dev, - "Check PHY_STOP fail\n"); - goto fail; -@@ -3887,28 +3894,28 @@ static long rtl8152_check_firmware(struc - "Invalid length for PHY_STOP\n"); - goto fail; - } -- -- stop = block; -+ __set_bit(FW_FLAGS_STOP, &fw_flags); - break; - case RTL_FW_PHY_NC: -- if (!start || stop) { -+ if (!test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { - dev_err(&tp->intf->dev, - "check PHY_NC fail\n"); - goto fail; - } - -- if (phy_nc) { -+ if (test_bit(FW_FLAGS_NC, &fw_flags)) { - dev_err(&tp->intf->dev, - "multiple PHY NC encountered\n"); - goto fail; - } - -- phy_nc = (struct fw_phy_nc *)block; -- if (!rtl8152_is_fw_phy_nc_ok(tp, phy_nc)) { -+ if (!rtl8152_is_fw_phy_nc_ok(tp, (struct fw_phy_nc *)block)) { - dev_err(&tp->intf->dev, - "check PHY NC firmware failed\n"); - goto fail; - } -+ __set_bit(FW_FLAGS_NC, &fw_flags); - - break; - default: -@@ -3922,7 +3929,7 @@ static long rtl8152_check_firmware(struc - } - - fw_end: -- if ((phy_nc || start) && !stop) { -+ if (test_bit(FW_FLAGS_START, &fw_flags) && !test_bit(FW_FLAGS_STOP, &fw_flags)) { - dev_err(&tp->intf->dev, "without PHY_STOP\n"); - goto fail; - } diff --git a/target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch b/target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch deleted file mode 100644 index 3559e3b95a..0000000000 --- a/target/linux/generic/backport-5.15/792-v5.13-r8152-add-help-function-to-change-mtu.patch +++ /dev/null @@ -1,157 +0,0 @@ -From f010a7d51cbb42bdb956f0a28b8868b15d7a3816 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 16 Apr 2021 16:04:34 +0800 -Subject: [PATCH] r8152: add help function to change mtu - -commit 67ce1a806f164e59a074fea8809725d3411eaa20 upstream. - -The different chips may have different requests when changing mtu. -Therefore, add a new help function of rtl_ops to change mtu. Besides, -reset the tx/rx after changing mtu. - -Additionally, add mtu_to_size() and size_to_mtu() macros to simplify -the code. - -Signed-off-by: Hayes Wang -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 53 ++++++++++++++++++++++++----------------- - 1 file changed, 31 insertions(+), 22 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -658,15 +658,13 @@ enum rtl_register_content { - - #define INTR_LINK 0x0004 - --#define RTL8153_MAX_PACKET 9216 /* 9K */ --#define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \ -- ETH_FCS_LEN) - #define RTL8152_RMS (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) - #define RTL8153_RMS RTL8153_MAX_PACKET - #define RTL8152_TX_TIMEOUT (5 * HZ) - #define RTL8152_NAPI_WEIGHT 64 --#define rx_reserved_size(x) ((x) + VLAN_ETH_HLEN + ETH_FCS_LEN + \ -- sizeof(struct rx_desc) + RX_ALIGN) -+#define mtu_to_size(m) ((m) + VLAN_ETH_HLEN + ETH_FCS_LEN) -+#define size_to_mtu(s) ((s) - VLAN_ETH_HLEN - ETH_FCS_LEN) -+#define rx_reserved_size(x) (mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN) - - /* rtl8152 flags */ - enum rtl8152_flags { -@@ -796,6 +794,7 @@ struct r8152 { - bool (*in_nway)(struct r8152 *tp); - void (*hw_phy_cfg)(struct r8152 *tp); - void (*autosuspend_en)(struct r8152 *tp, bool enable); -+ void (*change_mtu)(struct r8152 *tp); - } rtl_ops; - - struct ups_info { -@@ -1022,8 +1021,7 @@ enum tx_csum_stat { - static const int multicast_filter_limit = 32; - static unsigned int agg_buf_sz = 16384; - --#define RTL_LIMITED_TSO_SIZE (agg_buf_sz - sizeof(struct tx_desc) - \ -- VLAN_ETH_HLEN - ETH_FCS_LEN) -+#define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc)) - - static - int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) -@@ -2633,10 +2631,7 @@ static void rtl8152_nic_reset(struct r81 - - static void set_tx_qlen(struct r8152 *tp) - { -- struct net_device *netdev = tp->netdev; -- -- tp->tx_qlen = agg_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN + -- sizeof(struct tx_desc)); -+ tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc)); - } - - static inline u8 rtl8152_get_speed(struct r8152 *tp) -@@ -4725,6 +4720,12 @@ static void r8153b_hw_phy_cfg(struct r81 - set_bit(PHY_RESET, &tp->flags); - } - -+static void rtl8153_change_mtu(struct r8152 *tp) -+{ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); -+} -+ - static void r8153_first_init(struct r8152 *tp) - { - u32 ocp_data; -@@ -4757,9 +4758,7 @@ static void r8153_first_init(struct r815 - - rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); - -- ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); -- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); -+ rtl8153_change_mtu(tp); - - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); - ocp_data |= TCR0_AUTO_FIFO; -@@ -4794,8 +4793,7 @@ static void r8153_enter_oob(struct r8152 - - wait_oob_link_list_ready(tp); - -- ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); - - switch (tp->version) { - case RTL_VER_03: -@@ -6518,12 +6516,21 @@ static int rtl8152_change_mtu(struct net - dev->mtu = new_mtu; - - if (netif_running(dev)) { -- u32 rms = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; -- -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rms); -+ if (tp->rtl_ops.change_mtu) -+ tp->rtl_ops.change_mtu(tp); - -- if (netif_carrier_ok(dev)) -- r8153_set_rx_early_size(tp); -+ if (netif_carrier_ok(dev)) { -+ netif_stop_queue(dev); -+ napi_disable(&tp->napi); -+ tasklet_disable(&tp->tx_tl); -+ tp->rtl_ops.disable(tp); -+ tp->rtl_ops.enable(tp); -+ rtl_start_rx(tp); -+ tasklet_enable(&tp->tx_tl); -+ napi_enable(&tp->napi); -+ rtl8152_set_rx_mode(dev); -+ netif_wake_queue(dev); -+ } - } - - mutex_unlock(&tp->control); -@@ -6612,6 +6619,7 @@ static int rtl_ops_init(struct r8152 *tp - ops->in_nway = rtl8153_in_nway; - ops->hw_phy_cfg = r8153_hw_phy_cfg; - ops->autosuspend_en = rtl8153_runtime_enable; -+ ops->change_mtu = rtl8153_change_mtu; - if (tp->udev->speed < USB_SPEED_SUPER) - tp->rx_buf_sz = 16 * 1024; - else -@@ -6633,6 +6641,7 @@ static int rtl_ops_init(struct r8152 *tp - ops->in_nway = rtl8153_in_nway; - ops->hw_phy_cfg = r8153b_hw_phy_cfg; - ops->autosuspend_en = rtl8153b_runtime_enable; -+ ops->change_mtu = rtl8153_change_mtu; - tp->rx_buf_sz = 32 * 1024; - tp->eee_en = true; - tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; -@@ -6853,7 +6862,7 @@ static int rtl8152_probe(struct usb_inte - netdev->max_mtu = ETH_DATA_LEN; - break; - default: -- netdev->max_mtu = RTL8153_MAX_MTU; -+ netdev->max_mtu = size_to_mtu(9 * 1024); - break; - } - diff --git a/target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch b/target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch deleted file mode 100644 index 06a141b451..0000000000 --- a/target/linux/generic/backport-5.15/793-v5.13-r8152-support-new-chips.patch +++ /dev/null @@ -1,2886 +0,0 @@ -From e7439e7fd384f55f55837f7e4866e74d8dca3827 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 16 Apr 2021 16:04:35 +0800 -Subject: [PATCH] r8152: support new chips - -commit 195aae321c829dd1945900d75561e6aa79cce208 upstream. - -Support RTL8153C, RTL8153D, RTL8156A, and RTL8156B. The RTL8156A -and RTL8156B are the 2.5G ethernet. - -Signed-off-by: Hayes Wang -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 2634 +++++++++++++++++++++++++++++++++++---- - 1 file changed, 2359 insertions(+), 275 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -44,10 +44,14 @@ - - #define PLA_IDR 0xc000 - #define PLA_RCR 0xc010 -+#define PLA_RCR1 0xc012 - #define PLA_RMS 0xc016 - #define PLA_RXFIFO_CTRL0 0xc0a0 -+#define PLA_RXFIFO_FULL 0xc0a2 - #define PLA_RXFIFO_CTRL1 0xc0a4 -+#define PLA_RX_FIFO_FULL 0xc0a6 - #define PLA_RXFIFO_CTRL2 0xc0a8 -+#define PLA_RX_FIFO_EMPTY 0xc0aa - #define PLA_DMY_REG0 0xc0b0 - #define PLA_FMC 0xc0b4 - #define PLA_CFG_WOL 0xc0b6 -@@ -64,6 +68,8 @@ - #define PLA_MACDBG_PRE 0xd38c /* RTL_VER_04 only */ - #define PLA_MACDBG_POST 0xd38e /* RTL_VER_04 only */ - #define PLA_EXTRA_STATUS 0xd398 -+#define PLA_GPHY_CTRL 0xd3ae -+#define PLA_POL_GPIO_CTRL 0xdc6a - #define PLA_EFUSE_DATA 0xdd00 - #define PLA_EFUSE_CMD 0xdd02 - #define PLA_LEDSEL 0xdd90 -@@ -73,6 +79,8 @@ - #define PLA_LWAKE_CTRL_REG 0xe007 - #define PLA_GPHY_INTR_IMR 0xe022 - #define PLA_EEE_CR 0xe040 -+#define PLA_EEE_TXTWSYS 0xe04c -+#define PLA_EEE_TXTWSYS_2P5G 0xe058 - #define PLA_EEEP_CR 0xe080 - #define PLA_MAC_PWR_CTRL 0xe0c0 - #define PLA_MAC_PWR_CTRL2 0xe0ca -@@ -83,6 +91,7 @@ - #define PLA_TCR1 0xe612 - #define PLA_MTPS 0xe615 - #define PLA_TXFIFO_CTRL 0xe618 -+#define PLA_TXFIFO_FULL 0xe61a - #define PLA_RSTTALLY 0xe800 - #define PLA_CR 0xe813 - #define PLA_CRWECR 0xe81c -@@ -99,6 +108,7 @@ - #define PLA_SFF_STS_7 0xe8de - #define PLA_PHYSTATUS 0xe908 - #define PLA_CONFIG6 0xe90a /* CONFIG6 */ -+#define PLA_USB_CFG 0xe952 - #define PLA_BP_BA 0xfc26 - #define PLA_BP_0 0xfc28 - #define PLA_BP_1 0xfc2a -@@ -113,6 +123,7 @@ - #define USB_USB2PHY 0xb41e - #define USB_SSPHYLINK1 0xb426 - #define USB_SSPHYLINK2 0xb428 -+#define USB_L1_CTRL 0xb45e - #define USB_U2P3_CTRL 0xb460 - #define USB_CSR_DUMMY1 0xb464 - #define USB_CSR_DUMMY2 0xb466 -@@ -123,7 +134,12 @@ - #define USB_FW_FIX_EN0 0xcfca - #define USB_FW_FIX_EN1 0xcfcc - #define USB_LPM_CONFIG 0xcfd8 -+#define USB_ECM_OPTION 0xcfee - #define USB_CSTMR 0xcfef /* RTL8153A */ -+#define USB_MISC_2 0xcfff -+#define USB_ECM_OP 0xd26b -+#define USB_GPHY_CTRL 0xd284 -+#define USB_SPEED_OPTION 0xd32a - #define USB_FW_CTRL 0xd334 /* RTL8153B */ - #define USB_FC_TIMER 0xd340 - #define USB_USB_CTRL 0xd406 -@@ -137,16 +153,20 @@ - #define USB_RX_EXTRA_AGGR_TMR 0xd432 /* RTL8153B */ - #define USB_TX_DMA 0xd434 - #define USB_UPT_RXDMA_OWN 0xd437 -+#define USB_UPHY3_MDCMDIO 0xd480 - #define USB_TOLERANCE 0xd490 - #define USB_LPM_CTRL 0xd41a - #define USB_BMU_RESET 0xd4b0 -+#define USB_BMU_CONFIG 0xd4b4 - #define USB_U1U2_TIMER 0xd4da - #define USB_FW_TASK 0xd4e8 /* RTL8153B */ -+#define USB_RX_AGGR_NUM 0xd4ee - #define USB_UPS_CTRL 0xd800 - #define USB_POWER_CUT 0xd80a - #define USB_MISC_0 0xd81a - #define USB_MISC_1 0xd81f - #define USB_AFE_CTRL2 0xd824 -+#define USB_UPHY_XTAL 0xd826 - #define USB_UPS_CFG 0xd842 - #define USB_UPS_FLAGS 0xd848 - #define USB_WDT1_CTRL 0xe404 -@@ -189,6 +209,9 @@ - #define OCP_EEE_ABLE 0xa5c4 - #define OCP_EEE_ADV 0xa5d0 - #define OCP_EEE_LPABLE 0xa5d2 -+#define OCP_10GBT_CTRL 0xa5d4 -+#define OCP_10GBT_STAT 0xa5d6 -+#define OCP_EEE_ADV2 0xa6d4 - #define OCP_PHY_STATE 0xa708 /* nway state for 8153 */ - #define OCP_PHY_PATCH_STAT 0xb800 - #define OCP_PHY_PATCH_CMD 0xb820 -@@ -200,6 +223,7 @@ - /* SRAM Register */ - #define SRAM_GREEN_CFG 0x8011 - #define SRAM_LPF_CFG 0x8012 -+#define SRAM_GPHY_FW_VER 0x801e - #define SRAM_10M_AMP1 0x8080 - #define SRAM_10M_AMP2 0x8082 - #define SRAM_IMPEDANCE 0x8084 -@@ -211,11 +235,19 @@ - #define RCR_AM 0x00000004 - #define RCR_AB 0x00000008 - #define RCR_ACPT_ALL (RCR_AAP | RCR_APM | RCR_AM | RCR_AB) -+#define SLOT_EN BIT(11) -+ -+/* PLA_RCR1 */ -+#define OUTER_VLAN BIT(7) -+#define INNER_VLAN BIT(6) - - /* PLA_RXFIFO_CTRL0 */ - #define RXFIFO_THR1_NORMAL 0x00080002 - #define RXFIFO_THR1_OOB 0x01800003 - -+/* PLA_RXFIFO_FULL */ -+#define RXFIFO_FULL_MASK 0xfff -+ - /* PLA_RXFIFO_CTRL1 */ - #define RXFIFO_THR2_FULL 0x00000060 - #define RXFIFO_THR2_HIGH 0x00000038 -@@ -286,6 +318,7 @@ - #define MCU_BORW_EN 0x4000 - - /* PLA_CPCR */ -+#define FLOW_CTRL_EN BIT(0) - #define CPCR_RX_VLAN 0x0040 - - /* PLA_CFG_WOL */ -@@ -311,6 +344,10 @@ - /* PLA_CONFIG6 */ - #define LANWAKE_CLR_EN BIT(0) - -+/* PLA_USB_CFG */ -+#define EN_XG_LIP BIT(1) -+#define EN_G_LIP BIT(2) -+ - /* PLA_CONFIG5 */ - #define BWF_EN 0x0040 - #define MWF_EN 0x0020 -@@ -334,6 +371,7 @@ - /* PLA_MAC_PWR_CTRL2 */ - #define EEE_SPDWN_RATIO 0x8007 - #define MAC_CLK_SPDWN_EN BIT(15) -+#define EEE_SPDWN_RATIO_MASK 0xff - - /* PLA_MAC_PWR_CTRL3 */ - #define PLA_MCU_SPDWN_EN BIT(14) -@@ -346,6 +384,7 @@ - #define PWRSAVE_SPDWN_EN 0x1000 - #define RXDV_SPDWN_EN 0x0800 - #define TX10MIDLE_EN 0x0100 -+#define IDLE_SPDWN_EN BIT(6) - #define TP100_SPDWN_EN 0x0020 - #define TP500_SPDWN_EN 0x0010 - #define TP1000_SPDWN_EN 0x0008 -@@ -386,6 +425,13 @@ - #define LINK_CHANGE_FLAG BIT(8) - #define POLL_LINK_CHG BIT(0) - -+/* PLA_GPHY_CTRL */ -+#define GPHY_FLASH BIT(1) -+ -+/* PLA_POL_GPIO_CTRL */ -+#define DACK_DET_EN BIT(15) -+#define POL_GPHY_PATCH BIT(4) -+ - /* USB_USB2PHY */ - #define USB2PHY_SUSPEND 0x0001 - #define USB2PHY_L1 0x0002 -@@ -434,6 +480,9 @@ - #define BMU_RESET_EP_IN 0x01 - #define BMU_RESET_EP_OUT 0x02 - -+/* USB_BMU_CONFIG */ -+#define ACT_ODMA BIT(1) -+ - /* USB_UPT_RXDMA_OWN */ - #define OWN_UPDATE BIT(0) - #define OWN_CLEAR BIT(1) -@@ -441,27 +490,52 @@ - /* USB_FW_TASK */ - #define FC_PATCH_TASK BIT(1) - -+/* USB_RX_AGGR_NUM */ -+#define RX_AGGR_NUM_MASK 0x1ff -+ - /* USB_UPS_CTRL */ - #define POWER_CUT 0x0100 - - /* USB_PM_CTRL_STATUS */ - #define RESUME_INDICATE 0x0001 - -+/* USB_ECM_OPTION */ -+#define BYPASS_MAC_RESET BIT(5) -+ - /* USB_CSTMR */ - #define FORCE_SUPER BIT(0) - -+/* USB_MISC_2 */ -+#define UPS_FORCE_PWR_DOWN BIT(0) -+ -+/* USB_ECM_OP */ -+#define EN_ALL_SPEED BIT(0) -+ -+/* USB_GPHY_CTRL */ -+#define GPHY_PATCH_DONE BIT(2) -+#define BYPASS_FLASH BIT(5) -+#define BACKUP_RESTRORE BIT(6) -+ -+/* USB_SPEED_OPTION */ -+#define RG_PWRDN_EN BIT(8) -+#define ALL_SPEED_OFF BIT(9) -+ - /* USB_FW_CTRL */ - #define FLOW_CTRL_PATCH_OPT BIT(1) -+#define AUTO_SPEEDUP BIT(3) -+#define FLOW_CTRL_PATCH_2 BIT(8) - - /* USB_FC_TIMER */ - #define CTRL_TIMER_EN BIT(15) - - /* USB_USB_CTRL */ -+#define CDC_ECM_EN BIT(3) - #define RX_AGG_DISABLE 0x0010 - #define RX_ZERO_EN 0x0080 - - /* USB_U2P3_CTRL */ - #define U2P3_ENABLE 0x0001 -+#define RX_DETECT8 BIT(3) - - /* USB_POWER_CUT */ - #define PWR_EN 0x0001 -@@ -497,8 +571,12 @@ - #define SEN_VAL_NORMAL 0xa000 - #define SEL_RXIDLE 0x0100 - -+/* USB_UPHY_XTAL */ -+#define OOBS_POLLING BIT(8) -+ - /* USB_UPS_CFG */ - #define SAW_CNT_1MS_MASK 0x0fff -+#define MID_REVERSE BIT(5) /* RTL8156A */ - - /* USB_UPS_FLAGS */ - #define UPS_FLAGS_R_TUNE BIT(0) -@@ -506,6 +584,7 @@ - #define UPS_FLAGS_250M_CKDIV BIT(2) - #define UPS_FLAGS_EN_ALDPS BIT(3) - #define UPS_FLAGS_CTAP_SHORT_DIS BIT(4) -+#define UPS_FLAGS_SPEED_MASK (0xf << 16) - #define ups_flags_speed(x) ((x) << 16) - #define UPS_FLAGS_EN_EEE BIT(20) - #define UPS_FLAGS_EN_500M_EEE BIT(21) -@@ -526,6 +605,8 @@ enum spd_duplex { - FORCE_10M_FULL, - FORCE_100M_HALF, - FORCE_100M_FULL, -+ FORCE_1000M_FULL, -+ NWAY_2500M_FULL, - }; - - /* OCP_ALDPS_CONFIG */ -@@ -590,6 +671,9 @@ enum spd_duplex { - #define EN_10M_CLKDIV BIT(11) - #define EN_10M_BGOFF 0x0080 - -+/* OCP_10GBT_CTRL */ -+#define RTL_ADV2_5G_F_R BIT(5) /* Advertise 2.5GBASE-T fast-retrain */ -+ - /* OCP_PHY_STATE */ - #define TXDIS_STATE 0x01 - #define ABD_STATE 0x02 -@@ -609,7 +693,8 @@ enum spd_duplex { - #define EN_EMI_L 0x0040 - - /* OCP_SYSCLK_CFG */ --#define clk_div_expo(x) (min(x, 5) << 8) -+#define sysclk_div_expo(x) (min(x, 5) << 8) -+#define clk_div_expo(x) (min(x, 5) << 4) - - /* SRAM_GREEN_CFG */ - #define GREEN_ETH_EN BIT(15) -@@ -640,6 +725,11 @@ enum spd_duplex { - #define BP4_SUPER_ONLY 0x1578 /* RTL_VER_04 only */ - - enum rtl_register_content { -+ _2500bps = BIT(10), -+ _1250bps = BIT(9), -+ _500bps = BIT(8), -+ _tx_flow = BIT(6), -+ _rx_flow = BIT(5), - _1000bps = 0x10, - _100bps = 0x08, - _10bps = 0x04, -@@ -647,6 +737,9 @@ enum rtl_register_content { - FULL_DUP = 0x01, - }; - -+#define is_speed_2500(_speed) (((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS)) -+#define is_flow_control(_speed) (((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow)) -+ - #define RTL8152_MAX_TX 4 - #define RTL8152_MAX_RX 10 - #define INTBUFSIZE 2 -@@ -661,7 +754,6 @@ enum rtl_register_content { - #define RTL8152_RMS (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) - #define RTL8153_RMS RTL8153_MAX_PACKET - #define RTL8152_TX_TIMEOUT (5 * HZ) --#define RTL8152_NAPI_WEIGHT 64 - #define mtu_to_size(m) ((m) + VLAN_ETH_HLEN + ETH_FCS_LEN) - #define size_to_mtu(s) ((s) - VLAN_ETH_HLEN - ETH_FCS_LEN) - #define rx_reserved_size(x) (mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN) -@@ -798,6 +890,7 @@ struct r8152 { - } rtl_ops; - - struct ups_info { -+ u32 r_tune:1; - u32 _10m_ckdiv:1; - u32 _250m_ckdiv:1; - u32 aldps:1; -@@ -839,7 +932,9 @@ struct r8152 { - u32 rx_buf_sz; - u32 rx_copybreak; - u32 rx_pending; -+ u32 fc_pause_on, fc_pause_off; - -+ u32 support_2500full:1; - u16 ocp_base; - u16 speed; - u16 eee_adv; -@@ -999,6 +1094,15 @@ enum rtl_version { - RTL_VER_07, - RTL_VER_08, - RTL_VER_09, -+ -+ RTL_TEST_01, -+ RTL_VER_10, -+ RTL_VER_11, -+ RTL_VER_12, -+ RTL_VER_13, -+ RTL_VER_14, -+ RTL_VER_15, -+ - RTL_VER_MAX - }; - -@@ -1014,6 +1118,7 @@ enum tx_csum_stat { - #define RTL_ADVERTISED_100_FULL BIT(3) - #define RTL_ADVERTISED_1000_HALF BIT(4) - #define RTL_ADVERTISED_1000_FULL BIT(5) -+#define RTL_ADVERTISED_2500_FULL BIT(6) - - /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - * The RTL chips use a 64 element hash table based on the Ethernet CRC. -@@ -2607,7 +2712,7 @@ static netdev_tx_t rtl8152_start_xmit(st - - static void r8152b_reset_packet_filter(struct r8152 *tp) - { -- u32 ocp_data; -+ u32 ocp_data; - - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC); - ocp_data &= ~FMC_FCR_MCU_EN; -@@ -2618,14 +2723,47 @@ static void r8152b_reset_packet_filter(s - - static void rtl8152_nic_reset(struct r8152 *tp) - { -- int i; -+ u32 ocp_data; -+ int i; - -- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST); -+ switch (tp->version) { -+ case RTL_TEST_01: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); -+ ocp_data &= ~CR_TE; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_RESET); -+ ocp_data &= ~BMU_RESET_EP_IN; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); -+ ocp_data |= CDC_ECM_EN; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); -+ ocp_data &= ~CR_RE; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_RESET); -+ ocp_data |= BMU_RESET_EP_IN; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); -+ ocp_data &= ~CDC_ECM_EN; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); -+ break; - -- for (i = 0; i < 1000; i++) { -- if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST)) -- break; -- usleep_range(100, 400); -+ default: -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST); -+ -+ for (i = 0; i < 1000; i++) { -+ if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST)) -+ break; -+ usleep_range(100, 400); -+ } -+ break; - } - } - -@@ -2634,9 +2772,9 @@ static void set_tx_qlen(struct r8152 *tp - tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc)); - } - --static inline u8 rtl8152_get_speed(struct r8152 *tp) -+static inline u16 rtl8152_get_speed(struct r8152 *tp) - { -- return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); -+ return ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); - } - - static void rtl_eee_plus_en(struct r8152 *tp, bool enable) -@@ -2796,6 +2934,7 @@ static int rtl_enable(struct r8152 *tp) - switch (tp->version) { - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_14: - r8153b_rx_agg_chg_indicate(tp); - break; - default: -@@ -2833,6 +2972,7 @@ static void r8153_set_rx_early_timeout(s - - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_14: - /* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout - * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 128ns. - */ -@@ -2842,6 +2982,18 @@ static void r8153_set_rx_early_timeout(s - ocp_data); - break; - -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, -+ 640 / 8); -+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR, -+ ocp_data); -+ r8153b_rx_agg_chg_indicate(tp); -+ break; -+ - default: - break; - } -@@ -2861,8 +3013,19 @@ static void r8153_set_rx_early_size(stru - break; - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_14: -+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, -+ ocp_data / 8); -+ break; -+ case RTL_TEST_01: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: - ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, - ocp_data / 8); -+ r8153b_rx_agg_chg_indicate(tp); - break; - default: - WARN_ON_ONCE(1); -@@ -2872,6 +3035,8 @@ static void r8153_set_rx_early_size(stru - - static int rtl8153_enable(struct r8152 *tp) - { -+ u32 ocp_data; -+ - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - return -ENODEV; - -@@ -2882,15 +3047,18 @@ static int rtl8153_enable(struct r8152 * - - rtl_set_ifg(tp, rtl8152_get_speed(tp)); - -- if (tp->version == RTL_VER_09) { -- u32 ocp_data; -- -+ switch (tp->version) { -+ case RTL_VER_09: -+ case RTL_VER_14: - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); - ocp_data &= ~FC_PATCH_TASK; - ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); - usleep_range(1000, 2000); - ocp_data |= FC_PATCH_TASK; - ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); -+ break; -+ default: -+ break; - } - - return rtl_enable(tp); -@@ -2955,12 +3123,40 @@ static void rtl_rx_vlan_en(struct r8152 - { - u32 ocp_data; - -- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); -- if (enable) -- ocp_data |= CPCR_RX_VLAN; -- else -- ocp_data &= ~CPCR_RX_VLAN; -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); -+ switch (tp->version) { -+ case RTL_VER_01: -+ case RTL_VER_02: -+ case RTL_VER_03: -+ case RTL_VER_04: -+ case RTL_VER_05: -+ case RTL_VER_06: -+ case RTL_VER_07: -+ case RTL_VER_08: -+ case RTL_VER_09: -+ case RTL_VER_14: -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); -+ if (enable) -+ ocp_data |= CPCR_RX_VLAN; -+ else -+ ocp_data &= ~CPCR_RX_VLAN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); -+ break; -+ -+ case RTL_TEST_01: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ default: -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR1); -+ if (enable) -+ ocp_data |= OUTER_VLAN | INNER_VLAN; -+ else -+ ocp_data &= ~(OUTER_VLAN | INNER_VLAN); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR1, ocp_data); -+ break; -+ } - } - - static int rtl8152_set_features(struct net_device *dev, -@@ -3053,6 +3249,40 @@ static void __rtl_set_wol(struct r8152 * - device_set_wakeup_enable(&tp->udev->dev, false); - } - -+static void r8153_mac_clk_speed_down(struct r8152 *tp, bool enable) -+{ -+ u32 ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); -+ -+ /* MAC clock speed down */ -+ if (enable) -+ ocp_data |= MAC_CLK_SPDWN_EN; -+ else -+ ocp_data &= ~MAC_CLK_SPDWN_EN; -+ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); -+} -+ -+static void r8156_mac_clk_spd(struct r8152 *tp, bool enable) -+{ -+ u32 ocp_data; -+ -+ /* MAC clock speed down */ -+ if (enable) { -+ /* aldps_spdwn_ratio, tp10_spdwn_ratio */ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, -+ 0x0403); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); -+ ocp_data &= ~EEE_SPDWN_RATIO_MASK; -+ ocp_data |= MAC_CLK_SPDWN_EN | 0x03; /* eee_spdwn_ratio */ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); -+ } else { -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); -+ ocp_data &= ~MAC_CLK_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); -+ } -+} -+ - static void r8153_u1u2en(struct r8152 *tp, bool enable) - { - u8 u1u2[8]; -@@ -3112,6 +3342,9 @@ static void r8153b_ups_flags(struct r815 - if (tp->ups_info.eee_cmod_lv) - ups_flags |= UPS_FLAGS_EEE_CMOD_LV_EN; - -+ if (tp->ups_info.r_tune) -+ ups_flags |= UPS_FLAGS_R_TUNE; -+ - if (tp->ups_info._10m_ckdiv) - ups_flags |= UPS_FLAGS_EN_10M_CKDIV; - -@@ -3162,6 +3395,88 @@ static void r8153b_ups_flags(struct r815 - ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); - } - -+static void r8156_ups_flags(struct r8152 *tp) -+{ -+ u32 ups_flags = 0; -+ -+ if (tp->ups_info.green) -+ ups_flags |= UPS_FLAGS_EN_GREEN; -+ -+ if (tp->ups_info.aldps) -+ ups_flags |= UPS_FLAGS_EN_ALDPS; -+ -+ if (tp->ups_info.eee) -+ ups_flags |= UPS_FLAGS_EN_EEE; -+ -+ if (tp->ups_info.flow_control) -+ ups_flags |= UPS_FLAGS_EN_FLOW_CTR; -+ -+ if (tp->ups_info.eee_ckdiv) -+ ups_flags |= UPS_FLAGS_EN_EEE_CKDIV; -+ -+ if (tp->ups_info._10m_ckdiv) -+ ups_flags |= UPS_FLAGS_EN_10M_CKDIV; -+ -+ if (tp->ups_info.eee_plloff_100) -+ ups_flags |= UPS_FLAGS_EEE_PLLOFF_100; -+ -+ if (tp->ups_info.eee_plloff_giga) -+ ups_flags |= UPS_FLAGS_EEE_PLLOFF_GIGA; -+ -+ if (tp->ups_info._250m_ckdiv) -+ ups_flags |= UPS_FLAGS_250M_CKDIV; -+ -+ switch (tp->ups_info.speed_duplex) { -+ case FORCE_10M_HALF: -+ ups_flags |= ups_flags_speed(0); -+ break; -+ case FORCE_10M_FULL: -+ ups_flags |= ups_flags_speed(1); -+ break; -+ case FORCE_100M_HALF: -+ ups_flags |= ups_flags_speed(2); -+ break; -+ case FORCE_100M_FULL: -+ ups_flags |= ups_flags_speed(3); -+ break; -+ case NWAY_10M_HALF: -+ ups_flags |= ups_flags_speed(4); -+ break; -+ case NWAY_10M_FULL: -+ ups_flags |= ups_flags_speed(5); -+ break; -+ case NWAY_100M_HALF: -+ ups_flags |= ups_flags_speed(6); -+ break; -+ case NWAY_100M_FULL: -+ ups_flags |= ups_flags_speed(7); -+ break; -+ case NWAY_1000M_FULL: -+ ups_flags |= ups_flags_speed(8); -+ break; -+ case NWAY_2500M_FULL: -+ ups_flags |= ups_flags_speed(9); -+ break; -+ default: -+ break; -+ } -+ -+ switch (tp->ups_info.lite_mode) { -+ case 1: -+ ups_flags |= 0 << 5; -+ break; -+ case 2: -+ ups_flags |= 2 << 5; -+ break; -+ case 0: -+ default: -+ ups_flags |= 1 << 5; -+ break; -+ } -+ -+ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); -+} -+ - static void rtl_green_en(struct r8152 *tp, bool enable) - { - u16 data; -@@ -3225,16 +3540,16 @@ static void r8153b_ups_en(struct r8152 * - ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; - ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); - -- ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff); -- ocp_data |= BIT(0); -- ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data |= UPS_FORCE_PWR_DOWN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); - } else { - ocp_data &= ~(UPS_EN | USP_PREWAKE); - ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); - -- ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff); -- ocp_data &= ~BIT(0); -- ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data &= ~UPS_FORCE_PWR_DOWN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); - - if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { - int i; -@@ -3254,6 +3569,95 @@ static void r8153b_ups_en(struct r8152 * - } - } - -+static void r8153c_ups_en(struct r8152 *tp, bool enable) -+{ -+ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT); -+ -+ if (enable) { -+ r8153b_ups_flags(tp); -+ -+ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data |= UPS_FORCE_PWR_DOWN; -+ ocp_data &= ~BIT(7); -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); -+ } else { -+ ocp_data &= ~(UPS_EN | USP_PREWAKE); -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data &= ~UPS_FORCE_PWR_DOWN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); -+ -+ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { -+ int i; -+ -+ for (i = 0; i < 500; i++) { -+ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & -+ AUTOLOAD_DONE) -+ break; -+ msleep(20); -+ } -+ -+ tp->rtl_ops.hw_phy_cfg(tp); -+ -+ rtl8152_set_speed(tp, tp->autoneg, tp->speed, -+ tp->duplex, tp->advertising); -+ } -+ -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); -+ ocp_data |= BIT(8); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); -+ -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); -+ } -+} -+ -+static void r8156_ups_en(struct r8152 *tp, bool enable) -+{ -+ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT); -+ -+ if (enable) { -+ r8156_ups_flags(tp); -+ -+ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data |= UPS_FORCE_PWR_DOWN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); -+ -+ switch (tp->version) { -+ case RTL_VER_13: -+ case RTL_VER_15: -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPHY_XTAL); -+ ocp_data &= ~OOBS_POLLING; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_UPHY_XTAL, ocp_data); -+ break; -+ default: -+ break; -+ } -+ } else { -+ ocp_data &= ~(UPS_EN | USP_PREWAKE); -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data &= ~UPS_FORCE_PWR_DOWN; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); -+ -+ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { -+ tp->rtl_ops.hw_phy_cfg(tp); -+ -+ rtl8152_set_speed(tp, tp->autoneg, tp->speed, -+ tp->duplex, tp->advertising); -+ } -+ } -+} -+ - static void r8153_power_cut_en(struct r8152 *tp, bool enable) - { - u32 ocp_data; -@@ -3383,6 +3787,38 @@ static void rtl8153b_runtime_enable(stru - } - } - -+static void rtl8153c_runtime_enable(struct r8152 *tp, bool enable) -+{ -+ if (enable) { -+ r8153_queue_wake(tp, true); -+ r8153b_u1u2en(tp, false); -+ r8153_u2p3en(tp, false); -+ rtl_runtime_suspend_enable(tp, true); -+ r8153c_ups_en(tp, true); -+ } else { -+ r8153c_ups_en(tp, false); -+ r8153_queue_wake(tp, false); -+ rtl_runtime_suspend_enable(tp, false); -+ r8153b_u1u2en(tp, true); -+ } -+} -+ -+static void rtl8156_runtime_enable(struct r8152 *tp, bool enable) -+{ -+ if (enable) { -+ r8153_queue_wake(tp, true); -+ r8153b_u1u2en(tp, false); -+ r8153_u2p3en(tp, false); -+ rtl_runtime_suspend_enable(tp, true); -+ } else { -+ r8153_queue_wake(tp, false); -+ rtl_runtime_suspend_enable(tp, false); -+ r8153_u2p3en(tp, true); -+ if (tp->udev->speed >= USB_SPEED_SUPER) -+ r8153b_u1u2en(tp, true); -+ } -+} -+ - static void r8153_teredo_off(struct r8152 *tp) - { - u32 ocp_data; -@@ -3403,14 +3839,19 @@ static void r8153_teredo_off(struct r815 - - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_TEST_01: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_14: -+ case RTL_VER_15: -+ default: - /* The bit 0 ~ 7 are relative with teredo settings. They are - * W1C (write 1 to clear), so set all 1 to disable it. - */ - ocp_write_byte(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, 0xff); - break; -- -- default: -- break; - } - - ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE); -@@ -3445,6 +3886,12 @@ static void rtl_clear_bp(struct r8152 *t - break; - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_14: -+ case RTL_VER_15: - default: - if (type == MCU_TYPE_USB) { - ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); -@@ -3654,6 +4101,11 @@ static bool rtl8152_is_fw_mac_ok(struct - case RTL_VER_06: - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_14: -+ case RTL_VER_15: - fw_reg = 0xf800; - bp_ba_addr = PLA_BP_BA; - bp_en_addr = PLA_BP_EN; -@@ -3677,6 +4129,11 @@ static bool rtl8152_is_fw_mac_ok(struct - break; - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_14: -+ case RTL_VER_15: - fw_reg = 0xe600; - bp_ba_addr = USB_BP_BA; - bp_en_addr = USB_BP2_EN; -@@ -4216,6 +4673,22 @@ static void r8153_eee_en(struct r8152 *t - tp->ups_info.eee = enable; - } - -+static void r8156_eee_en(struct r8152 *tp, bool enable) -+{ -+ u16 config; -+ -+ r8153_eee_en(tp, enable); -+ -+ config = ocp_reg_read(tp, OCP_EEE_ADV2); -+ -+ if (enable) -+ config |= MDIO_EEE_2_5GT; -+ else -+ config &= ~MDIO_EEE_2_5GT; -+ -+ ocp_reg_write(tp, OCP_EEE_ADV2, config); -+} -+ - static void rtl_eee_enable(struct r8152 *tp, bool enable) - { - switch (tp->version) { -@@ -4237,6 +4710,7 @@ static void rtl_eee_enable(struct r8152 - case RTL_VER_06: - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_14: - if (enable) { - r8153_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); -@@ -4245,6 +4719,19 @@ static void rtl_eee_enable(struct r8152 - ocp_reg_write(tp, OCP_EEE_ADV, 0); - } - break; -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ if (enable) { -+ r8156_eee_en(tp, true); -+ ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); -+ } else { -+ r8156_eee_en(tp, false); -+ ocp_reg_write(tp, OCP_EEE_ADV, 0); -+ } -+ break; - default: - break; - } -@@ -4291,6 +4778,20 @@ static void wait_oob_link_list_ready(str - } - } - -+static void r8156b_wait_loading_flash(struct r8152 *tp) -+{ -+ if ((ocp_read_word(tp, MCU_TYPE_PLA, PLA_GPHY_CTRL) & GPHY_FLASH) && -+ !(ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL) & BYPASS_FLASH)) { -+ int i; -+ -+ for (i = 0; i < 100; i++) { -+ if (ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL) & GPHY_PATCH_DONE) -+ break; -+ usleep_range(1000, 2000); -+ } -+ } -+} -+ - static void r8152b_exit_oob(struct r8152 *tp) - { - u32 ocp_data; -@@ -4341,7 +4842,7 @@ static void r8152b_exit_oob(struct r8152 - } - - /* TX share fifo free credit full threshold */ -- ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL); -+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2); - - ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD); - ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH); -@@ -4518,6 +5019,21 @@ static int r8153b_post_firmware_1(struct - return 0; - } - -+static int r8153c_post_firmware_1(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL); -+ ocp_data |= FLOW_CTRL_PATCH_2; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); -+ ocp_data |= FC_PATCH_TASK; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); -+ -+ return 0; -+} -+ - static void r8153_aldps_en(struct r8152 *tp, bool enable) - { - u16 data; -@@ -4720,6 +5236,13 @@ static void r8153b_hw_phy_cfg(struct r81 - set_bit(PHY_RESET, &tp->flags); - } - -+static void r8153c_hw_phy_cfg(struct r8152 *tp) -+{ -+ r8153b_hw_phy_cfg(tp); -+ -+ tp->ups_info.r_tune = true; -+} -+ - static void rtl8153_change_mtu(struct r8152 *tp) - { - ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); -@@ -4807,6 +5330,7 @@ static void r8153_enter_oob(struct r8152 - - case RTL_VER_08: - case RTL_VER_09: -+ case RTL_VER_14: - /* Clear teredo wake event. bit[15:8] is the teredo wakeup - * type. Set it to zero. bits[7:0] are the W1C bits about - * the events. Set them to all 1 to clear them. -@@ -4843,6 +5367,96 @@ static void rtl8153_disable(struct r8152 - r8153_aldps_en(tp, true); - } - -+static int rtl8156_enable(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 speed; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return -ENODEV; -+ -+ set_tx_qlen(tp); -+ rtl_set_eee_plus(tp); -+ r8153_set_rx_early_timeout(tp); -+ r8153_set_rx_early_size(tp); -+ -+ speed = rtl8152_get_speed(tp); -+ rtl_set_ifg(tp, speed); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); -+ if (speed & _2500bps) -+ ocp_data &= ~IDLE_SPDWN_EN; -+ else -+ ocp_data |= IDLE_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); -+ -+ if (speed & _1000bps) -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11); -+ else if (speed & _500bps) -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d); -+ -+ if (tp->udev->speed == USB_SPEED_HIGH) { -+ /* USB 0xb45e[3:0] l1_nyet_hird */ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL); -+ ocp_data &= ~0xf; -+ if (is_flow_control(speed)) -+ ocp_data |= 0xf; -+ else -+ ocp_data |= 0x1; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data); -+ } -+ -+ return rtl_enable(tp); -+} -+ -+static int rtl8156b_enable(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 speed; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return -ENODEV; -+ -+ set_tx_qlen(tp); -+ rtl_set_eee_plus(tp); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM); -+ ocp_data &= ~RX_AGGR_NUM_MASK; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, ocp_data); -+ -+ r8153_set_rx_early_timeout(tp); -+ r8153_set_rx_early_size(tp); -+ -+ speed = rtl8152_get_speed(tp); -+ rtl_set_ifg(tp, speed); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); -+ if (speed & _2500bps) -+ ocp_data &= ~IDLE_SPDWN_EN; -+ else -+ ocp_data |= IDLE_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); -+ -+ if (tp->udev->speed == USB_SPEED_HIGH) { -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL); -+ ocp_data &= ~0xf; -+ if (is_flow_control(speed)) -+ ocp_data |= 0xf; -+ else -+ ocp_data |= 0x1; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data); -+ } -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); -+ ocp_data &= ~FC_PATCH_TASK; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); -+ usleep_range(1000, 2000); -+ ocp_data |= FC_PATCH_TASK; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); -+ -+ return rtl_enable(tp); -+} -+ - static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, - u32 advertising) - { -@@ -4891,58 +5505,73 @@ static int rtl8152_set_speed(struct r815 - - tp->mii.force_media = 1; - } else { -- u16 anar, tmp1; -+ u16 orig, new1; - u32 support; - - support = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | - RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; - -- if (tp->mii.supports_gmii) -+ if (tp->mii.supports_gmii) { - support |= RTL_ADVERTISED_1000_FULL; - -+ if (tp->support_2500full) -+ support |= RTL_ADVERTISED_2500_FULL; -+ } -+ - if (!(advertising & support)) - return -EINVAL; - -- anar = r8152_mdio_read(tp, MII_ADVERTISE); -- tmp1 = anar & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | -+ orig = r8152_mdio_read(tp, MII_ADVERTISE); -+ new1 = orig & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - if (advertising & RTL_ADVERTISED_10_HALF) { -- tmp1 |= ADVERTISE_10HALF; -+ new1 |= ADVERTISE_10HALF; - tp->ups_info.speed_duplex = NWAY_10M_HALF; - } - if (advertising & RTL_ADVERTISED_10_FULL) { -- tmp1 |= ADVERTISE_10FULL; -+ new1 |= ADVERTISE_10FULL; - tp->ups_info.speed_duplex = NWAY_10M_FULL; - } - - if (advertising & RTL_ADVERTISED_100_HALF) { -- tmp1 |= ADVERTISE_100HALF; -+ new1 |= ADVERTISE_100HALF; - tp->ups_info.speed_duplex = NWAY_100M_HALF; - } - if (advertising & RTL_ADVERTISED_100_FULL) { -- tmp1 |= ADVERTISE_100FULL; -+ new1 |= ADVERTISE_100FULL; - tp->ups_info.speed_duplex = NWAY_100M_FULL; - } - -- if (anar != tmp1) { -- r8152_mdio_write(tp, MII_ADVERTISE, tmp1); -- tp->mii.advertising = tmp1; -+ if (orig != new1) { -+ r8152_mdio_write(tp, MII_ADVERTISE, new1); -+ tp->mii.advertising = new1; - } - - if (tp->mii.supports_gmii) { -- u16 gbcr; -- -- gbcr = r8152_mdio_read(tp, MII_CTRL1000); -- tmp1 = gbcr & ~(ADVERTISE_1000FULL | -+ orig = r8152_mdio_read(tp, MII_CTRL1000); -+ new1 = orig & ~(ADVERTISE_1000FULL | - ADVERTISE_1000HALF); - - if (advertising & RTL_ADVERTISED_1000_FULL) { -- tmp1 |= ADVERTISE_1000FULL; -+ new1 |= ADVERTISE_1000FULL; - tp->ups_info.speed_duplex = NWAY_1000M_FULL; - } - -- if (gbcr != tmp1) -- r8152_mdio_write(tp, MII_CTRL1000, tmp1); -+ if (orig != new1) -+ r8152_mdio_write(tp, MII_CTRL1000, new1); -+ } -+ -+ if (tp->support_2500full) { -+ orig = ocp_reg_read(tp, OCP_10GBT_CTRL); -+ new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G; -+ -+ if (advertising & RTL_ADVERTISED_2500_FULL) { -+ new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G; -+ tp->ups_info.speed_duplex = NWAY_2500M_FULL; -+ } -+ -+ if (orig != new1) -+ ocp_reg_write(tp, OCP_10GBT_CTRL, new1); - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; -@@ -5098,6 +5727,253 @@ static void rtl8153b_down(struct r8152 * - r8153_aldps_en(tp, true); - } - -+static void rtl8153c_change_mtu(struct r8152 *tp) -+{ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, 10 * 1024 / 64); -+ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64); -+ -+ /* Adjust the tx fifo free credit full threshold, otherwise -+ * the fifo would be too small to send a jumbo frame packet. -+ */ -+ if (tp->netdev->mtu < 8000) -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, 2048 / 8); -+ else -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, 900 / 8); -+} -+ -+static void rtl8153c_up(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ -+ r8153b_u1u2en(tp, false); -+ r8153_u2p3en(tp, false); -+ r8153_aldps_en(tp, false); -+ -+ rxdy_gated_en(tp, true); -+ r8153_teredo_off(tp); -+ -+ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); -+ ocp_data &= ~RCR_ACPT_ALL; -+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); -+ -+ rtl8152_nic_reset(tp); -+ rtl_reset_bmu(tp); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); -+ ocp_data &= ~NOW_IS_OOB; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); -+ ocp_data &= ~MCU_BORW_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); -+ -+ wait_oob_link_list_ready(tp); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); -+ ocp_data |= RE_INIT_LL; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); -+ -+ wait_oob_link_list_ready(tp); -+ -+ rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); -+ -+ rtl8153c_change_mtu(tp); -+ -+ rtl8152_nic_reset(tp); -+ -+ /* rx share fifo credit full threshold */ -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, 0x02); -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 0x08); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL); -+ -+ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B); -+ -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); -+ ocp_data |= BIT(8); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); -+ -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); -+ ocp_data &= ~PLA_MCU_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); -+ -+ r8153_aldps_en(tp, true); -+ r8153b_u1u2en(tp, true); -+} -+ -+static inline u32 fc_pause_on_auto(struct r8152 *tp) -+{ -+ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024); -+} -+ -+static inline u32 fc_pause_off_auto(struct r8152 *tp) -+{ -+ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024); -+} -+ -+static void r8156_fc_parameter(struct r8152 *tp) -+{ -+ u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp); -+ u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp); -+ -+ switch (tp->version) { -+ case RTL_VER_10: -+ case RTL_VER_11: -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 8); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 8); -+ break; -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void rtl8156_change_mtu(struct r8152 *tp) -+{ -+ u32 rx_max_size = mtu_to_size(tp->netdev->mtu); -+ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rx_max_size); -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); -+ r8156_fc_parameter(tp); -+ -+ /* TX share fifo free credit full threshold */ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, -+ ALIGN(rx_max_size + sizeof(struct tx_desc), 1024) / 16); -+} -+ -+static void rtl8156_up(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ -+ r8153b_u1u2en(tp, false); -+ r8153_u2p3en(tp, false); -+ r8153_aldps_en(tp, false); -+ -+ rxdy_gated_en(tp, true); -+ r8153_teredo_off(tp); -+ -+ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); -+ ocp_data &= ~RCR_ACPT_ALL; -+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); -+ -+ rtl8152_nic_reset(tp); -+ rtl_reset_bmu(tp); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); -+ ocp_data &= ~NOW_IS_OOB; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); -+ ocp_data &= ~MCU_BORW_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); -+ -+ rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); -+ -+ rtl8156_change_mtu(tp); -+ -+ switch (tp->version) { -+ case RTL_TEST_01: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG); -+ ocp_data |= ACT_ODMA; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); -+ break; -+ default: -+ break; -+ } -+ -+ /* share FIFO settings */ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL); -+ ocp_data &= ~RXFIFO_FULL_MASK; -+ ocp_data |= 0x08; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); -+ ocp_data &= ~PLA_MCU_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION); -+ ocp_data &= ~(RG_PWRDN_EN | ALL_SPEED_OFF); -+ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, ocp_data); -+ -+ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400); -+ -+ if (tp->saved_wolopts != __rtl_get_wol(tp)) { -+ netif_warn(tp, ifup, tp->netdev, "wol setting is changed\n"); -+ __rtl_set_wol(tp, tp->saved_wolopts); -+ } -+ -+ r8153_aldps_en(tp, true); -+ r8153_u2p3en(tp, true); -+ -+ if (tp->udev->speed >= USB_SPEED_SUPER) -+ r8153b_u1u2en(tp, true); -+} -+ -+static void rtl8156_down(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) { -+ rtl_drop_queued_tx(tp); -+ return; -+ } -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); -+ ocp_data |= PLA_MCU_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); -+ -+ r8153b_u1u2en(tp, false); -+ r8153_u2p3en(tp, false); -+ r8153b_power_cut_en(tp, false); -+ r8153_aldps_en(tp, false); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); -+ ocp_data &= ~NOW_IS_OOB; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); -+ -+ rtl_disable(tp); -+ rtl_reset_bmu(tp); -+ -+ /* Clear teredo wake event. bit[15:8] is the teredo wakeup -+ * type. Set it to zero. bits[7:0] are the W1C bits about -+ * the events. Set them to all 1 to clear them. -+ */ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); -+ ocp_data |= NOW_IS_OOB; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); -+ -+ rtl_rx_vlan_en(tp, true); -+ rxdy_gated_en(tp, false); -+ -+ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); -+ ocp_data |= RCR_APM | RCR_AM | RCR_AB; -+ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); -+ -+ r8153_aldps_en(tp, true); -+} -+ - static bool rtl8152_in_nway(struct r8152 *tp) - { - u16 nway_state; -@@ -5128,7 +6004,7 @@ static void set_carrier(struct r8152 *tp - { - struct net_device *netdev = tp->netdev; - struct napi_struct *napi = &tp->napi; -- u8 speed; -+ u16 speed; - - speed = rtl8152_get_speed(tp); - -@@ -5141,7 +6017,7 @@ static void set_carrier(struct r8152 *tp - rtl_start_rx(tp); - clear_bit(RTL8152_SET_RX_MODE, &tp->flags); - _rtl8152_set_rx_mode(netdev); -- napi_enable(&tp->napi); -+ napi_enable(napi); - netif_wake_queue(netdev); - netif_info(tp, link, netdev, "carrier on\n"); - } else if (netif_queue_stopped(netdev) && -@@ -5521,14 +6397,9 @@ static void r8153_init(struct r8152 *tp) - - ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); - -- /* MAC clock speed down */ -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0); -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0); -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0); -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0); -- - r8153_power_cut_en(tp, false); - rtl_runtime_suspend_enable(tp, false); -+ r8153_mac_clk_speed_down(tp, false); - r8153_u1u2en(tp, true); - usb_enable_lpm(tp->udev); - -@@ -5621,9 +6492,7 @@ static void r8153b_init(struct r8152 *tp - usb_enable_lpm(tp->udev); - - /* MAC clock speed down */ -- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); -- ocp_data |= MAC_CLK_SPDWN_EN; -- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); -+ r8153_mac_clk_speed_down(tp, true); - - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); - ocp_data &= ~PLA_MCU_SPDWN_EN; -@@ -5652,6 +6521,1069 @@ static void r8153b_init(struct r8152 *tp - r8152_led_configuration(tp); - } - -+static void r8153c_init(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 data; -+ int i; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ -+ r8153b_u1u2en(tp, false); -+ -+ /* Disable spi_en */ -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5); -+ ocp_data &= ~BIT(3); -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data); -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, 0xcbf0); -+ ocp_data |= BIT(1); -+ ocp_write_word(tp, MCU_TYPE_USB, 0xcbf0, ocp_data); -+ -+ for (i = 0; i < 500; i++) { -+ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & -+ AUTOLOAD_DONE) -+ break; -+ -+ msleep(20); -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ } -+ -+ data = r8153_phy_status(tp, 0); -+ -+ data = r8152_mdio_read(tp, MII_BMCR); -+ if (data & BMCR_PDOWN) { -+ data &= ~BMCR_PDOWN; -+ r8152_mdio_write(tp, MII_BMCR, data); -+ } -+ -+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); -+ -+ r8153_u2p3en(tp, false); -+ -+ /* MSC timer = 0xfff * 8ms = 32760 ms */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); -+ -+ r8153b_power_cut_en(tp, false); -+ r8153c_ups_en(tp, false); -+ r8153_queue_wake(tp, false); -+ rtl_runtime_suspend_enable(tp, false); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); -+ if (rtl8152_get_speed(tp) & LINK_STATUS) -+ ocp_data |= CUR_LINK_OK; -+ else -+ ocp_data &= ~CUR_LINK_OK; -+ -+ ocp_data |= POLL_LINK_CHG; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); -+ -+ r8153b_u1u2en(tp, true); -+ -+ usb_enable_lpm(tp->udev); -+ -+ /* MAC clock speed down */ -+ r8153_mac_clk_speed_down(tp, true); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); -+ ocp_data &= ~BIT(7); -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); -+ -+ set_bit(GREEN_ETHERNET, &tp->flags); -+ -+ /* rx aggregation */ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); -+ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); -+ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); -+ -+ rtl_tally_reset(tp); -+ -+ tp->coalesce = 15000; /* 15 us */ -+} -+ -+static void r8156_hw_phy_cfg(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 data; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); -+ if (ocp_data & PCUT_STATUS) { -+ ocp_data &= ~PCUT_STATUS; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); -+ } -+ -+ data = r8153_phy_status(tp, 0); -+ switch (data) { -+ case PHY_STAT_EXT_INIT: -+ rtl8152_apply_firmware(tp, true); -+ -+ data = ocp_reg_read(tp, 0xa468); -+ data &= ~(BIT(3) | BIT(1)); -+ ocp_reg_write(tp, 0xa468, data); -+ break; -+ case PHY_STAT_LAN_ON: -+ case PHY_STAT_PWRDN: -+ default: -+ rtl8152_apply_firmware(tp, false); -+ break; -+ } -+ -+ /* disable ALDPS before updating the PHY parameters */ -+ r8153_aldps_en(tp, false); -+ -+ /* disable EEE before updating the PHY parameters */ -+ rtl_eee_enable(tp, false); -+ -+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); -+ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); -+ ocp_data |= PFM_PWM_SWITCH; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); -+ -+ switch (tp->version) { -+ case RTL_VER_10: -+ data = ocp_reg_read(tp, 0xad40); -+ data &= ~0x3ff; -+ data |= BIT(7) | BIT(2); -+ ocp_reg_write(tp, 0xad40, data); -+ -+ data = ocp_reg_read(tp, 0xad4e); -+ data |= BIT(4); -+ ocp_reg_write(tp, 0xad4e, data); -+ data = ocp_reg_read(tp, 0xad16); -+ data &= ~0x3ff; -+ data |= 0x6; -+ ocp_reg_write(tp, 0xad16, data); -+ data = ocp_reg_read(tp, 0xad32); -+ data &= ~0x3f; -+ data |= 6; -+ ocp_reg_write(tp, 0xad32, data); -+ data = ocp_reg_read(tp, 0xac08); -+ data &= ~(BIT(12) | BIT(8)); -+ ocp_reg_write(tp, 0xac08, data); -+ data = ocp_reg_read(tp, 0xac8a); -+ data |= BIT(12) | BIT(13) | BIT(14); -+ data &= ~BIT(15); -+ ocp_reg_write(tp, 0xac8a, data); -+ data = ocp_reg_read(tp, 0xad18); -+ data |= BIT(10); -+ ocp_reg_write(tp, 0xad18, data); -+ data = ocp_reg_read(tp, 0xad1a); -+ data |= 0x3ff; -+ ocp_reg_write(tp, 0xad1a, data); -+ data = ocp_reg_read(tp, 0xad1c); -+ data |= 0x3ff; -+ ocp_reg_write(tp, 0xad1c, data); -+ -+ data = sram_read(tp, 0x80ea); -+ data &= ~0xff00; -+ data |= 0xc400; -+ sram_write(tp, 0x80ea, data); -+ data = sram_read(tp, 0x80eb); -+ data &= ~0x0700; -+ data |= 0x0300; -+ sram_write(tp, 0x80eb, data); -+ data = sram_read(tp, 0x80f8); -+ data &= ~0xff00; -+ data |= 0x1c00; -+ sram_write(tp, 0x80f8, data); -+ data = sram_read(tp, 0x80f1); -+ data &= ~0xff00; -+ data |= 0x3000; -+ sram_write(tp, 0x80f1, data); -+ -+ data = sram_read(tp, 0x80fe); -+ data &= ~0xff00; -+ data |= 0xa500; -+ sram_write(tp, 0x80fe, data); -+ data = sram_read(tp, 0x8102); -+ data &= ~0xff00; -+ data |= 0x5000; -+ sram_write(tp, 0x8102, data); -+ data = sram_read(tp, 0x8015); -+ data &= ~0xff00; -+ data |= 0x3300; -+ sram_write(tp, 0x8015, data); -+ data = sram_read(tp, 0x8100); -+ data &= ~0xff00; -+ data |= 0x7000; -+ sram_write(tp, 0x8100, data); -+ data = sram_read(tp, 0x8014); -+ data &= ~0xff00; -+ data |= 0xf000; -+ sram_write(tp, 0x8014, data); -+ data = sram_read(tp, 0x8016); -+ data &= ~0xff00; -+ data |= 0x6500; -+ sram_write(tp, 0x8016, data); -+ data = sram_read(tp, 0x80dc); -+ data &= ~0xff00; -+ data |= 0xed00; -+ sram_write(tp, 0x80dc, data); -+ data = sram_read(tp, 0x80df); -+ data |= BIT(8); -+ sram_write(tp, 0x80df, data); -+ data = sram_read(tp, 0x80e1); -+ data &= ~BIT(8); -+ sram_write(tp, 0x80e1, data); -+ -+ data = ocp_reg_read(tp, 0xbf06); -+ data &= ~0x003f; -+ data |= 0x0038; -+ ocp_reg_write(tp, 0xbf06, data); -+ -+ sram_write(tp, 0x819f, 0xddb6); -+ -+ ocp_reg_write(tp, 0xbc34, 0x5555); -+ data = ocp_reg_read(tp, 0xbf0a); -+ data &= ~0x0e00; -+ data |= 0x0a00; -+ ocp_reg_write(tp, 0xbf0a, data); -+ -+ data = ocp_reg_read(tp, 0xbd2c); -+ data &= ~BIT(13); -+ ocp_reg_write(tp, 0xbd2c, data); -+ break; -+ case RTL_VER_11: -+ data = ocp_reg_read(tp, 0xad16); -+ data |= 0x3ff; -+ ocp_reg_write(tp, 0xad16, data); -+ data = ocp_reg_read(tp, 0xad32); -+ data &= ~0x3f; -+ data |= 6; -+ ocp_reg_write(tp, 0xad32, data); -+ data = ocp_reg_read(tp, 0xac08); -+ data &= ~(BIT(12) | BIT(8)); -+ ocp_reg_write(tp, 0xac08, data); -+ data = ocp_reg_read(tp, 0xacc0); -+ data &= ~0x3; -+ data |= BIT(1); -+ ocp_reg_write(tp, 0xacc0, data); -+ data = ocp_reg_read(tp, 0xad40); -+ data &= ~0xe7; -+ data |= BIT(6) | BIT(2); -+ ocp_reg_write(tp, 0xad40, data); -+ data = ocp_reg_read(tp, 0xac14); -+ data &= ~BIT(7); -+ ocp_reg_write(tp, 0xac14, data); -+ data = ocp_reg_read(tp, 0xac80); -+ data &= ~(BIT(8) | BIT(9)); -+ ocp_reg_write(tp, 0xac80, data); -+ data = ocp_reg_read(tp, 0xac5e); -+ data &= ~0x7; -+ data |= BIT(1); -+ ocp_reg_write(tp, 0xac5e, data); -+ ocp_reg_write(tp, 0xad4c, 0x00a8); -+ ocp_reg_write(tp, 0xac5c, 0x01ff); -+ data = ocp_reg_read(tp, 0xac8a); -+ data &= ~0xf0; -+ data |= BIT(4) | BIT(5); -+ ocp_reg_write(tp, 0xac8a, data); -+ ocp_reg_write(tp, 0xb87c, 0x8157); -+ data = ocp_reg_read(tp, 0xb87e); -+ data &= ~0xff00; -+ data |= 0x0500; -+ ocp_reg_write(tp, 0xb87e, data); -+ ocp_reg_write(tp, 0xb87c, 0x8159); -+ data = ocp_reg_read(tp, 0xb87e); -+ data &= ~0xff00; -+ data |= 0x0700; -+ ocp_reg_write(tp, 0xb87e, data); -+ -+ /* AAGC */ -+ ocp_reg_write(tp, 0xb87c, 0x80a2); -+ ocp_reg_write(tp, 0xb87e, 0x0153); -+ ocp_reg_write(tp, 0xb87c, 0x809c); -+ ocp_reg_write(tp, 0xb87e, 0x0153); -+ -+ /* EEE parameter */ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS_2P5G, 0x0056); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_USB_CFG); -+ ocp_data |= EN_XG_LIP | EN_G_LIP; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_USB_CFG, ocp_data); -+ -+ sram_write(tp, 0x8257, 0x020f); /* XG PLL */ -+ sram_write(tp, 0x80ea, 0x7843); /* GIGA Master */ -+ -+ if (rtl_phy_patch_request(tp, true, true)) -+ return; -+ -+ /* Advance EEE */ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); -+ ocp_data |= EEE_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); -+ -+ data = ocp_reg_read(tp, OCP_DOWN_SPEED); -+ data &= ~(EN_EEE_100 | EN_EEE_1000); -+ data |= EN_10M_CLKDIV; -+ ocp_reg_write(tp, OCP_DOWN_SPEED, data); -+ tp->ups_info._10m_ckdiv = true; -+ tp->ups_info.eee_plloff_100 = false; -+ tp->ups_info.eee_plloff_giga = false; -+ -+ data = ocp_reg_read(tp, OCP_POWER_CFG); -+ data &= ~EEE_CLKDIV_EN; -+ ocp_reg_write(tp, OCP_POWER_CFG, data); -+ tp->ups_info.eee_ckdiv = false; -+ -+ ocp_reg_write(tp, OCP_SYSCLK_CFG, 0); -+ ocp_reg_write(tp, OCP_SYSCLK_CFG, sysclk_div_expo(5)); -+ tp->ups_info._250m_ckdiv = false; -+ -+ rtl_phy_patch_request(tp, false, true); -+ -+ /* enable ADC Ibias Cal */ -+ data = ocp_reg_read(tp, 0xd068); -+ data |= BIT(13); -+ ocp_reg_write(tp, 0xd068, data); -+ -+ /* enable Thermal Sensor */ -+ data = sram_read(tp, 0x81a2); -+ data &= ~BIT(8); -+ sram_write(tp, 0x81a2, data); -+ data = ocp_reg_read(tp, 0xb54c); -+ data &= ~0xff00; -+ data |= 0xdb00; -+ ocp_reg_write(tp, 0xb54c, data); -+ -+ /* Nway 2.5G Lite */ -+ data = ocp_reg_read(tp, 0xa454); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xa454, data); -+ -+ /* CS DSP solution */ -+ data = ocp_reg_read(tp, OCP_10GBT_CTRL); -+ data |= RTL_ADV2_5G_F_R; -+ ocp_reg_write(tp, OCP_10GBT_CTRL, data); -+ data = ocp_reg_read(tp, 0xad4e); -+ data &= ~BIT(4); -+ ocp_reg_write(tp, 0xad4e, data); -+ data = ocp_reg_read(tp, 0xa86a); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xa86a, data); -+ -+ /* MDI SWAP */ -+ if ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) & MID_REVERSE) && -+ (ocp_reg_read(tp, 0xd068) & BIT(1))) { -+ u16 swap_a, swap_b; -+ -+ data = ocp_reg_read(tp, 0xd068); -+ data &= ~0x1f; -+ data |= 0x1; /* p0 */ -+ ocp_reg_write(tp, 0xd068, data); -+ swap_a = ocp_reg_read(tp, 0xd06a); -+ data &= ~0x18; -+ data |= 0x18; /* p3 */ -+ ocp_reg_write(tp, 0xd068, data); -+ swap_b = ocp_reg_read(tp, 0xd06a); -+ data &= ~0x18; /* p0 */ -+ ocp_reg_write(tp, 0xd068, data); -+ ocp_reg_write(tp, 0xd06a, -+ (swap_a & ~0x7ff) | (swap_b & 0x7ff)); -+ data |= 0x18; /* p3 */ -+ ocp_reg_write(tp, 0xd068, data); -+ ocp_reg_write(tp, 0xd06a, -+ (swap_b & ~0x7ff) | (swap_a & 0x7ff)); -+ data &= ~0x18; -+ data |= 0x08; /* p1 */ -+ ocp_reg_write(tp, 0xd068, data); -+ swap_a = ocp_reg_read(tp, 0xd06a); -+ data &= ~0x18; -+ data |= 0x10; /* p2 */ -+ ocp_reg_write(tp, 0xd068, data); -+ swap_b = ocp_reg_read(tp, 0xd06a); -+ data &= ~0x18; -+ data |= 0x08; /* p1 */ -+ ocp_reg_write(tp, 0xd068, data); -+ ocp_reg_write(tp, 0xd06a, -+ (swap_a & ~0x7ff) | (swap_b & 0x7ff)); -+ data &= ~0x18; -+ data |= 0x10; /* p2 */ -+ ocp_reg_write(tp, 0xd068, data); -+ ocp_reg_write(tp, 0xd06a, -+ (swap_b & ~0x7ff) | (swap_a & 0x7ff)); -+ swap_a = ocp_reg_read(tp, 0xbd5a); -+ swap_b = ocp_reg_read(tp, 0xbd5c); -+ ocp_reg_write(tp, 0xbd5a, (swap_a & ~0x1f1f) | -+ ((swap_b & 0x1f) << 8) | -+ ((swap_b >> 8) & 0x1f)); -+ ocp_reg_write(tp, 0xbd5c, (swap_b & ~0x1f1f) | -+ ((swap_a & 0x1f) << 8) | -+ ((swap_a >> 8) & 0x1f)); -+ swap_a = ocp_reg_read(tp, 0xbc18); -+ swap_b = ocp_reg_read(tp, 0xbc1a); -+ ocp_reg_write(tp, 0xbc18, (swap_a & ~0x1f1f) | -+ ((swap_b & 0x1f) << 8) | -+ ((swap_b >> 8) & 0x1f)); -+ ocp_reg_write(tp, 0xbc1a, (swap_b & ~0x1f1f) | -+ ((swap_a & 0x1f) << 8) | -+ ((swap_a >> 8) & 0x1f)); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); -+ -+ data = ocp_reg_read(tp, 0xa428); -+ data &= ~BIT(9); -+ ocp_reg_write(tp, 0xa428, data); -+ data = ocp_reg_read(tp, 0xa5ea); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xa5ea, data); -+ tp->ups_info.lite_mode = 0; -+ -+ if (tp->eee_en) -+ rtl_eee_enable(tp, true); -+ -+ r8153_aldps_en(tp, true); -+ r8152b_enable_fc(tp); -+ r8153_u2p3en(tp, true); -+ -+ set_bit(PHY_RESET, &tp->flags); -+} -+ -+static void r8156b_hw_phy_cfg(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 data; -+ -+ switch (tp->version) { -+ case RTL_VER_12: -+ ocp_reg_write(tp, 0xbf86, 0x9000); -+ data = ocp_reg_read(tp, 0xc402); -+ data |= BIT(10); -+ ocp_reg_write(tp, 0xc402, data); -+ data &= ~BIT(10); -+ ocp_reg_write(tp, 0xc402, data); -+ ocp_reg_write(tp, 0xbd86, 0x1010); -+ ocp_reg_write(tp, 0xbd88, 0x1010); -+ data = ocp_reg_read(tp, 0xbd4e); -+ data &= ~(BIT(10) | BIT(11)); -+ data |= BIT(11); -+ ocp_reg_write(tp, 0xbd4e, data); -+ data = ocp_reg_read(tp, 0xbf46); -+ data &= ~0xf00; -+ data |= 0x700; -+ ocp_reg_write(tp, 0xbf46, data); -+ break; -+ case RTL_VER_13: -+ case RTL_VER_15: -+ r8156b_wait_loading_flash(tp); -+ break; -+ default: -+ break; -+ } -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); -+ if (ocp_data & PCUT_STATUS) { -+ ocp_data &= ~PCUT_STATUS; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); -+ } -+ -+ data = r8153_phy_status(tp, 0); -+ switch (data) { -+ case PHY_STAT_EXT_INIT: -+ rtl8152_apply_firmware(tp, true); -+ -+ data = ocp_reg_read(tp, 0xa466); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xa466, data); -+ -+ data = ocp_reg_read(tp, 0xa468); -+ data &= ~(BIT(3) | BIT(1)); -+ ocp_reg_write(tp, 0xa468, data); -+ break; -+ case PHY_STAT_LAN_ON: -+ case PHY_STAT_PWRDN: -+ default: -+ rtl8152_apply_firmware(tp, false); -+ break; -+ } -+ -+ data = r8152_mdio_read(tp, MII_BMCR); -+ if (data & BMCR_PDOWN) { -+ data &= ~BMCR_PDOWN; -+ r8152_mdio_write(tp, MII_BMCR, data); -+ } -+ -+ /* disable ALDPS before updating the PHY parameters */ -+ r8153_aldps_en(tp, false); -+ -+ /* disable EEE before updating the PHY parameters */ -+ rtl_eee_enable(tp, false); -+ -+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); -+ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); -+ ocp_data |= PFM_PWM_SWITCH; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); -+ -+ switch (tp->version) { -+ case RTL_VER_12: -+ data = ocp_reg_read(tp, 0xbc08); -+ data |= BIT(3) | BIT(2); -+ ocp_reg_write(tp, 0xbc08, data); -+ -+ data = sram_read(tp, 0x8fff); -+ data &= ~0xff00; -+ data |= 0x0400; -+ sram_write(tp, 0x8fff, data); -+ -+ data = ocp_reg_read(tp, 0xacda); -+ data |= 0xff00; -+ ocp_reg_write(tp, 0xacda, data); -+ data = ocp_reg_read(tp, 0xacde); -+ data |= 0xf000; -+ ocp_reg_write(tp, 0xacde, data); -+ ocp_reg_write(tp, 0xac8c, 0x0ffc); -+ ocp_reg_write(tp, 0xac46, 0xb7b4); -+ ocp_reg_write(tp, 0xac50, 0x0fbc); -+ ocp_reg_write(tp, 0xac3c, 0x9240); -+ ocp_reg_write(tp, 0xac4e, 0x0db4); -+ ocp_reg_write(tp, 0xacc6, 0x0707); -+ ocp_reg_write(tp, 0xacc8, 0xa0d3); -+ ocp_reg_write(tp, 0xad08, 0x0007); -+ -+ ocp_reg_write(tp, 0xb87c, 0x8560); -+ ocp_reg_write(tp, 0xb87e, 0x19cc); -+ ocp_reg_write(tp, 0xb87c, 0x8562); -+ ocp_reg_write(tp, 0xb87e, 0x19cc); -+ ocp_reg_write(tp, 0xb87c, 0x8564); -+ ocp_reg_write(tp, 0xb87e, 0x19cc); -+ ocp_reg_write(tp, 0xb87c, 0x8566); -+ ocp_reg_write(tp, 0xb87e, 0x147d); -+ ocp_reg_write(tp, 0xb87c, 0x8568); -+ ocp_reg_write(tp, 0xb87e, 0x147d); -+ ocp_reg_write(tp, 0xb87c, 0x856a); -+ ocp_reg_write(tp, 0xb87e, 0x147d); -+ ocp_reg_write(tp, 0xb87c, 0x8ffe); -+ ocp_reg_write(tp, 0xb87e, 0x0907); -+ ocp_reg_write(tp, 0xb87c, 0x80d6); -+ ocp_reg_write(tp, 0xb87e, 0x2801); -+ ocp_reg_write(tp, 0xb87c, 0x80f2); -+ ocp_reg_write(tp, 0xb87e, 0x2801); -+ ocp_reg_write(tp, 0xb87c, 0x80f4); -+ ocp_reg_write(tp, 0xb87e, 0x6077); -+ ocp_reg_write(tp, 0xb506, 0x01e7); -+ -+ ocp_reg_write(tp, 0xb87c, 0x8013); -+ ocp_reg_write(tp, 0xb87e, 0x0700); -+ ocp_reg_write(tp, 0xb87c, 0x8fb9); -+ ocp_reg_write(tp, 0xb87e, 0x2801); -+ ocp_reg_write(tp, 0xb87c, 0x8fba); -+ ocp_reg_write(tp, 0xb87e, 0x0100); -+ ocp_reg_write(tp, 0xb87c, 0x8fbc); -+ ocp_reg_write(tp, 0xb87e, 0x1900); -+ ocp_reg_write(tp, 0xb87c, 0x8fbe); -+ ocp_reg_write(tp, 0xb87e, 0xe100); -+ ocp_reg_write(tp, 0xb87c, 0x8fc0); -+ ocp_reg_write(tp, 0xb87e, 0x0800); -+ ocp_reg_write(tp, 0xb87c, 0x8fc2); -+ ocp_reg_write(tp, 0xb87e, 0xe500); -+ ocp_reg_write(tp, 0xb87c, 0x8fc4); -+ ocp_reg_write(tp, 0xb87e, 0x0f00); -+ ocp_reg_write(tp, 0xb87c, 0x8fc6); -+ ocp_reg_write(tp, 0xb87e, 0xf100); -+ ocp_reg_write(tp, 0xb87c, 0x8fc8); -+ ocp_reg_write(tp, 0xb87e, 0x0400); -+ ocp_reg_write(tp, 0xb87c, 0x8fca); -+ ocp_reg_write(tp, 0xb87e, 0xf300); -+ ocp_reg_write(tp, 0xb87c, 0x8fcc); -+ ocp_reg_write(tp, 0xb87e, 0xfd00); -+ ocp_reg_write(tp, 0xb87c, 0x8fce); -+ ocp_reg_write(tp, 0xb87e, 0xff00); -+ ocp_reg_write(tp, 0xb87c, 0x8fd0); -+ ocp_reg_write(tp, 0xb87e, 0xfb00); -+ ocp_reg_write(tp, 0xb87c, 0x8fd2); -+ ocp_reg_write(tp, 0xb87e, 0x0100); -+ ocp_reg_write(tp, 0xb87c, 0x8fd4); -+ ocp_reg_write(tp, 0xb87e, 0xf400); -+ ocp_reg_write(tp, 0xb87c, 0x8fd6); -+ ocp_reg_write(tp, 0xb87e, 0xff00); -+ ocp_reg_write(tp, 0xb87c, 0x8fd8); -+ ocp_reg_write(tp, 0xb87e, 0xf600); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_USB_CFG); -+ ocp_data |= EN_XG_LIP | EN_G_LIP; -+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_USB_CFG, ocp_data); -+ ocp_reg_write(tp, 0xb87c, 0x813d); -+ ocp_reg_write(tp, 0xb87e, 0x390e); -+ ocp_reg_write(tp, 0xb87c, 0x814f); -+ ocp_reg_write(tp, 0xb87e, 0x790e); -+ ocp_reg_write(tp, 0xb87c, 0x80b0); -+ ocp_reg_write(tp, 0xb87e, 0x0f31); -+ data = ocp_reg_read(tp, 0xbf4c); -+ data |= BIT(1); -+ ocp_reg_write(tp, 0xbf4c, data); -+ data = ocp_reg_read(tp, 0xbcca); -+ data |= BIT(9) | BIT(8); -+ ocp_reg_write(tp, 0xbcca, data); -+ ocp_reg_write(tp, 0xb87c, 0x8141); -+ ocp_reg_write(tp, 0xb87e, 0x320e); -+ ocp_reg_write(tp, 0xb87c, 0x8153); -+ ocp_reg_write(tp, 0xb87e, 0x720e); -+ ocp_reg_write(tp, 0xb87c, 0x8529); -+ ocp_reg_write(tp, 0xb87e, 0x050e); -+ data = ocp_reg_read(tp, OCP_EEE_CFG); -+ data &= ~CTAP_SHORT_EN; -+ ocp_reg_write(tp, OCP_EEE_CFG, data); -+ -+ sram_write(tp, 0x816c, 0xc4a0); -+ sram_write(tp, 0x8170, 0xc4a0); -+ sram_write(tp, 0x8174, 0x04a0); -+ sram_write(tp, 0x8178, 0x04a0); -+ sram_write(tp, 0x817c, 0x0719); -+ sram_write(tp, 0x8ff4, 0x0400); -+ sram_write(tp, 0x8ff1, 0x0404); -+ -+ ocp_reg_write(tp, 0xbf4a, 0x001b); -+ ocp_reg_write(tp, 0xb87c, 0x8033); -+ ocp_reg_write(tp, 0xb87e, 0x7c13); -+ ocp_reg_write(tp, 0xb87c, 0x8037); -+ ocp_reg_write(tp, 0xb87e, 0x7c13); -+ ocp_reg_write(tp, 0xb87c, 0x803b); -+ ocp_reg_write(tp, 0xb87e, 0xfc32); -+ ocp_reg_write(tp, 0xb87c, 0x803f); -+ ocp_reg_write(tp, 0xb87e, 0x7c13); -+ ocp_reg_write(tp, 0xb87c, 0x8043); -+ ocp_reg_write(tp, 0xb87e, 0x7c13); -+ ocp_reg_write(tp, 0xb87c, 0x8047); -+ ocp_reg_write(tp, 0xb87e, 0x7c13); -+ -+ ocp_reg_write(tp, 0xb87c, 0x8145); -+ ocp_reg_write(tp, 0xb87e, 0x370e); -+ ocp_reg_write(tp, 0xb87c, 0x8157); -+ ocp_reg_write(tp, 0xb87e, 0x770e); -+ ocp_reg_write(tp, 0xb87c, 0x8169); -+ ocp_reg_write(tp, 0xb87e, 0x0d0a); -+ ocp_reg_write(tp, 0xb87c, 0x817b); -+ ocp_reg_write(tp, 0xb87e, 0x1d0a); -+ -+ data = sram_read(tp, 0x8217); -+ data &= ~0xff00; -+ data |= 0x5000; -+ sram_write(tp, 0x8217, data); -+ data = sram_read(tp, 0x821a); -+ data &= ~0xff00; -+ data |= 0x5000; -+ sram_write(tp, 0x821a, data); -+ sram_write(tp, 0x80da, 0x0403); -+ data = sram_read(tp, 0x80dc); -+ data &= ~0xff00; -+ data |= 0x1000; -+ sram_write(tp, 0x80dc, data); -+ sram_write(tp, 0x80b3, 0x0384); -+ sram_write(tp, 0x80b7, 0x2007); -+ data = sram_read(tp, 0x80ba); -+ data &= ~0xff00; -+ data |= 0x6c00; -+ sram_write(tp, 0x80ba, data); -+ sram_write(tp, 0x80b5, 0xf009); -+ data = sram_read(tp, 0x80bd); -+ data &= ~0xff00; -+ data |= 0x9f00; -+ sram_write(tp, 0x80bd, data); -+ sram_write(tp, 0x80c7, 0xf083); -+ sram_write(tp, 0x80dd, 0x03f0); -+ data = sram_read(tp, 0x80df); -+ data &= ~0xff00; -+ data |= 0x1000; -+ sram_write(tp, 0x80df, data); -+ sram_write(tp, 0x80cb, 0x2007); -+ data = sram_read(tp, 0x80ce); -+ data &= ~0xff00; -+ data |= 0x6c00; -+ sram_write(tp, 0x80ce, data); -+ sram_write(tp, 0x80c9, 0x8009); -+ data = sram_read(tp, 0x80d1); -+ data &= ~0xff00; -+ data |= 0x8000; -+ sram_write(tp, 0x80d1, data); -+ sram_write(tp, 0x80a3, 0x200a); -+ sram_write(tp, 0x80a5, 0xf0ad); -+ sram_write(tp, 0x809f, 0x6073); -+ sram_write(tp, 0x80a1, 0x000b); -+ data = sram_read(tp, 0x80a9); -+ data &= ~0xff00; -+ data |= 0xc000; -+ sram_write(tp, 0x80a9, data); -+ -+ if (rtl_phy_patch_request(tp, true, true)) -+ return; -+ -+ data = ocp_reg_read(tp, 0xb896); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xb896, data); -+ data = ocp_reg_read(tp, 0xb892); -+ data &= ~0xff00; -+ ocp_reg_write(tp, 0xb892, data); -+ ocp_reg_write(tp, 0xb88e, 0xc23e); -+ ocp_reg_write(tp, 0xb890, 0x0000); -+ ocp_reg_write(tp, 0xb88e, 0xc240); -+ ocp_reg_write(tp, 0xb890, 0x0103); -+ ocp_reg_write(tp, 0xb88e, 0xc242); -+ ocp_reg_write(tp, 0xb890, 0x0507); -+ ocp_reg_write(tp, 0xb88e, 0xc244); -+ ocp_reg_write(tp, 0xb890, 0x090b); -+ ocp_reg_write(tp, 0xb88e, 0xc246); -+ ocp_reg_write(tp, 0xb890, 0x0c0e); -+ ocp_reg_write(tp, 0xb88e, 0xc248); -+ ocp_reg_write(tp, 0xb890, 0x1012); -+ ocp_reg_write(tp, 0xb88e, 0xc24a); -+ ocp_reg_write(tp, 0xb890, 0x1416); -+ data = ocp_reg_read(tp, 0xb896); -+ data |= BIT(0); -+ ocp_reg_write(tp, 0xb896, data); -+ -+ rtl_phy_patch_request(tp, false, true); -+ -+ data = ocp_reg_read(tp, 0xa86a); -+ data |= BIT(0); -+ ocp_reg_write(tp, 0xa86a, data); -+ data = ocp_reg_read(tp, 0xa6f0); -+ data |= BIT(0); -+ ocp_reg_write(tp, 0xa6f0, data); -+ -+ ocp_reg_write(tp, 0xbfa0, 0xd70d); -+ ocp_reg_write(tp, 0xbfa2, 0x4100); -+ ocp_reg_write(tp, 0xbfa4, 0xe868); -+ ocp_reg_write(tp, 0xbfa6, 0xdc59); -+ ocp_reg_write(tp, 0xb54c, 0x3c18); -+ data = ocp_reg_read(tp, 0xbfa4); -+ data &= ~BIT(5); -+ ocp_reg_write(tp, 0xbfa4, data); -+ data = sram_read(tp, 0x817d); -+ data |= BIT(12); -+ sram_write(tp, 0x817d, data); -+ break; -+ case RTL_VER_13: -+ /* 2.5G INRX */ -+ data = ocp_reg_read(tp, 0xac46); -+ data &= ~0x00f0; -+ data |= 0x0090; -+ ocp_reg_write(tp, 0xac46, data); -+ data = ocp_reg_read(tp, 0xad30); -+ data &= ~0x0003; -+ data |= 0x0001; -+ ocp_reg_write(tp, 0xad30, data); -+ fallthrough; -+ case RTL_VER_15: -+ /* EEE parameter */ -+ ocp_reg_write(tp, 0xb87c, 0x80f5); -+ ocp_reg_write(tp, 0xb87e, 0x760e); -+ ocp_reg_write(tp, 0xb87c, 0x8107); -+ ocp_reg_write(tp, 0xb87e, 0x360e); -+ ocp_reg_write(tp, 0xb87c, 0x8551); -+ data = ocp_reg_read(tp, 0xb87e); -+ data &= ~0xff00; -+ data |= 0x0800; -+ ocp_reg_write(tp, 0xb87e, data); -+ -+ /* ADC_PGA parameter */ -+ data = ocp_reg_read(tp, 0xbf00); -+ data &= ~0xe000; -+ data |= 0xa000; -+ ocp_reg_write(tp, 0xbf00, data); -+ data = ocp_reg_read(tp, 0xbf46); -+ data &= ~0x0f00; -+ data |= 0x0300; -+ ocp_reg_write(tp, 0xbf46, data); -+ -+ /* Green Table-PGA, 1G full viterbi */ -+ sram_write(tp, 0x8044, 0x2417); -+ sram_write(tp, 0x804a, 0x2417); -+ sram_write(tp, 0x8050, 0x2417); -+ sram_write(tp, 0x8056, 0x2417); -+ sram_write(tp, 0x805c, 0x2417); -+ sram_write(tp, 0x8062, 0x2417); -+ sram_write(tp, 0x8068, 0x2417); -+ sram_write(tp, 0x806e, 0x2417); -+ sram_write(tp, 0x8074, 0x2417); -+ sram_write(tp, 0x807a, 0x2417); -+ -+ /* XG PLL */ -+ data = ocp_reg_read(tp, 0xbf84); -+ data &= ~0xe000; -+ data |= 0xa000; -+ ocp_reg_write(tp, 0xbf84, data); -+ break; -+ default: -+ break; -+ } -+ -+ if (rtl_phy_patch_request(tp, true, true)) -+ return; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); -+ ocp_data |= EEE_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); -+ -+ data = ocp_reg_read(tp, OCP_DOWN_SPEED); -+ data &= ~(EN_EEE_100 | EN_EEE_1000); -+ data |= EN_10M_CLKDIV; -+ ocp_reg_write(tp, OCP_DOWN_SPEED, data); -+ tp->ups_info._10m_ckdiv = true; -+ tp->ups_info.eee_plloff_100 = false; -+ tp->ups_info.eee_plloff_giga = false; -+ -+ data = ocp_reg_read(tp, OCP_POWER_CFG); -+ data &= ~EEE_CLKDIV_EN; -+ ocp_reg_write(tp, OCP_POWER_CFG, data); -+ tp->ups_info.eee_ckdiv = false; -+ -+ rtl_phy_patch_request(tp, false, true); -+ -+ rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); -+ -+ data = ocp_reg_read(tp, 0xa428); -+ data &= ~BIT(9); -+ ocp_reg_write(tp, 0xa428, data); -+ data = ocp_reg_read(tp, 0xa5ea); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xa5ea, data); -+ tp->ups_info.lite_mode = 0; -+ -+ if (tp->eee_en) -+ rtl_eee_enable(tp, true); -+ -+ r8153_aldps_en(tp, true); -+ r8152b_enable_fc(tp); -+ r8153_u2p3en(tp, true); -+ -+ set_bit(PHY_RESET, &tp->flags); -+} -+ -+static void r8156_init(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 data; -+ int i; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP); -+ ocp_data &= ~EN_ALL_SPEED; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data); -+ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION); -+ ocp_data |= BYPASS_MAC_RESET; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data); -+ -+ r8153b_u1u2en(tp, false); -+ -+ for (i = 0; i < 500; i++) { -+ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & -+ AUTOLOAD_DONE) -+ break; -+ -+ msleep(20); -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ } -+ -+ data = r8153_phy_status(tp, 0); -+ if (data == PHY_STAT_EXT_INIT) { -+ data = ocp_reg_read(tp, 0xa468); -+ data &= ~(BIT(3) | BIT(1)); -+ ocp_reg_write(tp, 0xa468, data); -+ } -+ -+ data = r8152_mdio_read(tp, MII_BMCR); -+ if (data & BMCR_PDOWN) { -+ data &= ~BMCR_PDOWN; -+ r8152_mdio_write(tp, MII_BMCR, data); -+ } -+ -+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); -+ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); -+ -+ r8153_u2p3en(tp, false); -+ -+ /* MSC timer = 0xfff * 8ms = 32760 ms */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); -+ -+ /* U1/U2/L1 idle timer. 500 us */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); -+ -+ r8153b_power_cut_en(tp, false); -+ r8156_ups_en(tp, false); -+ r8153_queue_wake(tp, false); -+ rtl_runtime_suspend_enable(tp, false); -+ -+ if (tp->udev->speed >= USB_SPEED_SUPER) -+ r8153b_u1u2en(tp, true); -+ -+ usb_enable_lpm(tp->udev); -+ -+ r8156_mac_clk_spd(tp, true); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); -+ ocp_data &= ~PLA_MCU_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); -+ if (rtl8152_get_speed(tp) & LINK_STATUS) -+ ocp_data |= CUR_LINK_OK; -+ else -+ ocp_data &= ~CUR_LINK_OK; -+ ocp_data |= POLL_LINK_CHG; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); -+ -+ set_bit(GREEN_ETHERNET, &tp->flags); -+ -+ /* rx aggregation */ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); -+ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); -+ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG); -+ ocp_data |= ACT_ODMA; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); -+ -+ rtl_tally_reset(tp); -+ -+ tp->coalesce = 15000; /* 15 us */ -+} -+ -+static void r8156b_init(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ u16 data; -+ int i; -+ -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ -+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP); -+ ocp_data &= ~EN_ALL_SPEED; -+ ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data); -+ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION); -+ ocp_data |= BYPASS_MAC_RESET; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); -+ ocp_data |= RX_DETECT8; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); -+ -+ r8153b_u1u2en(tp, false); -+ -+ switch (tp->version) { -+ case RTL_VER_13: -+ case RTL_VER_15: -+ r8156b_wait_loading_flash(tp); -+ break; -+ default: -+ break; -+ } -+ -+ for (i = 0; i < 500; i++) { -+ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & -+ AUTOLOAD_DONE) -+ break; -+ -+ msleep(20); -+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) -+ return; -+ } -+ -+ data = r8153_phy_status(tp, 0); -+ if (data == PHY_STAT_EXT_INIT) { -+ data = ocp_reg_read(tp, 0xa468); -+ data &= ~(BIT(3) | BIT(1)); -+ ocp_reg_write(tp, 0xa468, data); -+ -+ data = ocp_reg_read(tp, 0xa466); -+ data &= ~BIT(0); -+ ocp_reg_write(tp, 0xa466, data); -+ } -+ -+ data = r8152_mdio_read(tp, MII_BMCR); -+ if (data & BMCR_PDOWN) { -+ data &= ~BMCR_PDOWN; -+ r8152_mdio_write(tp, MII_BMCR, data); -+ } -+ -+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); -+ -+ r8153_u2p3en(tp, false); -+ -+ /* MSC timer = 0xfff * 8ms = 32760 ms */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); -+ -+ /* U1/U2/L1 idle timer. 500 us */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); -+ -+ r8153b_power_cut_en(tp, false); -+ r8156_ups_en(tp, false); -+ r8153_queue_wake(tp, false); -+ rtl_runtime_suspend_enable(tp, false); -+ -+ if (tp->udev->speed >= USB_SPEED_SUPER) -+ r8153b_u1u2en(tp, true); -+ -+ usb_enable_lpm(tp->udev); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR); -+ ocp_data &= ~SLOT_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); -+ ocp_data |= FLOW_CTRL_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); -+ -+ /* enable fc timer and set timer to 600 ms. */ -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER, -+ CTRL_TIMER_EN | (600 / 8)); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL); -+ if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & DACK_DET_EN)) -+ ocp_data |= FLOW_CTRL_PATCH_2; -+ ocp_data &= ~AUTO_SPEEDUP; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); -+ ocp_data |= FC_PATCH_TASK; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); -+ -+ r8156_mac_clk_spd(tp, true); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); -+ ocp_data &= ~PLA_MCU_SPDWN_EN; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); -+ if (rtl8152_get_speed(tp) & LINK_STATUS) -+ ocp_data |= CUR_LINK_OK; -+ else -+ ocp_data &= ~CUR_LINK_OK; -+ ocp_data |= POLL_LINK_CHG; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); -+ -+ set_bit(GREEN_ETHERNET, &tp->flags); -+ -+ /* rx aggregation */ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); -+ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); -+ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); -+ -+ rtl_tally_reset(tp); -+ -+ tp->coalesce = 15000; /* 15 us */ -+} -+ - static int rtl8152_pre_reset(struct usb_interface *intf) - { - struct r8152 *tp = usb_get_intfdata(intf); -@@ -6015,6 +7947,22 @@ int rtl8152_get_link_ksettings(struct ne - - mii_ethtool_get_link_ksettings(&tp->mii, cmd); - -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ cmd->link_modes.supported, tp->support_2500full); -+ -+ if (tp->support_2500full) { -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ cmd->link_modes.advertising, -+ ocp_reg_read(tp, OCP_10GBT_CTRL) & MDIO_AN_10GBT_CTRL_ADV2_5G); -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ cmd->link_modes.lp_advertising, -+ ocp_reg_read(tp, OCP_10GBT_STAT) & MDIO_AN_10GBT_STAT_LP2_5G); -+ -+ if (is_speed_2500(rtl8152_get_speed(tp))) -+ cmd->base.speed = SPEED_2500; -+ } -+ - mutex_unlock(&tp->control); - - usb_autopm_put_interface(tp->intf); -@@ -6058,6 +8006,10 @@ static int rtl8152_set_link_ksettings(st - cmd->link_modes.advertising)) - advertising |= RTL_ADVERTISED_1000_FULL; - -+ if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ cmd->link_modes.advertising)) -+ advertising |= RTL_ADVERTISED_2500_FULL; -+ - mutex_lock(&tp->control); - - ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed, -@@ -6647,6 +8599,67 @@ static int rtl_ops_init(struct r8152 *tp - tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; - break; - -+ case RTL_VER_11: -+ tp->eee_en = true; -+ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; -+ fallthrough; -+ case RTL_VER_10: -+ ops->init = r8156_init; -+ ops->enable = rtl8156_enable; -+ ops->disable = rtl8153_disable; -+ ops->up = rtl8156_up; -+ ops->down = rtl8156_down; -+ ops->unload = rtl8153_unload; -+ ops->eee_get = r8153_get_eee; -+ ops->eee_set = r8152_set_eee; -+ ops->in_nway = rtl8153_in_nway; -+ ops->hw_phy_cfg = r8156_hw_phy_cfg; -+ ops->autosuspend_en = rtl8156_runtime_enable; -+ ops->change_mtu = rtl8156_change_mtu; -+ tp->rx_buf_sz = 48 * 1024; -+ tp->support_2500full = 1; -+ break; -+ -+ case RTL_VER_12: -+ case RTL_VER_13: -+ tp->support_2500full = 1; -+ fallthrough; -+ case RTL_VER_15: -+ tp->eee_en = true; -+ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; -+ ops->init = r8156b_init; -+ ops->enable = rtl8156b_enable; -+ ops->disable = rtl8153_disable; -+ ops->up = rtl8156_up; -+ ops->down = rtl8156_down; -+ ops->unload = rtl8153_unload; -+ ops->eee_get = r8153_get_eee; -+ ops->eee_set = r8152_set_eee; -+ ops->in_nway = rtl8153_in_nway; -+ ops->hw_phy_cfg = r8156b_hw_phy_cfg; -+ ops->autosuspend_en = rtl8156_runtime_enable; -+ ops->change_mtu = rtl8156_change_mtu; -+ tp->rx_buf_sz = 48 * 1024; -+ break; -+ -+ case RTL_VER_14: -+ ops->init = r8153c_init; -+ ops->enable = rtl8153_enable; -+ ops->disable = rtl8153_disable; -+ ops->up = rtl8153c_up; -+ ops->down = rtl8153b_down; -+ ops->unload = rtl8153_unload; -+ ops->eee_get = r8153_get_eee; -+ ops->eee_set = r8152_set_eee; -+ ops->in_nway = rtl8153_in_nway; -+ ops->hw_phy_cfg = r8153c_hw_phy_cfg; -+ ops->autosuspend_en = rtl8153c_runtime_enable; -+ ops->change_mtu = rtl8153c_change_mtu; -+ tp->rx_buf_sz = 32 * 1024; -+ tp->eee_en = true; -+ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; -+ break; -+ - default: - ret = -ENODEV; - dev_err(&tp->intf->dev, "Unknown Device\n"); -@@ -6660,11 +8673,13 @@ static int rtl_ops_init(struct r8152 *tp - #define FIRMWARE_8153A_3 "rtl_nic/rtl8153a-3.fw" - #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" - #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" -+#define FIRMWARE_8153C_1 "rtl_nic/rtl8153c-1.fw" - - MODULE_FIRMWARE(FIRMWARE_8153A_2); - MODULE_FIRMWARE(FIRMWARE_8153A_3); - MODULE_FIRMWARE(FIRMWARE_8153A_4); - MODULE_FIRMWARE(FIRMWARE_8153B_2); -+MODULE_FIRMWARE(FIRMWARE_8153C_1); - - static int rtl_fw_init(struct r8152 *tp) - { -@@ -6690,6 +8705,11 @@ static int rtl_fw_init(struct r8152 *tp) - rtl_fw->pre_fw = r8153b_pre_firmware_1; - rtl_fw->post_fw = r8153b_post_firmware_1; - break; -+ case RTL_VER_14: -+ rtl_fw->fw_name = FIRMWARE_8153C_1; -+ rtl_fw->pre_fw = r8153b_pre_firmware_1; -+ rtl_fw->post_fw = r8153c_post_firmware_1; -+ break; - default: - break; - } -@@ -6745,6 +8765,27 @@ u8 rtl8152_get_version(struct usb_interf - case 0x6010: - version = RTL_VER_09; - break; -+ case 0x7010: -+ version = RTL_TEST_01; -+ break; -+ case 0x7020: -+ version = RTL_VER_10; -+ break; -+ case 0x7030: -+ version = RTL_VER_11; -+ break; -+ case 0x7400: -+ version = RTL_VER_12; -+ break; -+ case 0x7410: -+ version = RTL_VER_13; -+ break; -+ case 0x6400: -+ version = RTL_VER_14; -+ break; -+ case 0x7420: -+ version = RTL_VER_15; -+ break; - default: - version = RTL_VER_UNKNOWN; - dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data); -@@ -6857,12 +8898,29 @@ static int rtl8152_probe(struct usb_inte - /* MTU range: 68 - 1500 or 9194 */ - netdev->min_mtu = ETH_MIN_MTU; - switch (tp->version) { -+ case RTL_VER_03: -+ case RTL_VER_04: -+ case RTL_VER_05: -+ case RTL_VER_06: -+ case RTL_VER_08: -+ case RTL_VER_09: -+ case RTL_VER_14: -+ netdev->max_mtu = size_to_mtu(9 * 1024); -+ break; -+ case RTL_VER_10: -+ case RTL_VER_11: -+ netdev->max_mtu = size_to_mtu(15 * 1024); -+ break; -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ netdev->max_mtu = size_to_mtu(16 * 1024); -+ break; - case RTL_VER_01: - case RTL_VER_02: -- netdev->max_mtu = ETH_DATA_LEN; -- break; -+ case RTL_VER_07: - default: -- netdev->max_mtu = size_to_mtu(9 * 1024); -+ netdev->max_mtu = ETH_DATA_LEN; - break; - } - -@@ -6878,7 +8936,13 @@ static int rtl8152_probe(struct usb_inte - tp->advertising = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | - RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; - if (tp->mii.supports_gmii) { -- tp->speed = SPEED_1000; -+ if (tp->support_2500full && -+ tp->udev->speed >= USB_SPEED_SUPER) { -+ tp->speed = SPEED_2500; -+ tp->advertising |= RTL_ADVERTISED_2500_FULL; -+ } else { -+ tp->speed = SPEED_1000; -+ } - tp->advertising |= RTL_ADVERTISED_1000_FULL; - } - tp->duplex = DUPLEX_FULL; -@@ -6902,7 +8966,11 @@ static int rtl8152_probe(struct usb_inte - set_ethernet_addr(tp); - - usb_set_intfdata(intf, tp); -- netif_napi_add(netdev, &tp->napi, r8152_poll, RTL8152_NAPI_WEIGHT); -+ -+ if (tp->support_2500full) -+ netif_napi_add(netdev, &tp->napi, r8152_poll, 256); -+ else -+ netif_napi_add(netdev, &tp->napi, r8152_poll, 64); - - ret = register_netdev(netdev); - if (ret != 0) { -@@ -6938,7 +9006,8 @@ static void rtl8152_disconnect(struct us - unregister_netdev(tp->netdev); - tasklet_kill(&tp->tx_tl); - cancel_delayed_work_sync(&tp->hw_phy_work); -- tp->rtl_ops.unload(tp); -+ if (tp->rtl_ops.unload) -+ tp->rtl_ops.unload(tp); - rtl8152_release_firmware(tp); - free_netdev(tp->netdev); - } -@@ -6958,13 +9027,28 @@ static void rtl8152_disconnect(struct us - .idProduct = (prod), \ - .bInterfaceClass = USB_CLASS_COMM, \ - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ -+ .bInterfaceProtocol = USB_CDC_PROTO_NONE \ -+}, \ -+{ \ -+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | \ -+ USB_DEVICE_ID_MATCH_DEVICE, \ -+ .idVendor = (vend), \ -+ .idProduct = (prod), \ -+ .bInterfaceClass = USB_CLASS_COMM, \ -+ .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, \ - .bInterfaceProtocol = USB_CDC_PROTO_NONE - - /* table of devices that work with this driver */ - static const struct usb_device_id rtl8152_table[] = { -+ /* Realtek */ - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050)}, -+ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8053)}, - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, -+ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8155)}, -+ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8156)}, -+ -+ /* Microsoft */ - {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)}, - {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)}, - {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927)}, diff --git a/target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch b/target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch deleted file mode 100644 index 943c821b82..0000000000 --- a/target/linux/generic/backport-5.15/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch +++ /dev/null @@ -1,691 +0,0 @@ -From ca09589a72a0aa17389754fb75a5cd1a5d46818f Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 16 Apr 2021 16:04:36 +0800 -Subject: [PATCH] r8152: support PHY firmware for RTL8156 series - -commit 4a51b0e8a0143b0e83d51d9c58c6416c3818a9f2 upstream. - -Support new firmware type and method for RTL8156 series. - -Signed-off-by: Hayes Wang -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 563 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 561 insertions(+), 2 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -975,8 +975,60 @@ enum rtl8152_fw_flags { - FW_FLAGS_START, - FW_FLAGS_STOP, - FW_FLAGS_NC, -+ FW_FLAGS_NC1, -+ FW_FLAGS_NC2, -+ FW_FLAGS_UC2, -+ FW_FLAGS_UC, -+ FW_FLAGS_SPEED_UP, -+ FW_FLAGS_VER, - }; - -+enum rtl8152_fw_fixup_cmd { -+ FW_FIXUP_AND = 0, -+ FW_FIXUP_OR, -+ FW_FIXUP_NOT, -+ FW_FIXUP_XOR, -+}; -+ -+struct fw_phy_set { -+ __le16 addr; -+ __le16 data; -+} __packed; -+ -+struct fw_phy_speed_up { -+ struct fw_block blk_hdr; -+ __le16 fw_offset; -+ __le16 version; -+ __le16 fw_reg; -+ __le16 reserved; -+ char info[]; -+} __packed; -+ -+struct fw_phy_ver { -+ struct fw_block blk_hdr; -+ struct fw_phy_set ver; -+ __le32 reserved; -+} __packed; -+ -+struct fw_phy_fixup { -+ struct fw_block blk_hdr; -+ struct fw_phy_set setting; -+ __le16 bit_cmd; -+ __le16 reserved; -+} __packed; -+ -+struct fw_phy_union { -+ struct fw_block blk_hdr; -+ __le16 fw_offset; -+ __le16 fw_reg; -+ struct fw_phy_set pre_set[2]; -+ struct fw_phy_set bp[8]; -+ struct fw_phy_set bp_en; -+ u8 pre_num; -+ u8 bp_num; -+ char info[]; -+} __packed; -+ - /** - * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. - * The layout of the firmware block is: -@@ -1081,6 +1133,15 @@ enum rtl_fw_type { - RTL_FW_PHY_START, - RTL_FW_PHY_STOP, - RTL_FW_PHY_NC, -+ RTL_FW_PHY_FIXUP, -+ RTL_FW_PHY_UNION_NC, -+ RTL_FW_PHY_UNION_NC1, -+ RTL_FW_PHY_UNION_NC2, -+ RTL_FW_PHY_UNION_UC2, -+ RTL_FW_PHY_UNION_UC, -+ RTL_FW_PHY_UNION_MISC, -+ RTL_FW_PHY_SPEED_UP, -+ RTL_FW_PHY_VER, - }; - - enum rtl_version { -@@ -4000,6 +4061,162 @@ static int rtl_post_ram_code(struct r815 - return 0; - } - -+static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_up *phy) -+{ -+ u16 fw_offset; -+ u32 length; -+ bool rc = false; -+ -+ switch (tp->version) { -+ case RTL_VER_01: -+ case RTL_VER_02: -+ case RTL_VER_03: -+ case RTL_VER_04: -+ case RTL_VER_05: -+ case RTL_VER_06: -+ case RTL_VER_07: -+ case RTL_VER_08: -+ case RTL_VER_09: -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_14: -+ goto out; -+ case RTL_VER_13: -+ case RTL_VER_15: -+ default: -+ break; -+ } -+ -+ fw_offset = __le16_to_cpu(phy->fw_offset); -+ length = __le32_to_cpu(phy->blk_hdr.length); -+ if (fw_offset < sizeof(*phy) || length <= fw_offset) { -+ dev_err(&tp->intf->dev, "invalid fw_offset\n"); -+ goto out; -+ } -+ -+ length -= fw_offset; -+ if (length & 3) { -+ dev_err(&tp->intf->dev, "invalid block length\n"); -+ goto out; -+ } -+ -+ if (__le16_to_cpu(phy->fw_reg) != 0x9A00) { -+ dev_err(&tp->intf->dev, "invalid register to load firmware\n"); -+ goto out; -+ } -+ -+ rc = true; -+out: -+ return rc; -+} -+ -+static bool rtl8152_is_fw_phy_ver_ok(struct r8152 *tp, struct fw_phy_ver *ver) -+{ -+ bool rc = false; -+ -+ switch (tp->version) { -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ break; -+ default: -+ goto out; -+ } -+ -+ if (__le32_to_cpu(ver->blk_hdr.length) != sizeof(*ver)) { -+ dev_err(&tp->intf->dev, "invalid block length\n"); -+ goto out; -+ } -+ -+ if (__le16_to_cpu(ver->ver.addr) != SRAM_GPHY_FW_VER) { -+ dev_err(&tp->intf->dev, "invalid phy ver addr\n"); -+ goto out; -+ } -+ -+ rc = true; -+out: -+ return rc; -+} -+ -+static bool rtl8152_is_fw_phy_fixup_ok(struct r8152 *tp, struct fw_phy_fixup *fix) -+{ -+ bool rc = false; -+ -+ switch (tp->version) { -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ break; -+ default: -+ goto out; -+ } -+ -+ if (__le32_to_cpu(fix->blk_hdr.length) != sizeof(*fix)) { -+ dev_err(&tp->intf->dev, "invalid block length\n"); -+ goto out; -+ } -+ -+ if (__le16_to_cpu(fix->setting.addr) != OCP_PHY_PATCH_CMD || -+ __le16_to_cpu(fix->setting.data) != BIT(7)) { -+ dev_err(&tp->intf->dev, "invalid phy fixup\n"); -+ goto out; -+ } -+ -+ rc = true; -+out: -+ return rc; -+} -+ -+static bool rtl8152_is_fw_phy_union_ok(struct r8152 *tp, struct fw_phy_union *phy) -+{ -+ u16 fw_offset; -+ u32 length; -+ bool rc = false; -+ -+ switch (tp->version) { -+ case RTL_VER_10: -+ case RTL_VER_11: -+ case RTL_VER_12: -+ case RTL_VER_13: -+ case RTL_VER_15: -+ break; -+ default: -+ goto out; -+ } -+ -+ fw_offset = __le16_to_cpu(phy->fw_offset); -+ length = __le32_to_cpu(phy->blk_hdr.length); -+ if (fw_offset < sizeof(*phy) || length <= fw_offset) { -+ dev_err(&tp->intf->dev, "invalid fw_offset\n"); -+ goto out; -+ } -+ -+ length -= fw_offset; -+ if (length & 1) { -+ dev_err(&tp->intf->dev, "invalid block length\n"); -+ goto out; -+ } -+ -+ if (phy->pre_num > 2) { -+ dev_err(&tp->intf->dev, "invalid pre_num %d\n", phy->pre_num); -+ goto out; -+ } -+ -+ if (phy->bp_num > 8) { -+ dev_err(&tp->intf->dev, "invalid bp_num %d\n", phy->bp_num); -+ goto out; -+ } -+ -+ rc = true; -+out: -+ return rc; -+} -+ - static bool rtl8152_is_fw_phy_nc_ok(struct r8152 *tp, struct fw_phy_nc *phy) - { - u32 length; -@@ -4320,6 +4537,10 @@ static long rtl8152_check_firmware(struc - case RTL_FW_PHY_START: - if (test_bit(FW_FLAGS_START, &fw_flags) || - test_bit(FW_FLAGS_NC, &fw_flags) || -+ test_bit(FW_FLAGS_NC1, &fw_flags) || -+ test_bit(FW_FLAGS_NC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC, &fw_flags) || - test_bit(FW_FLAGS_STOP, &fw_flags)) { - dev_err(&tp->intf->dev, - "check PHY_START fail\n"); -@@ -4368,7 +4589,153 @@ static long rtl8152_check_firmware(struc - goto fail; - } - __set_bit(FW_FLAGS_NC, &fw_flags); -+ break; -+ case RTL_FW_PHY_UNION_NC: -+ if (!test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_NC1, &fw_flags) || -+ test_bit(FW_FLAGS_NC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "PHY_UNION_NC out of order\n"); -+ goto fail; -+ } -+ -+ if (test_bit(FW_FLAGS_NC, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY_UNION_NC encountered\n"); -+ goto fail; -+ } - -+ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { -+ dev_err(&tp->intf->dev, "check PHY_UNION_NC failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_NC, &fw_flags); -+ break; -+ case RTL_FW_PHY_UNION_NC1: -+ if (!test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_NC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "PHY_UNION_NC1 out of order\n"); -+ goto fail; -+ } -+ -+ if (test_bit(FW_FLAGS_NC1, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY NC1 encountered\n"); -+ goto fail; -+ } -+ -+ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { -+ dev_err(&tp->intf->dev, "check PHY_UNION_NC1 failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_NC1, &fw_flags); -+ break; -+ case RTL_FW_PHY_UNION_NC2: -+ if (!test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_UC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "PHY_UNION_NC2 out of order\n"); -+ goto fail; -+ } -+ -+ if (test_bit(FW_FLAGS_NC2, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY NC2 encountered\n"); -+ goto fail; -+ } -+ -+ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { -+ dev_err(&tp->intf->dev, "check PHY_UNION_NC2 failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_NC2, &fw_flags); -+ break; -+ case RTL_FW_PHY_UNION_UC2: -+ if (!test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_UC, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "PHY_UNION_UC2 out of order\n"); -+ goto fail; -+ } -+ -+ if (test_bit(FW_FLAGS_UC2, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY UC2 encountered\n"); -+ goto fail; -+ } -+ -+ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { -+ dev_err(&tp->intf->dev, "check PHY_UNION_UC2 failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_UC2, &fw_flags); -+ break; -+ case RTL_FW_PHY_UNION_UC: -+ if (!test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "PHY_UNION_UC out of order\n"); -+ goto fail; -+ } -+ -+ if (test_bit(FW_FLAGS_UC, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY UC encountered\n"); -+ goto fail; -+ } -+ -+ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { -+ dev_err(&tp->intf->dev, "check PHY_UNION_UC failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_UC, &fw_flags); -+ break; -+ case RTL_FW_PHY_UNION_MISC: -+ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { -+ dev_err(&tp->intf->dev, "check RTL_FW_PHY_UNION_MISC failed\n"); -+ goto fail; -+ } -+ break; -+ case RTL_FW_PHY_FIXUP: -+ if (!rtl8152_is_fw_phy_fixup_ok(tp, (struct fw_phy_fixup *)block)) { -+ dev_err(&tp->intf->dev, "check PHY fixup failed\n"); -+ goto fail; -+ } -+ break; -+ case RTL_FW_PHY_SPEED_UP: -+ if (test_bit(FW_FLAGS_SPEED_UP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY firmware encountered"); -+ goto fail; -+ } -+ -+ if (!rtl8152_is_fw_phy_speed_up_ok(tp, (struct fw_phy_speed_up *)block)) { -+ dev_err(&tp->intf->dev, "check PHY speed up failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_SPEED_UP, &fw_flags); -+ break; -+ case RTL_FW_PHY_VER: -+ if (test_bit(FW_FLAGS_START, &fw_flags) || -+ test_bit(FW_FLAGS_NC, &fw_flags) || -+ test_bit(FW_FLAGS_NC1, &fw_flags) || -+ test_bit(FW_FLAGS_NC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC2, &fw_flags) || -+ test_bit(FW_FLAGS_UC, &fw_flags) || -+ test_bit(FW_FLAGS_STOP, &fw_flags)) { -+ dev_err(&tp->intf->dev, "Invalid order to set PHY version\n"); -+ goto fail; -+ } -+ -+ if (test_bit(FW_FLAGS_VER, &fw_flags)) { -+ dev_err(&tp->intf->dev, "multiple PHY version encountered"); -+ goto fail; -+ } -+ -+ if (!rtl8152_is_fw_phy_ver_ok(tp, (struct fw_phy_ver *)block)) { -+ dev_err(&tp->intf->dev, "check PHY version failed\n"); -+ goto fail; -+ } -+ __set_bit(FW_FLAGS_VER, &fw_flags); - break; - default: - dev_warn(&tp->intf->dev, "Unknown type %u is found\n", -@@ -4391,6 +4758,143 @@ fail: - return ret; - } - -+static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, bool wait) -+{ -+ u32 len; -+ u8 *data; -+ -+ if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) { -+ dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); -+ return; -+ } -+ -+ len = __le32_to_cpu(phy->blk_hdr.length); -+ len -= __le16_to_cpu(phy->fw_offset); -+ data = (u8 *)phy + __le16_to_cpu(phy->fw_offset); -+ -+ if (rtl_phy_patch_request(tp, true, wait)) -+ return; -+ -+ while (len) { -+ u32 ocp_data, size; -+ int i; -+ -+ if (len < 2048) -+ size = len; -+ else -+ size = 2048; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL); -+ ocp_data |= GPHY_PATCH_DONE | BACKUP_RESTRORE; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL, ocp_data); -+ -+ generic_ocp_write(tp, __le16_to_cpu(phy->fw_reg), 0xff, size, data, MCU_TYPE_USB); -+ -+ data += size; -+ len -= size; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL); -+ ocp_data |= POL_GPHY_PATCH; -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL, ocp_data); -+ -+ for (i = 0; i < 1000; i++) { -+ if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & POL_GPHY_PATCH)) -+ break; -+ } -+ -+ if (i == 1000) { -+ dev_err(&tp->intf->dev, "ram code speedup mode timeout\n"); -+ return; -+ } -+ } -+ -+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); -+ rtl_phy_patch_request(tp, false, wait); -+ -+ if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version)) -+ dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); -+ else -+ dev_err(&tp->intf->dev, "ram code speedup mode fail\n"); -+} -+ -+static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver) -+{ -+ u16 ver_addr, ver; -+ -+ ver_addr = __le16_to_cpu(phy_ver->ver.addr); -+ ver = __le16_to_cpu(phy_ver->ver.data); -+ -+ if (sram_read(tp, ver_addr) >= ver) { -+ dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); -+ return 0; -+ } -+ -+ sram_write(tp, ver_addr, ver); -+ -+ dev_dbg(&tp->intf->dev, "PHY firmware version %x\n", ver); -+ -+ return ver; -+} -+ -+static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix) -+{ -+ u16 addr, data; -+ -+ addr = __le16_to_cpu(fix->setting.addr); -+ data = ocp_reg_read(tp, addr); -+ -+ switch (__le16_to_cpu(fix->bit_cmd)) { -+ case FW_FIXUP_AND: -+ data &= __le16_to_cpu(fix->setting.data); -+ break; -+ case FW_FIXUP_OR: -+ data |= __le16_to_cpu(fix->setting.data); -+ break; -+ case FW_FIXUP_NOT: -+ data &= ~__le16_to_cpu(fix->setting.data); -+ break; -+ case FW_FIXUP_XOR: -+ data ^= __le16_to_cpu(fix->setting.data); -+ break; -+ default: -+ return; -+ } -+ -+ ocp_reg_write(tp, addr, data); -+ -+ dev_dbg(&tp->intf->dev, "applied ocp %x %x\n", addr, data); -+} -+ -+static void rtl8152_fw_phy_union_apply(struct r8152 *tp, struct fw_phy_union *phy) -+{ -+ __le16 *data; -+ u32 length; -+ int i, num; -+ -+ num = phy->pre_num; -+ for (i = 0; i < num; i++) -+ sram_write(tp, __le16_to_cpu(phy->pre_set[i].addr), -+ __le16_to_cpu(phy->pre_set[i].data)); -+ -+ length = __le32_to_cpu(phy->blk_hdr.length); -+ length -= __le16_to_cpu(phy->fw_offset); -+ num = length / 2; -+ data = (__le16 *)((u8 *)phy + __le16_to_cpu(phy->fw_offset)); -+ -+ ocp_reg_write(tp, OCP_SRAM_ADDR, __le16_to_cpu(phy->fw_reg)); -+ for (i = 0; i < num; i++) -+ ocp_reg_write(tp, OCP_SRAM_DATA, __le16_to_cpu(data[i])); -+ -+ num = phy->bp_num; -+ for (i = 0; i < num; i++) -+ sram_write(tp, __le16_to_cpu(phy->bp[i].addr), __le16_to_cpu(phy->bp[i].data)); -+ -+ if (phy->bp_num && phy->bp_en.addr) -+ sram_write(tp, __le16_to_cpu(phy->bp_en.addr), __le16_to_cpu(phy->bp_en.data)); -+ -+ dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); -+} -+ - static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy) - { - u16 mode_reg, bp_index; -@@ -4444,6 +4948,12 @@ static void rtl8152_fw_mac_apply(struct - return; - } - -+ fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg); -+ if (fw_ver_reg && ocp_read_byte(tp, MCU_TYPE_USB, fw_ver_reg) >= mac->fw_ver_data) { -+ dev_dbg(&tp->intf->dev, "%s firmware has been the newest\n", type ? "PLA" : "USB"); -+ return; -+ } -+ - rtl_clear_bp(tp, type); - - /* Enable backup/restore of MACDBG. This is required after clearing PLA -@@ -4479,7 +4989,6 @@ static void rtl8152_fw_mac_apply(struct - ocp_write_word(tp, type, bp_en_addr, - __le16_to_cpu(mac->bp_en_value)); - -- fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg); - if (fw_ver_reg) - ocp_write_byte(tp, MCU_TYPE_USB, fw_ver_reg, - mac->fw_ver_data); -@@ -4494,7 +5003,7 @@ static void rtl8152_apply_firmware(struc - struct fw_header *fw_hdr; - struct fw_phy_patch_key *key; - u16 key_addr = 0; -- int i; -+ int i, patch_phy = 1; - - if (IS_ERR_OR_NULL(rtl_fw->fw)) - return; -@@ -4516,17 +5025,40 @@ static void rtl8152_apply_firmware(struc - rtl8152_fw_mac_apply(tp, (struct fw_mac *)block); - break; - case RTL_FW_PHY_START: -+ if (!patch_phy) -+ break; - key = (struct fw_phy_patch_key *)block; - key_addr = __le16_to_cpu(key->key_reg); - rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); - break; - case RTL_FW_PHY_STOP: -+ if (!patch_phy) -+ break; - WARN_ON(!key_addr); - rtl_post_ram_code(tp, key_addr, !power_cut); - break; - case RTL_FW_PHY_NC: - rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); - break; -+ case RTL_FW_PHY_VER: -+ patch_phy = rtl8152_fw_phy_ver(tp, (struct fw_phy_ver *)block); -+ break; -+ case RTL_FW_PHY_UNION_NC: -+ case RTL_FW_PHY_UNION_NC1: -+ case RTL_FW_PHY_UNION_NC2: -+ case RTL_FW_PHY_UNION_UC2: -+ case RTL_FW_PHY_UNION_UC: -+ case RTL_FW_PHY_UNION_MISC: -+ if (patch_phy) -+ rtl8152_fw_phy_union_apply(tp, (struct fw_phy_union *)block); -+ break; -+ case RTL_FW_PHY_FIXUP: -+ if (patch_phy) -+ rtl8152_fw_phy_fixup(tp, (struct fw_phy_fixup *)block); -+ break; -+ case RTL_FW_PHY_SPEED_UP: -+ rtl_ram_code_speed_up(tp, (struct fw_phy_speed_up *)block, !power_cut); -+ break; - default: - break; - } -@@ -5034,6 +5566,21 @@ static int r8153c_post_firmware_1(struct - return 0; - } - -+static int r8156a_post_firmware_1(struct r8152 *tp) -+{ -+ u32 ocp_data; -+ -+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1); -+ ocp_data |= FW_IP_RESET_EN; -+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1, ocp_data); -+ -+ /* Modify U3PHY parameter for compatibility issue */ -+ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPHY3_MDCMDIO, 0x4026840e); -+ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPHY3_MDCMDIO, 0x4001acc9); -+ -+ return 0; -+} -+ - static void r8153_aldps_en(struct r8152 *tp, bool enable) - { - u16 data; -@@ -8674,12 +9221,16 @@ static int rtl_ops_init(struct r8152 *tp - #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" - #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" - #define FIRMWARE_8153C_1 "rtl_nic/rtl8153c-1.fw" -+#define FIRMWARE_8156A_2 "rtl_nic/rtl8156a-2.fw" -+#define FIRMWARE_8156B_2 "rtl_nic/rtl8156b-2.fw" - - MODULE_FIRMWARE(FIRMWARE_8153A_2); - MODULE_FIRMWARE(FIRMWARE_8153A_3); - MODULE_FIRMWARE(FIRMWARE_8153A_4); - MODULE_FIRMWARE(FIRMWARE_8153B_2); - MODULE_FIRMWARE(FIRMWARE_8153C_1); -+MODULE_FIRMWARE(FIRMWARE_8156A_2); -+MODULE_FIRMWARE(FIRMWARE_8156B_2); - - static int rtl_fw_init(struct r8152 *tp) - { -@@ -8705,6 +9256,14 @@ static int rtl_fw_init(struct r8152 *tp) - rtl_fw->pre_fw = r8153b_pre_firmware_1; - rtl_fw->post_fw = r8153b_post_firmware_1; - break; -+ case RTL_VER_11: -+ rtl_fw->fw_name = FIRMWARE_8156A_2; -+ rtl_fw->post_fw = r8156a_post_firmware_1; -+ break; -+ case RTL_VER_13: -+ case RTL_VER_15: -+ rtl_fw->fw_name = FIRMWARE_8156B_2; -+ break; - case RTL_VER_14: - rtl_fw->fw_name = FIRMWARE_8153C_1; - rtl_fw->pre_fw = r8153b_pre_firmware_1; diff --git a/target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch b/target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch deleted file mode 100644 index 9ce0e778cf..0000000000 --- a/target/linux/generic/backport-5.15/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 579f58dd2819910354753bc5489fc1588fe9cfe2 Mon Sep 17 00:00:00 2001 -From: Hayes Wang -Date: Fri, 16 Apr 2021 16:04:37 +0800 -Subject: [PATCH] r8152: search the configuration of vendor mode - -commit c2198943e33b100ed21dfb636c8fa6baef841e9d upstream. - -The vendor mode is not always at config #1, so it is necessary to -set the correct configuration number. - -Signed-off-by: Hayes Wang -Signed-off-by: David S. Miller ---- - drivers/net/usb/r8152.c | 39 +++++++++++++++++++++++++++++++++++---- - 1 file changed, 35 insertions(+), 4 deletions(-) - ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -30,7 +30,7 @@ - #include - - /* Information for net-next */ --#define NETNEXT_VERSION "11" -+#define NETNEXT_VERSION "12" - - /* Information for net */ - #define NET_VERSION "11" -@@ -8131,6 +8131,39 @@ static void r8156b_init(struct r8152 *tp - tp->coalesce = 15000; /* 15 us */ - } - -+static bool rtl_vendor_mode(struct usb_interface *intf) -+{ -+ struct usb_host_interface *alt = intf->cur_altsetting; -+ struct usb_device *udev; -+ struct usb_host_config *c; -+ int i, num_configs; -+ -+ if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) -+ return true; -+ -+ /* The vendor mode is not always config #1, so to find it out. */ -+ udev = interface_to_usbdev(intf); -+ c = udev->config; -+ num_configs = udev->descriptor.bNumConfigurations; -+ for (i = 0; i < num_configs; (i++, c++)) { -+ struct usb_interface_descriptor *desc = NULL; -+ -+ if (c->desc.bNumInterfaces > 0) -+ desc = &c->intf_cache[0]->altsetting->desc; -+ else -+ continue; -+ -+ if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) { -+ usb_driver_set_configuration(udev, c->desc.bConfigurationValue); -+ break; -+ } -+ } -+ -+ WARN_ON_ONCE(i == num_configs); -+ -+ return false; -+} -+ - static int rtl8152_pre_reset(struct usb_interface *intf) - { - struct r8152 *tp = usb_get_intfdata(intf); -@@ -9369,10 +9402,8 @@ static int rtl8152_probe(struct usb_inte - if (version == RTL_VER_UNKNOWN) - return -ENODEV; - -- if (udev->actconfig->desc.bConfigurationValue != 1) { -- usb_driver_set_configuration(udev, 1); -+ if (!rtl_vendor_mode(intf)) - return -ENODEV; -- } - - if (intf->cur_altsetting->desc.bNumEndpoints < 3) - return -ENODEV; diff --git a/target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch b/target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch deleted file mode 100644 index 19938704b7..0000000000 --- a/target/linux/generic/backport-5.15/800-v5.13-0001-firmware-bcm47xx_nvram-rename-finding-function-and-i.patch +++ /dev/null @@ -1,80 +0,0 @@ -From fb009cbdd0693bd633f11e99526617b3d392cfad Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Mon, 8 Mar 2021 10:03:16 +0100 -Subject: [PATCH] firmware: bcm47xx_nvram: rename finding function and its - variables -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -1. Use "bcm47xx_" function name prefix for consistency -2. It takes flash start as argument so s/iobase/flash_start/ -3. "off" was used for finding flash end so just call it "flash_size" - -Signed-off-by: Rafał Miłecki -Signed-off-by: Thomas Bogendoerfer ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 24 ++++++++++++----------- - 1 file changed, 13 insertions(+), 11 deletions(-) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -48,11 +48,13 @@ static u32 find_nvram_size(void __iomem - return 0; - } - --/* Probe for NVRAM header */ --static int nvram_find_and_copy(void __iomem *iobase, u32 lim) -+/** -+ * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it -+ */ -+static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size) - { - struct nvram_header __iomem *header; -- u32 off; -+ size_t flash_size; - u32 size; - - if (nvram_len) { -@@ -61,25 +63,25 @@ static int nvram_find_and_copy(void __io - } - - /* TODO: when nvram is on nand flash check for bad blocks first. */ -- off = FLASH_MIN; -- while (off <= lim) { -+ flash_size = FLASH_MIN; -+ while (flash_size <= res_size) { - /* Windowed flash access */ -- size = find_nvram_size(iobase + off); -+ size = find_nvram_size(flash_start + flash_size); - if (size) { -- header = (struct nvram_header *)(iobase + off - size); -+ header = (struct nvram_header *)(flash_start + flash_size - size); - goto found; - } -- off <<= 1; -+ flash_size <<= 1; - } - - /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ -- header = (struct nvram_header *)(iobase + 4096); -+ header = (struct nvram_header *)(flash_start + 4096); - if (header->magic == NVRAM_MAGIC) { - size = NVRAM_SPACE; - goto found; - } - -- header = (struct nvram_header *)(iobase + 1024); -+ header = (struct nvram_header *)(flash_start + 1024); - if (header->magic == NVRAM_MAGIC) { - size = NVRAM_SPACE; - goto found; -@@ -124,7 +126,7 @@ int bcm47xx_nvram_init_from_mem(u32 base - if (!iobase) - return -ENOMEM; - -- err = nvram_find_and_copy(iobase, lim); -+ err = bcm47xx_nvram_find_and_copy(iobase, lim); - - iounmap(iobase); - diff --git a/target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch b/target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch deleted file mode 100644 index 6ab072883d..0000000000 --- a/target/linux/generic/backport-5.15/800-v5.13-0002-firmware-bcm47xx_nvram-add-helper-checking-for-NVRAM.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0a24b51a3264a3f942a75025ea5ff6133c8989b0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Mon, 8 Mar 2021 10:03:17 +0100 -Subject: [PATCH] firmware: bcm47xx_nvram: add helper checking for NVRAM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This avoids duplicating code doing casting and checking for NVRAM magic. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Thomas Bogendoerfer ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 30 ++++++++++++++--------- - 1 file changed, 18 insertions(+), 12 deletions(-) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -34,14 +34,20 @@ static char nvram_buf[NVRAM_SPACE]; - static size_t nvram_len; - static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; - -+/** -+ * bcm47xx_nvram_is_valid - check for a valid NVRAM at specified memory -+ */ -+static bool bcm47xx_nvram_is_valid(void __iomem *nvram) -+{ -+ return ((struct nvram_header *)nvram)->magic == NVRAM_MAGIC; -+} -+ - static u32 find_nvram_size(void __iomem *end) - { -- struct nvram_header __iomem *header; - int i; - - for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { -- header = (struct nvram_header *)(end - nvram_sizes[i]); -- if (header->magic == NVRAM_MAGIC) -+ if (bcm47xx_nvram_is_valid(end - nvram_sizes[i])) - return nvram_sizes[i]; - } - -@@ -55,6 +61,7 @@ static int bcm47xx_nvram_find_and_copy(v - { - struct nvram_header __iomem *header; - size_t flash_size; -+ size_t offset; - u32 size; - - if (nvram_len) { -@@ -68,31 +75,30 @@ static int bcm47xx_nvram_find_and_copy(v - /* Windowed flash access */ - size = find_nvram_size(flash_start + flash_size); - if (size) { -- header = (struct nvram_header *)(flash_start + flash_size - size); -+ offset = flash_size - size; - goto found; - } - flash_size <<= 1; - } - - /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ -- header = (struct nvram_header *)(flash_start + 4096); -- if (header->magic == NVRAM_MAGIC) { -- size = NVRAM_SPACE; -+ -+ offset = 4096; -+ if (bcm47xx_nvram_is_valid(flash_start + offset)) - goto found; -- } - -- header = (struct nvram_header *)(flash_start + 1024); -- if (header->magic == NVRAM_MAGIC) { -- size = NVRAM_SPACE; -+ offset = 1024; -+ if (bcm47xx_nvram_is_valid(flash_start + offset)) - goto found; -- } - - pr_err("no nvram found\n"); - return -ENXIO; - - found: -+ header = (struct nvram_header *)(flash_start + offset); - __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); - nvram_len = ((struct nvram_header *)(nvram_buf))->len; -+ size = res_size - offset; - if (nvram_len > size) { - pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); - nvram_len = size; diff --git a/target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch b/target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch deleted file mode 100644 index a1351f1197..0000000000 --- a/target/linux/generic/backport-5.15/800-v5.13-0003-firmware-bcm47xx_nvram-extract-code-copying-NVRAM.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 298923cf999cecd2ef06df126f85a3d68da8c4d8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Mon, 8 Mar 2021 10:03:18 +0100 -Subject: [PATCH] firmware: bcm47xx_nvram: extract code copying NVRAM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This simplifies function finding NVRAM. It doesn't directly deal with -NVRAM structure anymore and is a bit smaller. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Thomas Bogendoerfer ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 43 +++++++++++++---------- - 1 file changed, 25 insertions(+), 18 deletions(-) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -55,11 +55,34 @@ static u32 find_nvram_size(void __iomem - } - - /** -+ * bcm47xx_nvram_copy - copy NVRAM to internal buffer -+ */ -+static void bcm47xx_nvram_copy(void __iomem *nvram_start, size_t res_size) -+{ -+ struct nvram_header __iomem *header = nvram_start; -+ size_t copy_size; -+ -+ copy_size = header->len; -+ if (copy_size > res_size) { -+ pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); -+ copy_size = res_size; -+ } -+ if (copy_size >= NVRAM_SPACE) { -+ pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", -+ copy_size, NVRAM_SPACE - 1); -+ copy_size = NVRAM_SPACE - 1; -+ } -+ -+ __ioread32_copy(nvram_buf, nvram_start, DIV_ROUND_UP(copy_size, 4)); -+ nvram_buf[NVRAM_SPACE - 1] = '\0'; -+ nvram_len = copy_size; -+} -+ -+/** - * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it - */ - static int bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size) - { -- struct nvram_header __iomem *header; - size_t flash_size; - size_t offset; - u32 size; -@@ -95,23 +118,7 @@ static int bcm47xx_nvram_find_and_copy(v - return -ENXIO; - - found: -- header = (struct nvram_header *)(flash_start + offset); -- __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); -- nvram_len = ((struct nvram_header *)(nvram_buf))->len; -- size = res_size - offset; -- if (nvram_len > size) { -- pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); -- nvram_len = size; -- } -- if (nvram_len >= NVRAM_SPACE) { -- pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", -- nvram_len, NVRAM_SPACE - 1); -- nvram_len = NVRAM_SPACE - 1; -- } -- /* proceed reading data after header */ -- __ioread32_copy(nvram_buf + sizeof(*header), header + 1, -- DIV_ROUND_UP(nvram_len, 4)); -- nvram_buf[NVRAM_SPACE - 1] = '\0'; -+ bcm47xx_nvram_copy(flash_start + offset, res_size - offset); - - return 0; - } diff --git a/target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch b/target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch deleted file mode 100644 index 059a13220b..0000000000 --- a/target/linux/generic/backport-5.15/800-v5.13-0004-firmware-bcm47xx_nvram-look-for-NVRAM-with-for-inste.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 98b68324f67236e8c9152976535dc1f27fb67ba8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Mon, 8 Mar 2021 10:03:19 +0100 -Subject: [PATCH] firmware: bcm47xx_nvram: look for NVRAM with for instead of - while -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This loop requires variable initialization, stop condition and post -iteration increment. It's pretty much a for loop definition. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Thomas Bogendoerfer ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -93,15 +93,13 @@ static int bcm47xx_nvram_find_and_copy(v - } - - /* TODO: when nvram is on nand flash check for bad blocks first. */ -- flash_size = FLASH_MIN; -- while (flash_size <= res_size) { -+ for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { - /* Windowed flash access */ - size = find_nvram_size(flash_start + flash_size); - if (size) { - offset = flash_size - size; - goto found; - } -- flash_size <<= 1; - } - - /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ diff --git a/target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch b/target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch deleted file mode 100644 index 21d250049e..0000000000 --- a/target/linux/generic/backport-5.15/800-v5.13-0005-firmware-bcm47xx_nvram-inline-code-checking-NVRAM-si.patch +++ /dev/null @@ -1,70 +0,0 @@ -From f52da4ccfec9192e17f5c16260dfdd6d3ea76f65 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Mon, 8 Mar 2021 10:03:20 +0100 -Subject: [PATCH] firmware: bcm47xx_nvram: inline code checking NVRAM size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Separated function was not improving code quality much (or at all). -Moreover it expected possible flash end address as argument and it was -returning NVRAM size. - -The new code always operates on offsets which means less logic and less -calculations. - -Signed-off-by: Rafał Miłecki -Signed-off-by: Thomas Bogendoerfer ---- - drivers/firmware/broadcom/bcm47xx_nvram.c | 25 +++++++---------------- - 1 file changed, 7 insertions(+), 18 deletions(-) - ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -42,18 +42,6 @@ static bool bcm47xx_nvram_is_valid(void - return ((struct nvram_header *)nvram)->magic == NVRAM_MAGIC; - } - --static u32 find_nvram_size(void __iomem *end) --{ -- int i; -- -- for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { -- if (bcm47xx_nvram_is_valid(end - nvram_sizes[i])) -- return nvram_sizes[i]; -- } -- -- return 0; --} -- - /** - * bcm47xx_nvram_copy - copy NVRAM to internal buffer - */ -@@ -85,7 +73,7 @@ static int bcm47xx_nvram_find_and_copy(v - { - size_t flash_size; - size_t offset; -- u32 size; -+ int i; - - if (nvram_len) { - pr_warn("nvram already initialized\n"); -@@ -93,12 +81,13 @@ static int bcm47xx_nvram_find_and_copy(v - } - - /* TODO: when nvram is on nand flash check for bad blocks first. */ -+ -+ /* Try every possible flash size and check for NVRAM at its end */ - for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { -- /* Windowed flash access */ -- size = find_nvram_size(flash_start + flash_size); -- if (size) { -- offset = flash_size - size; -- goto found; -+ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { -+ offset = flash_size - nvram_sizes[i]; -+ if (bcm47xx_nvram_is_valid(flash_start + offset)) -+ goto found; - } - } - diff --git a/target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch b/target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch deleted file mode 100644 index 6b75b08717..0000000000 --- a/target/linux/generic/backport-5.15/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001 -From: Florian Fainelli -Date: Tue, 23 Feb 2021 18:44:53 +0100 -Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent - checking -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch adds an ignore_oc flag which can be set by EHCI controller -not supporting or wanting to disable overcurrent checking. The EHCI -platform data in include/linux/usb/ehci_pdriver.h is also augmented to -take advantage of this new flag. - -Signed-off-by: Florian Fainelli -Signed-off-by: Álvaro Fernández Rojas -Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/usb/host/ehci-hcd.c | 2 +- - drivers/usb/host/ehci-hub.c | 4 ++-- - drivers/usb/host/ehci-platform.c | 2 ++ - drivers/usb/host/ehci.h | 1 + - include/linux/usb/ehci_pdriver.h | 1 + - 5 files changed, 7 insertions(+), 3 deletions(-) - ---- a/drivers/usb/host/ehci-hcd.c -+++ b/drivers/usb/host/ehci-hcd.c -@@ -660,7 +660,7 @@ static int ehci_run (struct usb_hcd *hcd - "USB %x.%x started, EHCI %x.%02x%s\n", - ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, -- ignore_oc ? ", overcurrent ignored" : ""); -+ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : ""); - - ehci_writel(ehci, INTR_MASK, - &ehci->regs->intr_enable); /* Turn On Interrupts */ ---- a/drivers/usb/host/ehci-hub.c -+++ b/drivers/usb/host/ehci-hub.c -@@ -643,7 +643,7 @@ ehci_hub_status_data (struct usb_hcd *hc - * always set, seem to clear PORT_OCC and PORT_CSC when writing to - * PORT_POWER; that's surprising, but maybe within-spec. - */ -- if (!ignore_oc) -+ if (!ignore_oc && !ehci->spurious_oc) - mask = PORT_CSC | PORT_PEC | PORT_OCC; - else - mask = PORT_CSC | PORT_PEC; -@@ -1013,7 +1013,7 @@ int ehci_hub_control( - if (temp & PORT_PEC) - status |= USB_PORT_STAT_C_ENABLE << 16; - -- if ((temp & PORT_OCC) && !ignore_oc){ -+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){ - status |= USB_PORT_STAT_C_OVERCURRENT << 16; - - /* ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -333,6 +333,8 @@ static int ehci_platform_probe(struct pl - hcd->has_tt = 1; - if (pdata->reset_on_resume) - priv->reset_on_resume = true; -+ if (pdata->spurious_oc) -+ ehci->spurious_oc = 1; - - #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - if (ehci->big_endian_mmio) { ---- a/drivers/usb/host/ehci.h -+++ b/drivers/usb/host/ehci.h -@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controlle - unsigned need_oc_pp_cycle:1; /* MPC834X port power */ - unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ - unsigned is_aspeed:1; -+ unsigned spurious_oc:1; - - /* required for usb32 quirk */ - #define OHCI_CTRL_HCFS (3 << 6) ---- a/include/linux/usb/ehci_pdriver.h -+++ b/include/linux/usb/ehci_pdriver.h -@@ -50,6 +50,7 @@ struct usb_ehci_pdata { - unsigned no_io_watchdog:1; - unsigned reset_on_resume:1; - unsigned dma_mask_64:1; -+ unsigned spurious_oc:1; - - /* Turn on all power and clocks */ - int (*power_on)(struct platform_device *pdev); diff --git a/target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch b/target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch deleted file mode 100644 index 0094d47718..0000000000 --- a/target/linux/generic/backport-5.15/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Tue, 23 Feb 2021 18:44:55 +0100 -Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Over-current reporting isn't supported on some platforms such as bcm63xx. -These devices will incorrectly report over-current if this flag isn't properly -activated. - -Signed-off-by: Álvaro Fernández Rojas -Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com -Signed-off-by: Greg Kroah-Hartman ---- - drivers/usb/host/ehci-platform.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl - if (of_property_read_bool(dev->dev.of_node, "big-endian")) - ehci->big_endian_mmio = ehci->big_endian_desc = 1; - -+ if (of_property_read_bool(dev->dev.of_node, "spurious-oc")) -+ ehci->spurious_oc = 1; -+ - if (of_property_read_bool(dev->dev.of_node, - "needs-reset-on-resume")) - priv->reset_on_resume = true; diff --git a/target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch b/target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch deleted file mode 100644 index 8ca2b78f74..0000000000 --- a/target/linux/generic/backport-5.15/820-v5.13-make-pci_host_common_probe-declare-its-reliance-on-msi-domains.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 9ec37efb87832b578d7972fc80b04d94f5d2bbe3 Mon Sep 17 00:00:00 2001 -From: Marc Zyngier -Date: Tue, 30 Mar 2021 16:11:42 +0100 -Subject: PCI/MSI: Make pci_host_common_probe() declare its reliance on MSI - domains - -The generic PCI host driver relies on MSI domains for MSIs to -be provided to its end-points. Make this dependency explicit. - -This cures the warnings occuring on arm/arm64 VMs when booted -with PCI virtio devices and no MSI controller (no GICv3 ITS, -for example). - -It is likely that other drivers will need to express the same -dependency. - -Link: https://lore.kernel.org/r/20210330151145.997953-12-maz@kernel.org -Signed-off-by: Marc Zyngier -Signed-off-by: Lorenzo Pieralisi -Acked-by: Bjorn Helgaas ---- - drivers/pci/controller/pci-host-common.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/pci/controller/pci-host-common.c -+++ b/drivers/pci/controller/pci-host-common.c -@@ -77,6 +77,7 @@ int pci_host_common_probe(struct platfor - - bridge->sysdata = cfg; - bridge->ops = (struct pci_ops *)&ops->pci_ops; -+ bridge->msi_domain = true; - - platform_set_drvdata(pdev, bridge); - diff --git a/target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch b/target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch deleted file mode 100644 index 854dc34c42..0000000000 --- a/target/linux/generic/backport-5.15/821-v5.13-let-pci-host-bridges-declar-their-reliance-on-msi-domains.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 94e89b145371b68fa0ea294855adebcd03e0522e Mon Sep 17 00:00:00 2001 -From: Marc Zyngier -Date: Tue, 30 Mar 2021 16:11:41 +0100 -Subject: PCI/MSI: Let PCI host bridges declare their reliance on MSI domains - -There is a whole class of host bridges that cannot know whether -MSIs will be provided or not, as they rely on other blocks -to provide the MSI functionnality, using MSI domains. This is -the case for example on systems that use the ARM GIC architecture. - -Introduce a new attribute ('msi_domain') indicating that implicit -dependency, and use this property to set the NO_MSI flag when -no MSI domain is found at probe time. - -Link: https://lore.kernel.org/r/20210330151145.997953-11-maz@kernel.org -Signed-off-by: Marc Zyngier -Signed-off-by: Lorenzo Pieralisi -Acked-by: Bjorn Helgaas ---- - drivers/pci/probe.c | 2 ++ - include/linux/pci.h | 1 + - 2 files changed, 3 insertions(+) - ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -925,6 +925,8 @@ static int pci_register_host_bridge(stru - device_enable_async_suspend(bus->bridge); - pci_set_bus_of_node(bus); - pci_set_bus_msi_domain(bus); -+ if (bridge->msi_domain && !dev_get_msi_domain(&bus->dev)) -+ bus->bus_flags |= PCI_BUS_FLAGS_NO_MSI; - - if (!parent) - set_dev_node(bus->bridge, pcibus_to_node(bus)); ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -547,6 +547,7 @@ struct pci_host_bridge { - unsigned int native_dpc:1; /* OS may use PCIe DPC */ - unsigned int preserve_config:1; /* Preserve FW resource setup */ - unsigned int size_windows:1; /* Enable root bus sizing */ -+ unsigned int msi_domain:1; /* Bridge wants MSI domain */ - - /* Resource alignment requirements */ - resource_size_t (*align_resource)(struct pci_dev *dev, diff --git a/target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch b/target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch deleted file mode 100644 index c11aedd814..0000000000 --- a/target/linux/generic/backport-5.15/822-v5.13-advertise-lack-of-built-in-msi-handling.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 645e9c38383d7fcde2784ee537fa18ec9bed54d9 Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner -Date: Tue, 30 Mar 2021 16:11:43 +0100 -Subject: PCI: mediatek: Advertise lack of built-in MSI handling - -Some Mediatek host bridges cannot handle MSIs, which is sad. -This also results in an ugly warning at device probe time, -as the core PCI code wasn't told that MSIs were not available. - -Advertise this fact to the rest of the core PCI code by -using the 'msi_domain' attribute, which still opens the possibility -for another block to provide the MSI functionnality. - -[maz: commit message, switched over to msi_domain attribute] - -Link: https://lore.kernel.org/r/20210330151145.997953-13-maz@kernel.org -Reported-by: Frank Wunderlich -Signed-off-by: Thomas Gleixner -Signed-off-by: Marc Zyngier -Signed-off-by: Lorenzo Pieralisi -Acked-by: Bjorn Helgaas ---- - drivers/pci/controller/pcie-mediatek.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -143,6 +143,7 @@ struct mtk_pcie_port; - * struct mtk_pcie_soc - differentiate between host generations - * @need_fix_class_id: whether this host's class ID needed to be fixed or not - * @need_fix_device_id: whether this host's device ID needed to be fixed or not -+ * @no_msi: Bridge has no MSI support, and relies on an external block - * @device_id: device ID which this host need to be fixed - * @ops: pointer to configuration access functions - * @startup: pointer to controller setting functions -@@ -151,6 +152,7 @@ struct mtk_pcie_port; - struct mtk_pcie_soc { - bool need_fix_class_id; - bool need_fix_device_id; -+ bool no_msi; - unsigned int device_id; - struct pci_ops *ops; - int (*startup)(struct mtk_pcie_port *port); -@@ -1087,6 +1089,7 @@ static int mtk_pcie_probe(struct platfor - - host->ops = pcie->soc->ops; - host->sysdata = pcie; -+ host->msi_domain = pcie->soc->no_msi; - - err = pci_host_probe(host); - if (err) -@@ -1176,6 +1179,7 @@ static const struct dev_pm_ops mtk_pcie_ - }; - - static const struct mtk_pcie_soc mtk_pcie_soc_v1 = { -+ .no_msi = true, - .ops = &mtk_pcie_ops, - .startup = mtk_pcie_startup_port, - }; diff --git a/target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch b/target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch deleted file mode 100644 index 75b9947392..0000000000 --- a/target/linux/generic/backport-5.15/830-v5.14-leds-lp55xx-Initialize-enable-GPIO-direction-to-outp.patch +++ /dev/null @@ -1,28 +0,0 @@ -From a5d3d1adc95f4ac5968b7a77ee95a3abbbb96f49 Mon Sep 17 00:00:00 2001 -From: Doug Zobel -Date: Mon, 10 May 2021 15:40:00 -0500 -Subject: [PATCH] leds: lp55xx: Initialize enable GPIO direction to output - -The "Convert to use GPIO descriptors" commit changed the -initialization of the enable GPIO from GPIOF_DIR_OUT to -GPIOD_ASIS. This breaks systems where the GPIO does not -default to output. Changing the enable initialization -to GPIOD_OUT_LOW. - -Signed-off-by: Doug Zobel -Signed-off-by: Pavel Machek ---- - drivers/leds/leds-lp55xx-common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/leds/leds-lp55xx-common.c -+++ b/drivers/leds/leds-lp55xx-common.c -@@ -694,7 +694,7 @@ struct lp55xx_platform_data *lp55xx_of_p - of_property_read_u8(np, "clock-mode", &pdata->clock_mode); - - pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable", -- GPIOD_ASIS); -+ GPIOD_OUT_LOW); - if (IS_ERR(pdata->enable_gpiod)) - return ERR_CAST(pdata->enable_gpiod); - diff --git a/target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch b/target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch deleted file mode 100644 index 4f867724ac..0000000000 --- a/target/linux/generic/backport-5.15/851-v5.15-0001-phy-marvell-phy-mvebu-a3700-comphy-Rename-HS-SGMMI-t.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 40da06da15c1718b02072687bbfb2d08f5eb9399 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pali=20Roh=C3=A1r?= -Date: Fri, 27 Aug 2021 11:27:52 +0200 -Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Rename HS-SGMMI to - 2500Base-X -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Comphy phy mode 0x3 is incorrectly named. It is not SGMII but rather -2500Base-X mode which runs at 3.125 Gbps speed. - -Rename macro names and comments to 2500Base-X. - -Signed-off-by: Pali Rohár -Fixes: 9695375a3f4a ("phy: add A3700 COMPHY support") -Signed-off-by: David S. Miller ---- - drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -+++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -@@ -29,7 +29,7 @@ - - #define COMPHY_FW_MODE_SATA 0x1 - #define COMPHY_FW_MODE_SGMII 0x2 --#define COMPHY_FW_MODE_HS_SGMII 0x3 -+#define COMPHY_FW_MODE_2500BASEX 0x3 - #define COMPHY_FW_MODE_USB3H 0x4 - #define COMPHY_FW_MODE_USB3D 0x5 - #define COMPHY_FW_MODE_PCIE 0x6 -@@ -40,7 +40,7 @@ - - #define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ - #define COMPHY_FW_SPEED_2_5G 1 --#define COMPHY_FW_SPEED_3_125G 2 /* SGMII 2.5G */ -+#define COMPHY_FW_SPEED_3_125G 2 /* 2500BASE-X */ - #define COMPHY_FW_SPEED_5G 3 - #define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */ - #define COMPHY_FW_SPEED_6G 5 -@@ -84,14 +84,14 @@ static const struct mvebu_a3700_comphy_c - MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1, - COMPHY_FW_MODE_SGMII), - MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1, -- COMPHY_FW_MODE_HS_SGMII), -+ COMPHY_FW_MODE_2500BASEX), - /* lane 1 */ - MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0, - COMPHY_FW_MODE_PCIE), - MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0, - COMPHY_FW_MODE_SGMII), - MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0, -- COMPHY_FW_MODE_HS_SGMII), -+ COMPHY_FW_MODE_2500BASEX), - /* lane 2 */ - MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0, - COMPHY_FW_MODE_SATA), -@@ -205,7 +205,7 @@ static int mvebu_a3700_comphy_power_on(s - COMPHY_FW_SPEED_1_25G); - break; - case PHY_INTERFACE_MODE_2500BASEX: -- dev_dbg(lane->dev, "set lane %d to HS SGMII mode\n", -+ dev_dbg(lane->dev, "set lane %d to 2500BASEX mode\n", - lane->id); - fw_param = COMPHY_FW_NET(fw_mode, lane->port, - COMPHY_FW_SPEED_3_125G); diff --git a/target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch b/target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch deleted file mode 100644 index 99f56f1c57..0000000000 --- a/target/linux/generic/backport-5.15/851-v5.15-0002-phy-marvell-phy-mvebu-a3700-comphy-Remove-unsupporte.patch +++ /dev/null @@ -1,40 +0,0 @@ -From e1dbe9ecf621b6f71f3d2df3e50731d583f3d27f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pali=20Roh=C3=A1r?= -Date: Fri, 27 Aug 2021 11:27:53 +0200 -Subject: [PATCH] phy: marvell: phy-mvebu-a3700-comphy: Remove unsupported - modes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Armada 3700 does not support RXAUI, XFI and neither SFI. Remove unused -macros for these unsupported modes. - -Signed-off-by: Pali Rohár -Fixes: 9695375a3f4a ("phy: add A3700 COMPHY support") -Signed-off-by: David S. Miller ---- - drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 6 ------ - 1 file changed, 6 deletions(-) - ---- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -+++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c -@@ -33,18 +33,12 @@ - #define COMPHY_FW_MODE_USB3H 0x4 - #define COMPHY_FW_MODE_USB3D 0x5 - #define COMPHY_FW_MODE_PCIE 0x6 --#define COMPHY_FW_MODE_RXAUI 0x7 --#define COMPHY_FW_MODE_XFI 0x8 --#define COMPHY_FW_MODE_SFI 0x9 - #define COMPHY_FW_MODE_USB3 0xa - - #define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ - #define COMPHY_FW_SPEED_2_5G 1 - #define COMPHY_FW_SPEED_3_125G 2 /* 2500BASE-X */ - #define COMPHY_FW_SPEED_5G 3 --#define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */ --#define COMPHY_FW_SPEED_6G 5 --#define COMPHY_FW_SPEED_10_3125G 6 /* XFI 10G */ - #define COMPHY_FW_SPEED_MAX 0x3F - - #define COMPHY_FW_MODE(mode) ((mode) << 12) From fc8778981fb4240d87dec182181eff685dc76633 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 21 Mar 2022 15:13:01 +0100 Subject: [PATCH 05/26] generic: 5.15: rework backport patch Rework backport patch for kernel 5.15. Signed-off-by: Ansuel Smith --- ...N-filtering-syncing-out-of-dsa_switc.patch | 42 +++++++++---------- ...cross-chip-syncing-of-VLAN-filtering.patch | 22 +++++----- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch b/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch index eb60134a1e..c36b9e6a90 100644 --- a/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch +++ b/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch @@ -1,13 +1,7 @@ -From 7164a8cde4b42f76474088ccaf53f1e463d4e2f6 Mon Sep 17 00:00:00 2001 +From 381a730182f1d174e1950cd4e63e885b1c302051 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Mon, 24 Jan 2022 22:09:43 +0100 -Subject: [PATCH 5.10 1/2] net: dsa: Move VLAN filtering syncing out of - dsa_switch_bridge_leave -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -commit 381a730182f1d174e1950cd4e63e885b1c302051 upstream. +Subject: net: dsa: Move VLAN filtering syncing out of dsa_switch_bridge_leave Most of dsa_switch_bridge_leave was, in fact, dealing with the syncing of VLAN filtering for switches on which that is a global @@ -17,15 +11,16 @@ bugfix in the following commit. Signed-off-by: Tobias Waldekranz Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller -Signed-off-by: Marek Behún --- - net/dsa/switch.c | 39 ++++++++++++++++++++++++++------------- - 1 file changed, 26 insertions(+), 13 deletions(-) + net/dsa/switch.c | 38 +++++++++++++++++++++++++------------- + 1 file changed, 25 insertions(+), 13 deletions(-) +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index e3c7d2627a619..9f9b70d6070a3 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -104,23 +104,12 @@ static int dsa_switch_bridge_join(struct - return 0; +@@ -113,25 +113,14 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds, + return dsa_tag_8021q_bridge_join(ds, info); } -static int dsa_switch_bridge_leave(struct dsa_switch *ds, @@ -33,9 +28,11 @@ Signed-off-by: Marek Behún +static int dsa_switch_sync_vlan_filtering(struct dsa_switch *ds, + struct dsa_notifier_bridge_info *info) { - bool unset_vlan_filtering = br_vlan_enabled(info->br); - struct dsa_switch_tree *dst = ds->dst; - int err, i; + struct netlink_ext_ack extack = {0}; + bool change_vlan_filtering = false; + bool vlan_filtering; + int err, port; - if (dst->index == info->tree_index && ds->index == info->sw_index && - ds->ops->port_bridge_leave) @@ -47,14 +44,13 @@ Signed-off-by: Marek Behún - info->sw_index, info->port, - info->br); - - /* If the bridge was vlan_filtering, the bridge core doesn't trigger an - * event for changing vlan_filtering setting upon slave ports leaving - * it. That is a good thing, because that lets us handle it and also -@@ -153,6 +142,30 @@ static int dsa_switch_bridge_leave(struc - if (err && err != EOPNOTSUPP) + if (ds->needs_standalone_vlan_filtering && !br_vlan_enabled(info->br)) { + change_vlan_filtering = true; + vlan_filtering = true; +@@ -172,6 +161,29 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, return err; } -+ + + return 0; +} + @@ -78,6 +74,8 @@ Signed-off-by: Marek Behún + if (err) + return err; + - return 0; + return dsa_tag_8021q_bridge_leave(ds, info); } +-- +cgit diff --git a/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch b/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch index 0b36ef7cec..079ac7eb63 100644 --- a/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch +++ b/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch @@ -1,12 +1,7 @@ -From 6948a6654ffc878fc0258b363da77e7fd775b2d9 Mon Sep 17 00:00:00 2001 +From 108dc8741c203e9d6ce4e973367f1bac20c7192b Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Mon, 24 Jan 2022 22:09:44 +0100 -Subject: [PATCH 5.10 2/2] net: dsa: Avoid cross-chip syncing of VLAN filtering -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -commit 108dc8741c203e9d6ce4e973367f1bac20c7192b upstream. +Subject: net: dsa: Avoid cross-chip syncing of VLAN filtering Changes to VLAN filtering are not applicable to cross-chip notifications. @@ -34,25 +29,28 @@ Fixes: d371b7c92d19 ("net: dsa: Unset vlan_filtering when ports leave the bridge Signed-off-by: Tobias Waldekranz Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller -Signed-off-by: Marek Behún --- net/dsa/switch.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index 9f9b70d6070a3..517cc83d13cc8 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -162,9 +162,11 @@ static int dsa_switch_bridge_leave(struc +@@ -180,9 +180,11 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, info->sw_index, info->port, - info->br); + info->bridge); - err = dsa_switch_sync_vlan_filtering(ds, info); - if (err) - return err; -+ if (dst->index == info->tree_index && ds->index == info->sw_index) { ++ if (ds->dst->index == info->tree_index && ds->index == info->sw_index) { + err = dsa_switch_sync_vlan_filtering(ds, info); + if (err) + return err; + } - return 0; + return dsa_tag_8021q_bridge_leave(ds, info); } +-- +cgit From 7829ae4a2f9d37fa66b683d5824e0e3e93bb6c50 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Fri, 7 Jan 2022 23:32:59 +0100 Subject: [PATCH 06/26] generic: 5.15: qca8k: refresh backport patches Refresh qca8k backport patches for 5.15 kernel. Vlan_prepare is now dropped and there were some changes to vlan add/remove functions. Signed-off-by: Ansuel Smith --- ...ernal-delay-applied-to-the-wrong-PAD.patch | 6 +- ...16-net-dsa-qca8k-fix-MTU-calculation.patch | 2 + ...redundant-check-in-parse_port_config.patch | 7 +- ...vert-to-GENMASK_FIELD_PREP_FIELD_GET.patch | 66 ++++++++++--------- ...move-extra-mutex_init-in-qca8k_setup.patch | 5 ++ ...move-regmap-init-in-probe-and-set-it.patch | 7 +- ...k-initial-conversion-to-regmap-heper.patch | 17 +++-- ...ca8k-add-additional-MIB-counter-and-.patch | 17 +++-- ...ca8k-add-support-for-port-fast-aging.patch | 11 +++- ...sa-qca8k-add-set_ageing_time-support.patch | 19 ++++-- ...sa-qca8k-add-support-for-mdb_add-del.patch | 25 ++++--- 11 files changed, 119 insertions(+), 63 deletions(-) diff --git a/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch b/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch index df9518d86c..430329e23b 100644 --- a/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch +++ b/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch @@ -18,9 +18,11 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index a429c9750add1b..d7bcecbc1c5300 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1433,6 +1433,12 @@ qca8k_phylink_mac_config(struct dsa_swit +@@ -1433,6 +1433,12 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val); @@ -33,7 +35,7 @@ Signed-off-by: David S. Miller /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and * falling edge is set writing in the PORT0 PAD reg */ -@@ -1455,12 +1461,6 @@ qca8k_phylink_mac_config(struct dsa_swit +@@ -1455,12 +1461,6 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, val); diff --git a/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch b/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch index 7348d93ec4..721a59108b 100644 --- a/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch +++ b/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch @@ -28,6 +28,8 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index d7bcecbc1c5300..147ca39531a3bb 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1256,8 +1256,12 @@ qca8k_setup(struct dsa_switch *ds) diff --git a/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch b/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch index f477b1b929..d86f6156a5 100644 --- a/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch +++ b/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch @@ -16,9 +16,11 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index a429c9750add1..bfffc1fb7016d 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -983,7 +983,7 @@ qca8k_parse_port_config(struct qca8k_pri +@@ -983,7 +983,7 @@ qca8k_parse_port_config(struct qca8k_priv *priv) u32 delay; /* We have 2 CPU port. Check them */ @@ -27,3 +29,6 @@ Signed-off-by: David S. Miller /* Skip every other port */ if (port != 0 && port != 6) continue; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch b/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch index c1489fd9a8..a37ab8b848 100644 --- a/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch +++ b/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch @@ -14,6 +14,8 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 153 ++++++++++++++++++++++++++---------------------- 2 files changed, 130 insertions(+), 121 deletions(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index bfffc1fb7016d..0eceb9cba2dc8 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -9,6 +9,7 @@ @@ -24,7 +26,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -319,18 +320,18 @@ qca8k_fdb_read(struct qca8k_priv *priv, +@@ -319,18 +320,18 @@ qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) } /* vid - 83:72 */ @@ -52,7 +54,7 @@ Signed-off-by: David S. Miller return 0; } -@@ -343,18 +344,18 @@ qca8k_fdb_write(struct qca8k_priv *priv, +@@ -343,18 +344,18 @@ qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, int i; /* vid - 83:72 */ @@ -80,7 +82,7 @@ Signed-off-by: David S. Miller /* load the array into the ARL table */ for (i = 0; i < 3; i++) -@@ -372,7 +373,7 @@ qca8k_fdb_access(struct qca8k_priv *priv +@@ -372,7 +373,7 @@ qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port) reg |= cmd; if (port >= 0) { reg |= QCA8K_ATU_FUNC_PORT_EN; @@ -89,7 +91,7 @@ Signed-off-by: David S. Miller } /* Write the function register triggering the table access */ -@@ -454,7 +455,7 @@ qca8k_vlan_access(struct qca8k_priv *pri +@@ -454,7 +455,7 @@ qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) /* Set the command and VLAN index */ reg = QCA8K_VTU_FUNC1_BUSY; reg |= cmd; @@ -98,7 +100,7 @@ Signed-off-by: David S. Miller /* Write the function register triggering the table access */ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); -@@ -500,13 +501,11 @@ qca8k_vlan_add(struct qca8k_priv *priv, +@@ -500,13 +501,11 @@ qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, bool untagged) if (ret < 0) goto out; reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; @@ -115,7 +117,7 @@ Signed-off-by: David S. Miller ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); if (ret) -@@ -534,15 +533,13 @@ qca8k_vlan_del(struct qca8k_priv *priv, +@@ -534,15 +533,13 @@ qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid) ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); if (ret < 0) goto out; @@ -134,7 +136,7 @@ Signed-off-by: David S. Miller if ((reg & mask) != mask) { del = false; -@@ -1014,7 +1011,7 @@ qca8k_parse_port_config(struct qca8k_pri +@@ -1014,7 +1011,7 @@ qca8k_parse_port_config(struct qca8k_priv *priv) mode == PHY_INTERFACE_MODE_RGMII_TXID) delay = 1; @@ -143,7 +145,7 @@ Signed-off-by: David S. Miller dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); delay = 3; } -@@ -1030,7 +1027,7 @@ qca8k_parse_port_config(struct qca8k_pri +@@ -1030,7 +1027,7 @@ qca8k_parse_port_config(struct qca8k_priv *priv) mode == PHY_INTERFACE_MODE_RGMII_RXID) delay = 2; @@ -207,7 +209,7 @@ Signed-off-by: David S. Miller QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | QCA8K_PORT_HOL_CTRL1_WRED_EN, -@@ -1269,8 +1264,8 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1265,8 +1260,8 @@ qca8k_setup(struct dsa_switch *ds) mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, @@ -218,35 +220,34 @@ Signed-off-by: David S. Miller mask); } -@@ -1918,11 +1913,11 @@ qca8k_port_vlan_filtering(struct dsa_swi +@@ -1912,11 +1907,11 @@ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, if (vlan_filtering) { - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), -- QCA8K_PORT_LOOKUP_VLAN_MODE, -+ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, - QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE); + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_VLAN_MODE, ++ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, + QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE); } else { - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), -- QCA8K_PORT_LOOKUP_VLAN_MODE, -+ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, - QCA8K_PORT_LOOKUP_VLAN_MODE_NONE); + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_VLAN_MODE, ++ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, + QCA8K_PORT_LOOKUP_VLAN_MODE_NONE); } -@@ -1953,11 +1948,9 @@ qca8k_port_vlan_add(struct dsa_switch *d - dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret); +@@ -1940,10 +1935,9 @@ qca8k_port_vlan_add(struct dsa_switch *ds, int port, + } if (pvid) { - int shift = 16 * (port % 2); - - qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), -- 0xfff << shift, -- vlan->vid_end << shift); -+ QCA8K_EGREES_VLAN_PORT_MASK(port), -+ QCA8K_EGREES_VLAN_PORT(port, vlan->vid_end)); - qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), - QCA8K_PORT_VLAN_CVID(vlan->vid_end) | - QCA8K_PORT_VLAN_SVID(vlan->vid_end)); -@@ -2050,7 +2043,7 @@ static int qca8k_read_switch_id(struct q + ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), +- 0xfff << shift, vlan->vid << shift); ++ QCA8K_EGREES_VLAN_PORT_MASK(port), ++ QCA8K_EGREES_VLAN_PORT(port, vlan->vid)); + if (ret) + return ret; + +@@ -2037,7 +2031,7 @@ static int qca8k_read_switch_id(struct qca8k_priv *priv) if (ret < 0) return -ENODEV; @@ -255,7 +256,7 @@ Signed-off-by: David S. Miller if (id != data->id) { dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); return -ENODEV; -@@ -2059,7 +2052,7 @@ static int qca8k_read_switch_id(struct q +@@ -2046,7 +2040,7 @@ static int qca8k_read_switch_id(struct qca8k_priv *priv) priv->switch_id = id; /* Save revision to communicate to the internal PHY driver */ @@ -264,6 +265,8 @@ Signed-off-by: David S. Miller return 0; } +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 128b8cf85e080..085885275398b 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -30,9 +30,9 @@ @@ -506,3 +509,6 @@ Signed-off-by: David S. Miller #define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2))) /* L3 registers */ +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch b/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch index 8c39b8ea29..e5f3edfa51 100644 --- a/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch +++ b/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch @@ -12,6 +12,8 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 2 -- 1 file changed, 2 deletions(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 0eceb9cba2dc8..ae02043a52079 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1086,8 +1086,6 @@ qca8k_setup(struct dsa_switch *ds) @@ -23,3 +25,6 @@ Signed-off-by: David S. Miller /* Start by setting up the register mapping */ priv->regmap = devm_regmap_init(ds->dev, NULL, priv, &qca8k_regmap_config); +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch b/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch index 9fcc74a7ce..f67abf901b 100644 --- a/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch +++ b/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch @@ -14,6 +14,8 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index ae02043a52079..f63a432916360 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1086,12 +1086,6 @@ qca8k_setup(struct dsa_switch *ds) @@ -29,7 +31,7 @@ Signed-off-by: David S. Miller ret = qca8k_setup_mdio_bus(priv); if (ret) return ret; -@@ -2085,6 +2079,14 @@ qca8k_sw_probe(struct mdio_device *mdiod +@@ -2073,6 +2067,14 @@ qca8k_sw_probe(struct mdio_device *mdiodev) gpiod_set_value_cansleep(priv->reset_gpio, 0); } @@ -44,3 +46,6 @@ Signed-off-by: David S. Miller /* Check the detected switch id */ ret = qca8k_read_switch_id(priv); if (ret) +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch b/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch index 4ca9c8ba41..e0a9c809d8 100644 --- a/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch +++ b/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch @@ -23,6 +23,8 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 107 +++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 60 deletions(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index f63a432916360..d64a9af186beb 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -10,6 +10,7 @@ @@ -33,7 +35,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 +@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 page) static int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) { @@ -116,7 +118,7 @@ Signed-off-by: David S. Miller static const struct regmap_range qca8k_readable_ranges[] = { regmap_reg_range(0x0000, 0x00e4), /* Global control */ regmap_reg_range(0x0100, 0x0168), /* EEE control */ -@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap +@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap_config = { .max_register = 0x16ac, /* end MIB - Port6 range */ .reg_read = qca8k_regmap_read, .reg_write = qca8k_regmap_write, @@ -166,7 +168,7 @@ Signed-off-by: David S. Miller if (ret) goto exit; -@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv +@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) mask |= QCA8K_PORT_STATUS_LINK_AUTO; if (enable) @@ -178,7 +180,7 @@ Signed-off-by: David S. Miller } static u32 -@@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv * +@@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv) * a dt-overlay and driver reload changed the configuration */ @@ -221,7 +223,7 @@ Signed-off-by: David S. Miller if (ret) return ret; -@@ -1745,9 +1732,9 @@ qca8k_port_bridge_join(struct dsa_switch +@@ -1741,9 +1728,9 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) /* Add this port to the portvlan mask of the other ports * in the bridge */ @@ -234,7 +236,7 @@ Signed-off-by: David S. Miller if (ret) return ret; if (i != port) -@@ -1777,9 +1764,9 @@ qca8k_port_bridge_leave(struct dsa_switc +@@ -1773,9 +1760,9 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) /* Remove this port to the portvlan mask of the other ports * in the bridge */ @@ -247,3 +249,6 @@ Signed-off-by: David S. Miller } /* Set the cpu port to be the only one in the portvlan mask of +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch b/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch index 78bdf7f77d..e889a7f5b2 100644 --- a/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch +++ b/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch @@ -17,9 +17,11 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 4 ++++ 2 files changed, 24 insertions(+), 3 deletions(-) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index d64a9af186beb..bedaaa6b9a1df 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -70,6 +70,8 @@ static const struct qca8k_mib_desc ar832 +@@ -70,6 +70,8 @@ static const struct qca8k_mib_desc ar8327_mib[] = { MIB_DESC(1, 0x9c, "TxExcDefer"), MIB_DESC(1, 0xa0, "TxDefer"), MIB_DESC(1, 0xa4, "TxLateCol"), @@ -28,7 +30,7 @@ Signed-off-by: David S. Miller }; /* The 32bit switch registers are accessed indirectly. To achieve this we need -@@ -1605,12 +1607,16 @@ qca8k_phylink_mac_link_up(struct dsa_swi +@@ -1601,12 +1603,16 @@ qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, static void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) { @@ -46,7 +48,7 @@ Signed-off-by: David S. Miller strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name, ETH_GSTRING_LEN); } -@@ -1620,12 +1626,15 @@ qca8k_get_ethtool_stats(struct dsa_switc +@@ -1616,12 +1622,15 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) { struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; @@ -63,7 +65,7 @@ Signed-off-by: David S. Miller mib = &ar8327_mib[i]; reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; -@@ -1648,10 +1657,15 @@ qca8k_get_ethtool_stats(struct dsa_switc +@@ -1644,10 +1653,15 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, static int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset) { @@ -80,7 +82,7 @@ Signed-off-by: David S. Miller } static int -@@ -2146,14 +2160,17 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, +@@ -2150,14 +2164,17 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, static const struct qca8k_match_data qca8327 = { .id = QCA8K_ID_QCA8327, .reduced_package = true, @@ -98,6 +100,8 @@ Signed-off-by: David S. Miller }; static const struct of_device_id qca8k_of_match[] = { +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 085885275398b..91c94dfc9789d 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -21,6 +21,9 @@ @@ -118,3 +122,6 @@ Signed-off-by: David S. Miller }; enum { +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch b/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch index 41efa89b5e..877223b5d2 100644 --- a/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch +++ b/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch @@ -14,9 +14,11 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 1 + 2 files changed, 12 insertions(+) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index bedaaa6b9a1df..d988df913ae02 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1790,6 +1790,16 @@ qca8k_port_bridge_leave(struct dsa_switc +@@ -1786,6 +1786,16 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); } @@ -33,7 +35,7 @@ Signed-off-by: David S. Miller static int qca8k_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) -@@ -2005,6 +2015,7 @@ static const struct dsa_switch_ops qca8k +@@ -1994,6 +2004,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { .port_stp_state_set = qca8k_port_stp_state_set, .port_bridge_join = qca8k_port_bridge_join, .port_bridge_leave = qca8k_port_bridge_leave, @@ -41,6 +43,8 @@ Signed-off-by: David S. Miller .port_fdb_add = qca8k_port_fdb_add, .port_fdb_del = qca8k_port_fdb_del, .port_fdb_dump = qca8k_port_fdb_dump, +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 91c94dfc9789d..a533b8cf143be 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -262,6 +262,7 @@ enum qca8k_fdb_cmd { @@ -51,3 +55,6 @@ Signed-off-by: David S. Miller QCA8K_FDB_NEXT = 6, QCA8K_FDB_SEARCH = 7, }; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch b/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch index f32e6ae93a..b851c9598b 100644 --- a/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch +++ b/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch @@ -16,9 +16,11 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 3 +++ 2 files changed, 28 insertions(+) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index d988df913ae02..45e769b9166b8 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1261,6 +1261,10 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1257,6 +1257,10 @@ qca8k_setup(struct dsa_switch *ds) /* We don't have interrupts for link changes, so we need to poll */ ds->pcs_poll = true; @@ -29,10 +31,11 @@ Signed-off-by: David S. Miller return 0; } -@@ -1801,6 +1805,26 @@ qca8k_port_fast_age(struct dsa_switch *d +@@ -1796,6 +1800,26 @@ qca8k_port_fast_age(struct dsa_switch *ds, int port) + mutex_unlock(&priv->reg_mutex); } - static int ++static int +qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) +{ + struct qca8k_priv *priv = ds->priv; @@ -52,11 +55,10 @@ Signed-off-by: David S. Miller + QCA8K_ATU_AGE_TIME(val)); +} + -+static int + static int qca8k_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) - { -@@ -2006,6 +2030,7 @@ static const struct dsa_switch_ops qca8k +@@ -1995,6 +2019,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { .get_strings = qca8k_get_strings, .get_ethtool_stats = qca8k_get_ethtool_stats, .get_sset_count = qca8k_get_sset_count, @@ -64,6 +66,8 @@ Signed-off-by: David S. Miller .get_mac_eee = qca8k_get_mac_eee, .set_mac_eee = qca8k_set_mac_eee, .port_enable = qca8k_port_enable, +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index a533b8cf143be..40ec8012622f7 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -175,6 +175,9 @@ @@ -76,3 +80,6 @@ Signed-off-by: David S. Miller #define QCA8K_REG_GLOBAL_FW_CTRL0 0x620 #define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) #define QCA8K_REG_GLOBAL_FW_CTRL1 0x624 +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch b/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch index e0daa88c31..a71d7480da 100644 --- a/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch +++ b/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch @@ -18,12 +18,15 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 45e769b9166b8..67742fbd80409 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -436,6 +436,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv) +@@ -435,6 +435,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv) + mutex_unlock(&priv->reg_mutex); } - static int ++static int +qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, + const u8 *mac, u16 vid) +{ @@ -98,15 +101,14 @@ Signed-off-by: David S. Miller + return ret; +} + -+static int + static int qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) { - u32 reg; -@@ -1929,6 +2004,28 @@ qca8k_port_fdb_dump(struct dsa_switch *d +@@ -1925,6 +2000,28 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port, return 0; } -+static void ++static int +qca8k_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ @@ -114,7 +116,7 @@ Signed-off-by: David S. Miller + const u8 *addr = mdb->addr; + u16 vid = mdb->vid; + -+ qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid); ++ return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid); +} + +static int @@ -130,13 +132,16 @@ Signed-off-by: David S. Miller + static int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, - struct switchdev_trans *trans) -@@ -2044,6 +2141,8 @@ static const struct dsa_switch_ops qca8k + struct netlink_ext_ack *extack) +@@ -2033,6 +2130,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { .port_fdb_add = qca8k_port_fdb_add, .port_fdb_del = qca8k_port_fdb_del, .port_fdb_dump = qca8k_port_fdb_dump, + .port_mdb_add = qca8k_port_mdb_add, + .port_mdb_del = qca8k_port_mdb_del, .port_vlan_filtering = qca8k_port_vlan_filtering, - .port_vlan_prepare = qca8k_port_vlan_prepare, .port_vlan_add = qca8k_port_vlan_add, + .port_vlan_del = qca8k_port_vlan_del, +-- +cgit 1.2.3-1.el7 + From 1f302afd7350f46ec0fcc4b12b0ad59ac92fe5b6 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 4 Nov 2021 23:25:50 +0100 Subject: [PATCH 07/26] generic: 5.15: rework hack patch Rework hack patch in dir for kernel 5.15. For the specific patch of packet mangeling introduce a new extra_priv_flags as we don't have enough space to add additional flags in priv_flags. Signed-off-by: Ansuel Smith --- .../ath25/files/drivers/net/phy/mvswitch.c | 8 ++++ .../generic/files/drivers/net/phy/ar8216.c | 8 ++++ .../files/drivers/net/phy/b53/b53_common.c | 2 +- .../hack-5.15/212-tools_portability.patch | 4 +- .../hack-5.15/220-arm-gc_sections.patch | 4 +- .../hack-5.15/259-regmap_dynamic.patch | 42 ++++++++++++------- .../321-powerpc_crtsavres_prereq.patch | 2 +- ...don-t-reply-on-mtdblock-device-minor.patch | 33 +++++++-------- ...rans-call-add-disks-after-mtd-device.patch | 8 ++-- .../410-block-fit-partition-parser.patch | 22 +++++----- .../hack-5.15/600-bridge_offload.patch | 38 +++++++++-------- .../hack-5.15/660-fq_codel_defaults.patch | 2 +- .../700-swconfig_switch_drivers.patch | 2 +- .../710-net-dsa-mv88e6xxx-default-VID-1.patch | 4 +- ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 2 +- .../721-net-add-packet-mangeling.patch | 25 +++++++---- .../hack-5.15/773-bgmac-add-srab-switch.patch | 2 +- .../hack-5.15/901-debloat_sock_diag.patch | 10 ++--- .../hack-5.15/904-debloat_dma_buf.patch | 8 ++-- 19 files changed, 133 insertions(+), 93 deletions(-) diff --git a/target/linux/ath25/files/drivers/net/phy/mvswitch.c b/target/linux/ath25/files/drivers/net/phy/mvswitch.c index bd3b9e1ad1..e3550d55ba 100644 --- a/target/linux/ath25/files/drivers/net/phy/mvswitch.c +++ b/target/linux/ath25/files/drivers/net/phy/mvswitch.c @@ -312,7 +312,11 @@ mvswitch_config_init(struct phy_device *pdev) priv->orig_features = dev->features; #ifdef HEADER_MODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + dev->extra_priv_flags |= IFF_NO_IP_ALIGN; +#else dev->priv_flags |= IFF_NO_IP_ALIGN; +#endif dev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; #else dev->features |= NETIF_F_HW_VLAN_CTAG_RX; @@ -372,7 +376,11 @@ mvswitch_detach(struct phy_device *pdev) dev->eth_mangle_rx = NULL; dev->eth_mangle_tx = NULL; dev->features = priv->orig_features; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + dev->extra_priv_flags &= ~IFF_NO_IP_ALIGN; +#else dev->priv_flags &= ~IFF_NO_IP_ALIGN; +#endif } static void diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 11cb18e4f3..3e6494aebb 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -2465,7 +2465,11 @@ ar8xxx_phy_config_init(struct phy_device *phydev) /* VID fixup only needed on ar8216 */ if (chip_is_ar8216(priv)) { dev->phy_ptr = priv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + dev->extra_priv_flags |= IFF_NO_IP_ALIGN; +#else dev->priv_flags |= IFF_NO_IP_ALIGN; +#endif dev->eth_mangle_rx = ar8216_mangle_rx; dev->eth_mangle_tx = ar8216_mangle_tx; } @@ -2700,7 +2704,11 @@ ar8xxx_phy_detach(struct phy_device *phydev) #ifdef CONFIG_ETHERNET_PACKET_MANGLE dev->phy_ptr = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + dev->extra_priv_flags &= ~IFF_NO_IP_ALIGN; +#else dev->priv_flags &= ~IFF_NO_IP_ALIGN; +#endif dev->eth_mangle_rx = NULL; dev->eth_mangle_tx = NULL; #endif diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c index 030c5c86d6..87d731ec3e 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c @@ -529,7 +529,7 @@ static int b53_configure_ports_of(struct b53_device *dev) po |= PORT_OVERRIDE_SPEED_2000M; else po |= GMII_PO_SPEED_2000M; - /* fall through */ + fallthrough; case 1000: po |= GMII_PO_SPEED_1000M; break; diff --git a/target/linux/generic/hack-5.15/212-tools_portability.patch b/target/linux/generic/hack-5.15/212-tools_portability.patch index 0d8eb6fb9d..54ac048417 100644 --- a/target/linux/generic/hack-5.15/212-tools_portability.patch +++ b/target/linux/generic/hack-5.15/212-tools_portability.patch @@ -69,9 +69,9 @@ Signed-off-by: Felix Fietkau --- a/tools/include/linux/types.h +++ b/tools/include/linux/types.h @@ -7,8 +7,12 @@ - #include - #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ + #endif + +#ifndef __linux__ +#include +#else diff --git a/target/linux/generic/hack-5.15/220-arm-gc_sections.patch b/target/linux/generic/hack-5.15/220-arm-gc_sections.patch index 5b36c5ebae..331368b9fb 100644 --- a/target/linux/generic/hack-5.15/220-arm-gc_sections.patch +++ b/target/linux/generic/hack-5.15/220-arm-gc_sections.patch @@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos --- --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -114,6 +114,7 @@ config ARM +@@ -113,6 +113,7 @@ config ARM select HAVE_UID16 select HAVE_VIRT_CPU_ACCOUNTING_GEN select IRQ_FORCED_THREADING @@ -22,7 +22,7 @@ Signed-off-by: Gabor Juhos select OF_EARLY_FLATTREE if OF --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile -@@ -100,6 +100,7 @@ $(foreach o, $(libfdt_objs) atags_to_fdt +@@ -98,6 +98,7 @@ $(foreach o, $(libfdt_objs) atags_to_fdt ifdef building_out_of_srctree $(shell rm -f $(addprefix $(obj)/, fdt_rw.c fdt_ro.c fdt_wip.c fdt.c)) endif diff --git a/target/linux/generic/hack-5.15/259-regmap_dynamic.patch b/target/linux/generic/hack-5.15/259-regmap_dynamic.patch index bc81a7285c..1d9e862620 100644 --- a/target/linux/generic/hack-5.15/259-regmap_dynamic.patch +++ b/target/linux/generic/hack-5.15/259-regmap_dynamic.patch @@ -14,18 +14,19 @@ Signed-off-by: Felix Fietkau --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig -@@ -4,9 +4,8 @@ +@@ -4,10 +4,9 @@ # subsystems should select the appropriate symbols. config REGMAP -- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM) +- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO) select IRQ_DOMAIN if REGMAP_IRQ + select MDIO_BUS if REGMAP_MDIO - bool + tristate config REGCACHE_COMPRESSED select LZO_COMPRESS -@@ -14,46 +13,59 @@ config REGCACHE_COMPRESSED +@@ -15,53 +14,67 @@ config REGCACHE_COMPRESSED bool config REGMAP_AC97 @@ -33,58 +34,67 @@ Signed-off-by: Felix Fietkau tristate config REGMAP_I2C - tristate + select REGMAP + tristate depends on I2C config REGMAP_SLIMBUS - tristate + select REGMAP + tristate depends on SLIMBUS config REGMAP_SPI - tristate + select REGMAP -+ depends on SPI_MASTER + tristate depends on SPI config REGMAP_SPMI - tristate + select REGMAP + tristate depends on SPMI config REGMAP_W1 - tristate + select REGMAP + tristate depends on W1 - config REGMAP_MMIO - tristate + config REGMAP_MDIO + select REGMAP + tristate + + config REGMAP_MMIO ++ select REGMAP + tristate config REGMAP_IRQ - bool + select REGMAP + bool config REGMAP_SOUNDWIRE - tristate + select REGMAP + tristate + depends on SOUNDWIRE + + config REGMAP_SOUNDWIRE_MBQ ++ select REGMAP + tristate depends on SOUNDWIRE config REGMAP_SCCB - tristate + select REGMAP + tristate depends on I2C config REGMAP_I3C - tristate + select REGMAP + tristate depends on I3C config REGMAP_SPI_AVMM - tristate + select REGMAP + tristate depends on SPI + --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -2,10 +2,14 @@ diff --git a/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch b/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch index 4bb438295d..215528a90c 100644 --- a/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch +++ b/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch @@ -24,7 +24,7 @@ Signed-off-by: Alexandros C. Couloumbis -ifdef CONFIG_PPC32 -KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o -else --ifeq ($(call ld-ifversion, -ge, 225000000, y),y) +-ifeq ($(call ld-ifversion, -ge, 22500, y),y) -# Have the linker provide sfpr if possible. -# There is a corresponding test in arch/powerpc/lib/Makefile -KBUILD_LDFLAGS_MODULE += --save-restore-funcs diff --git a/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch b/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch index 04cf52b096..8f985c0b8f 100644 --- a/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch +++ b/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch @@ -28,43 +28,42 @@ Signed-off-by: Daniel Golle #include #include #include -@@ -121,7 +122,8 @@ int get_tree_mtd(struct fs_context *fc, +@@ -120,8 +121,9 @@ int get_tree_mtd(struct fs_context *fc, + struct fs_context *fc)) { #ifdef CONFIG_BLOCK - struct block_device *bdev; -- int ret, major; +- dev_t dev; +- int ret; + struct mtd_blktrans_dev *blktrans_dev; -+ int ret, major, part_bits; ++ struct block_device *bdev; ++ int ret, part_bits; #endif int mtdnr; -@@ -169,21 +171,38 @@ int get_tree_mtd(struct fs_context *fc, +@@ -169,16 +171,36 @@ int get_tree_mtd(struct fs_context *fc, /* try the old way - the hack where we allowed users to mount * /dev/mtdblock$(n) but didn't actually _use_ the blockdev */ -- bdev = lookup_bdev(fc->source); +- ret = lookup_bdev(fc->source, &dev); +- if (ret) { + bdev = blkdev_get_by_path(fc->source, FMODE_READ, NULL); - if (IS_ERR(bdev)) { - ret = PTR_ERR(bdev); ++ if (IS_ERR(bdev)) { ++ ret = PTR_ERR(bdev); errorf(fc, "MTD: Couldn't look up '%s': %d", fc->source, ret); return ret; } - pr_debug("MTDSB: lookup_bdev() returned 0\n"); + pr_debug("MTDSB: blkdev_get_by_path() returned 0\n"); - major = MAJOR(bdev->bd_dev); -- mtdnr = MINOR(bdev->bd_dev); -- bdput(bdev); - -- if (major == MTD_BLOCK_MAJOR) -- return mtd_get_sb_by_nr(fc, mtdnr, fill_super); -+ if (major == MTD_BLOCK_MAJOR) { +- if (MAJOR(dev) == MTD_BLOCK_MAJOR) +- return mtd_get_sb_by_nr(fc, MINOR(dev), fill_super); ++ if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { + if (!bdev->bd_disk) { + blkdev_put(bdev, FMODE_READ); + BUG(); + return -EINVAL; + } -+ + + blktrans_dev = (struct mtd_blktrans_dev *)(bdev->bd_disk->private_data); + if (!blktrans_dev || !blktrans_dev->tr) { + blkdev_put(bdev, FMODE_READ); @@ -76,7 +75,7 @@ Signed-off-by: Daniel Golle + blkdev_put(bdev, FMODE_READ); + if (MINOR(bdev->bd_dev) != (mtdnr << part_bits)) + return -EINVAL; - ++ + return mtd_get_sb_by_nr(fc, mtdnr, fill_super); + } + blkdev_put(bdev, FMODE_READ); diff --git a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch index 988d900b31..a715d17f3b 100644 --- a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch +++ b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -51,7 +51,7 @@ Signed-off-by: Daniel Golle + + list_for_each_entry(tr, &blktrans_majors, list) { + list_for_each_entry_safe(dev, next, &tr->devs, list) { -+ if (dev->disk->flags & GENHD_FL_UP) ++ if (disk_live(dev->disk)) + continue; + + device_add_disk(&dev->mtd->dev, dev->disk, NULL); @@ -88,11 +88,11 @@ Signed-off-by: Daniel Golle del_mtd_device(mtd); --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h -@@ -76,6 +76,6 @@ extern int deregister_mtd_blktrans(struc +@@ -76,6 +76,7 @@ extern int deregister_mtd_blktrans(struc extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev); -- +extern void register_mtd_blktrans_devs(void); - #endif /* __MTD_TRANS_H__ */ + /** + * module_mtd_blktrans() - Helper macro for registering a mtd blktrans driver diff --git a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch index 7816356227..b8cada98e6 100644 --- a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch +++ b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch @@ -6,9 +6,9 @@ #define ADDPART_FLAG_WHOLEDISK 2 +#define ADDPART_FLAG_READONLY 4 +#define ADDPART_FLAG_ROOTDEV 8 - void delete_partition(struct hd_struct *part); - int bdev_add_partition(struct block_device *bdev, int partno, - sector_t start, sector_t length); + int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, + sector_t length); + int bdev_del_partition(struct gendisk *disk, int partno); --- a/block/partitions/Kconfig +++ b/block/partitions/Kconfig @@ -101,6 +101,13 @@ config ATARI_PARTITION @@ -92,17 +92,17 @@ --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -396,7 +396,11 @@ int ubiblock_create(struct ubi_volume_in - dev->leb_size = vi->usable_leb_size; - /* Initialize the gendisk of this ubiblock device */ + gd->fops = &ubiblock_ops; + gd->major = ubiblock_major; +#ifdef CONFIG_FIT_PARTITION -+ gd = alloc_disk(0); ++ gd->minors = 0; +#else - gd = alloc_disk(1); + gd->minors = 1; +#endif - if (!gd) { - pr_err("UBI: block: alloc_disk failed\n"); - ret = -ENODEV; + gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL); + if (gd->first_minor < 0) { + dev_err(disk_to_dev(gd), @@ -413,6 +417,9 @@ int ubiblock_create(struct ubi_volume_in goto out_put_disk; } @@ -118,7 +118,7 @@ @@ -706,6 +706,9 @@ int efi_partition(struct parsed_partitio gpt_entry *ptes = NULL; u32 i; - unsigned ssz = bdev_logical_block_size(state->bdev) / 512; + unsigned ssz = queue_logical_block_size(state->disk->queue) / 512; +#ifdef CONFIG_FIT_PARTITION + u32 extra_slot = 64; +#endif diff --git a/target/linux/generic/hack-5.15/600-bridge_offload.patch b/target/linux/generic/hack-5.15/600-bridge_offload.patch index 586353816c..9206722d73 100644 --- a/target/linux/generic/hack-5.15/600-bridge_offload.patch +++ b/target/linux/generic/hack-5.15/600-bridge_offload.patch @@ -1,10 +1,10 @@ --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -57,6 +57,7 @@ struct br_ip_list { - #define BR_MRP_LOST_CONT BIT(18) #define BR_MRP_LOST_IN_CONT BIT(19) - #define BR_BPDU_FILTER BIT(20) -+#define BR_OFFLOAD BIT(21) + #define BR_TX_FWD_OFFLOAD BIT(20) + #define BR_BPDU_FILTER BIT(21) ++#define BR_OFFLOAD BIT(22) #define BR_DEFAULT_AGEING_TIME (300 * HZ) @@ -169,12 +169,12 @@ + if (br_offload_input(p, skb)) + return RX_HANDLER_CONSUMED; + - if (p->flags & BR_VLAN_TUNNEL) { - if (br_handle_ingress_vlan_tunnel(skb, p, - nbp_vlan_group_rcu(p))) + if (p->flags & BR_VLAN_TUNNEL) + br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p)) + --- /dev/null +++ b/net/bridge/br_offload.c -@@ -0,0 +1,436 @@ +@@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include @@ -580,7 +580,8 @@ +} + + -+int br_offload_set_cache_size(struct net_bridge *br, unsigned long val) ++int br_offload_set_cache_size(struct net_bridge *br, unsigned long val, ++ struct netlink_ext_ack *extack) +{ + br->offload_cache_size = val; + br_offload_check_gc(br); @@ -588,7 +589,8 @@ + return 0; +} + -+int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val) ++int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val, ++ struct netlink_ext_ack *extack) +{ + br->offload_cache_reserved = val; + br_offload_check_gc(br); @@ -657,8 +659,8 @@ + u32 offload_cache_reserved; + #ifdef CONFIG_NET_SWITCHDEV - int offload_fwd_mark; - #endif + /* Counter used to make sure that hardware domains get unique + * identifiers in case a bridge spans multiple switchdev instances. @@ -501,6 +517,10 @@ struct br_input_skb_cb { #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE u8 br_netfilter_broute:1; @@ -669,10 +671,10 @@ + int input_ifindex; #ifdef CONFIG_NET_SWITCHDEV - int offload_fwd_mark; + /* Set if TX data plane offloading is used towards at least one --- /dev/null +++ b/net/bridge/br_private_offload.h -@@ -0,0 +1,21 @@ +@@ -0,0 +1,23 @@ +#ifndef __BR_OFFLOAD_H +#define __BR_OFFLOAD_H + @@ -682,8 +684,10 @@ +void br_offload_fdb_update(const struct net_bridge_fdb_entry *fdb); +int br_offload_init(void); +void br_offload_fini(void); -+int br_offload_set_cache_size(struct net_bridge *br, unsigned long val); -+int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val); ++int br_offload_set_cache_size(struct net_bridge *br, unsigned long val, ++ struct netlink_ext_ack *extack); ++int br_offload_set_cache_reserved(struct net_bridge *br, unsigned long val, ++ struct netlink_ext_ack *extack); + +static inline void br_offload_skb_disable(struct sk_buff *skb) +{ @@ -804,9 +808,9 @@ __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid); + br_offload_skb_disable(skb); - - return 0; } + + int br_handle_egress_vlan_tunnel(struct sk_buff *skb, @@ -203,6 +205,7 @@ int br_handle_egress_vlan_tunnel(struct if (err) return err; diff --git a/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch b/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch index 5541c0bc89..6794349e26 100644 --- a/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch +++ b/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c -@@ -469,7 +469,11 @@ static int fq_codel_init(struct Qdisc *s +@@ -461,7 +461,11 @@ static int fq_codel_init(struct Qdisc *s sch->limit = 10*1024; q->flows_cnt = 1024; diff --git a/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch b/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch index b90e1fc441..560937a7c1 100644 --- a/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch +++ b/target/linux/generic/hack-5.15/700-swconfig_switch_drivers.patch @@ -38,7 +38,6 @@ Signed-off-by: Felix Fietkau +config AR8216_PHY + tristate "Driver for Atheros AR8216 switches" + select SWCONFIG -+ select ETHERNET_PACKET_MANGLE + +config AR8216_PHY_LEDS + bool "Atheros AR8216 switch LED support" @@ -53,6 +52,7 @@ Signed-off-by: Felix Fietkau +config PSB6970_PHY + tristate "Lantiq XWAY Tantos (PSB6970) Ethernet switch" + select SWCONFIG ++ select ETHERNET_PACKET_MANGLE + +config RTL8306_PHY + tristate "Driver for Realtek RTL8306S switches" diff --git a/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch b/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch index 03725653f9..f301cc1e2d 100644 --- a/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch +++ b/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch @@ -1,6 +1,6 @@ --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -2097,6 +2097,7 @@ static int mv88e6xxx_port_fdb_add(struct +@@ -2088,6 +2088,7 @@ static int mv88e6xxx_port_fdb_add(struct struct mv88e6xxx_chip *chip = ds->priv; int err; @@ -8,7 +8,7 @@ mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); -@@ -2111,6 +2112,7 @@ static int mv88e6xxx_port_fdb_del(struct +@@ -2102,6 +2103,7 @@ static int mv88e6xxx_port_fdb_del(struct struct mv88e6xxx_chip *chip = ds->priv; int err; diff --git a/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch index 68cac73935..46a1ba1d96 100644 --- a/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch +++ b/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch @@ -1,6 +1,6 @@ --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -2659,6 +2659,9 @@ static int mv88e6xxx_setup_port(struct m +@@ -2650,6 +2650,9 @@ static int mv88e6xxx_setup_port(struct m if (dsa_is_cpu_port(ds, port)) reg = 0; diff --git a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch index 67808c35f8..e36d829ac5 100644 --- a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch @@ -19,22 +19,33 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1618,6 +1618,7 @@ enum netdev_priv_flags { - IFF_FAILOVER_SLAVE = 1<<28, - IFF_L3MDEV_RX_HANDLER = 1<<29, +@@ -1618,6 +1618,10 @@ enum netdev_priv_flags { IFF_LIVE_RENAME_OK = 1<<30, -+ IFF_NO_IP_ALIGN = 1<<31, + IFF_TX_SKB_NO_LINEAR = 1<<31, }; ++ ++enum netdev_extra_priv_flags { ++ IFF_NO_IP_ALIGN = 1<<0, ++}; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN + #define IFF_EBRIDGE IFF_EBRIDGE @@ -1650,6 +1651,7 @@ enum netdev_priv_flags { - #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK + #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR +#define IFF_NO_IP_ALIGN IFF_NO_IP_ALIGN /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { +@@ -1987,6 +1987,7 @@ enum netdev_priv_flags { + /* Read-mostly cache-line for fast-path access */ + unsigned int flags; + unsigned int priv_flags; ++ unsigned int extra_priv_flags; + const struct net_device_ops *netdev_ops; + int ifindex; + unsigned short gflags; @@ -1990,6 +1992,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -120,9 +131,9 @@ Signed-off-by: Felix Fietkau --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -60,6 +60,7 @@ - #include #include #include + #include +#include #include @@ -137,7 +148,7 @@ Signed-off-by: Felix Fietkau + struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); + +#ifdef CONFIG_ETHERNET_PACKET_MANGLE -+ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN)) ++ if (dev && (dev->extra_priv_flags & IFF_NO_IP_ALIGN)) + return skb; +#endif + diff --git a/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch index bc377bdd82..5a7e38516c 100644 --- a/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch @@ -14,7 +14,7 @@ Signed-off-by: Hauke Mehrtens --- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c -@@ -280,6 +280,7 @@ static int bgmac_probe(struct bcma_devic +@@ -266,6 +266,7 @@ static int bgmac_probe(struct bcma_devic bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; diff --git a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch index 247b50d536..b0e1661019 100644 --- a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch @@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau --- a/net/Kconfig +++ b/net/Kconfig -@@ -104,6 +104,9 @@ source "net/mptcp/Kconfig" +@@ -98,6 +98,9 @@ source "net/mptcp/Kconfig" endif # if INET @@ -74,10 +74,10 @@ Signed-off-by: Felix Fietkau + } +} + - struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) - { - struct dst_entry *dst = __sk_dst_get(sk); -@@ -1834,9 +1848,11 @@ static void __sk_free(struct sock *sk) + INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, + u32)); + INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, +@@ -1816,9 +1830,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch index 54e78cedc8..b2fdc0991e 100644 --- a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch @@ -24,17 +24,15 @@ Signed-off-by: Felix Fietkau help --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile -@@ -1,4 +1,4 @@ +@@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 --obj-y += heap-helpers.o -obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o -obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o -+dma-buf-objs-y += heap-helpers.o +dma-buf-objs-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +dma-buf-objs-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile -@@ -1,15 +1,19 @@ +@@ -1,16 +1,20 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \ +obj-$(CONFIG_DMA_SHARED_BUFFER) := dma-shared-buffer.o @@ -46,11 +44,13 @@ Signed-off-by: Felix Fietkau -obj-$(CONFIG_SYNC_FILE) += sync_file.o -obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o -obj-$(CONFIG_UDMABUF) += udmabuf.o +-obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o +dma-buf-objs-$(CONFIG_DMABUF_HEAPS) += dma-heap.o +obj-$(CONFIG_DMABUF_HEAPS) += heaps/ +dma-buf-objs-$(CONFIG_SYNC_FILE) += sync_file.o +dma-buf-objs-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o +dma-buf-objs-$(CONFIG_UDMABUF) += udmabuf.o ++dma-buf-objs-$(CONFIG_DMABUF_SYSFS_STATS) += udmabuf.o dmabuf_selftests-y := \ selftest.o \ From 483503603cb210919088294051e6d27de1f03718 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Fri, 5 Nov 2021 00:48:27 +0100 Subject: [PATCH 08/26] generic: 5.15: rework pending patch Rework pending patch for kernel 5.15 Signed-off-by: Ansuel Smith --- ...include-asm-rwonce.h-for-kernel-code.patch | 4 +- ...0-add-linux-spidev-compatible-si3210.patch | 4 +- ...ame2-and-add-RENAME_WHITEOUT-support.patch | 27 +++--- ...41-jffs2-add-RENAME_EXCHANGE-support.patch | 2 +- .../270-platform-mikrotik-build-bits.patch | 6 +- .../pending-5.15/305-mips_module_reloc.patch | 6 +- ...CPU-option-reporting-to-proc-cpuinfo.patch | 6 +- ...t-command-line-parameters-from-users.patch | 8 +- ...ers-ofpart-fix-parsing-subpartitions.patch | 76 --------------- .../pending-5.15/420-mtd-redboot_space.patch | 4 +- ...mtd-add-routerbootpart-parser-config.patch | 8 +- ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 6 +- .../530-jffs2_make_lzma_available.patch | 2 +- ...-netfilter_optional_tcp_window_check.patch | 6 +- ...ng-with-source-address-failed-policy.patch | 8 +- ...et-add-mac-address-increment-support.patch | 6 +- ...83-of_net-add-mac-address-to-of-tree.patch | 4 +- ...detach-callback-to-struct-phy_driver.patch | 2 +- ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 31 +++--- ...net-phy-at803x-fix-feature-detection.patch | 66 ------------- ...hdev-Refactor-br_switchdev_fdb_notif.patch | 77 --------------- ...hdev-Include-local-flag-in-FDB-notif.patch | 42 -------- ...hdev-Send-FDB-notifications-for-host.patch | 96 ------------------- ...local-addresses-in-assisted-CPU-port.patch | 36 ------- ...bridge-addresses-in-assisted-CPU-por.patch | 30 ------ ...tic-FDB-entries-on-foreign-interface.patch | 56 ----------- ...ice-struct-copy-its-DMA-params-to-th.patch | 15 ++- .../810-pci_disable_common_quirks.patch | 6 +- .../pending-5.15/834-ledtrig-libata.patch | 2 +- ...ck-return-value-of-generic_handle_do.patch | 6 +- .../pending-5.15/920-mangle_bootargs.patch | 2 +- 31 files changed, 89 insertions(+), 561 deletions(-) delete mode 100644 target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch delete mode 100644 target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch delete mode 100644 target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch delete mode 100644 target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch delete mode 100644 target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch delete mode 100644 target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch delete mode 100644 target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch delete mode 100644 target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch diff --git a/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch index 282c8196e5..39b98eac1b 100644 --- a/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch +++ b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/compiler.h +++ b/include/linux/compiler.h -@@ -213,6 +213,8 @@ void ftrace_likely_update(struct ftrace_ +@@ -211,6 +211,8 @@ void ftrace_likely_update(struct ftrace_ __v; \ }) @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau #endif /* __KERNEL__ */ /* -@@ -245,6 +247,4 @@ static inline void *offset_to_ptr(const +@@ -243,6 +245,4 @@ static inline void *offset_to_ptr(const */ #define prevent_tail_call_optimization() mb() diff --git a/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch b/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch index 355e900a3b..ca7b8a6bb1 100644 --- a/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch +++ b/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch @@ -9,9 +9,9 @@ Signed-off-by: Giuseppe Lippolis --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -682,6 +682,7 @@ static const struct of_device_id spidev_ - { .compatible = "lwn,bk4" }, - { .compatible = "dh,dhcom-board" }, { .compatible = "menlo,m53cpld" }, + { .compatible = "cisco,spi-petra" }, + { .compatible = "micron,spi-authenta" }, + { .compatible = "siliconlabs,si3210" }, {}, }; diff --git a/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch index e48da41fae..61e133e382 100644 --- a/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch +++ b/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch @@ -8,13 +8,14 @@ Signed-off-by: Felix Fietkau --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c -@@ -609,7 +609,8 @@ static int jffs2_rmdir (struct inode *di +@@ -609,8 +609,8 @@ static int jffs2_rmdir (struct inode *di return ret; } --static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev) -+static int __jffs2_mknod (struct inode *dir_i, struct dentry *dentry, -+ umode_t mode, dev_t rdev, bool whiteout) +-static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, +- struct dentry *dentry, umode_t mode, dev_t rdev) ++static int __jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, ++ struct dentry *dentry, umode_t mode, dev_t rdev, bool whiteout) { struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; @@ -31,24 +32,26 @@ Signed-off-by: Felix Fietkau return 0; fail: -@@ -756,6 +761,17 @@ static int jffs2_mknod (struct inode *di +@@ -756,6 +761,19 @@ static int jffs2_mknod (struct inode *di return ret; } -+static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev) ++static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, ++ struct dentry *dentry, umode_t mode, dev_t rdev) +{ -+ return __jffs2_mknod(dir_i, dentry, mode, rdev, false); ++ return __jffs2_mknod(mnt_userns, dir_i, dentry, mode, rdev, false); +} + -+static int jffs2_whiteout (struct inode *old_dir, struct dentry *old_dentry) ++static int jffs2_whiteout (struct user_namespace *mnt_userns, struct inode *old_dir, ++ struct dentry *old_dentry) +{ -+ return __jffs2_mknod(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, ++ return __jffs2_mknod(mnt_userns, old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, + WHITEOUT_DEV, true); +} + - static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, + static int jffs2_rename (struct user_namespace *mnt_userns, + struct inode *old_dir_i, struct dentry *old_dentry, struct inode *new_dir_i, struct dentry *new_dentry, - unsigned int flags) @@ -766,7 +782,7 @@ static int jffs2_rename (struct inode *o uint8_t type; uint32_t now; @@ -67,7 +70,7 @@ Signed-off-by: Felix Fietkau - old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); + if (flags & RENAME_WHITEOUT) + /* Replace with whiteout */ -+ ret = jffs2_whiteout(old_dir_i, old_dentry); ++ ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); + else + /* Unlink the original */ + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), diff --git a/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch b/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch index dbc72339c6..7dc830ac37 100644 --- a/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch +++ b/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch @@ -52,7 +52,7 @@ Signed-off-by: Felix Fietkau @@ -851,6 +864,12 @@ static int jffs2_rename (struct inode *o if (flags & RENAME_WHITEOUT) /* Replace with whiteout */ - ret = jffs2_whiteout(old_dir_i, old_dentry); + ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); + else if (flags & RENAME_EXCHANGE) + /* Replace the original */ + ret = jffs2_do_link(c, JFFS2_INODE_INFO(old_dir_i), diff --git a/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch b/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch index df738ef97b..3fd5c6e95d 100644 --- a/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch +++ b/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch @@ -17,15 +17,15 @@ Signed-off-by: Thibaut VARÈNE --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -13,3 +13,5 @@ source "drivers/platform/chrome/Kconfig" - source "drivers/platform/mellanox/Kconfig" - source "drivers/platform/olpc/Kconfig" + + source "drivers/platform/surface/Kconfig" + +source "drivers/platform/mikrotik/Kconfig" --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_MIPS) += mips/ - obj-$(CONFIG_OLPC_EC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ + obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ +obj-$(CONFIG_MIKROTIK) += mikrotik/ diff --git a/target/linux/generic/pending-5.15/305-mips_module_reloc.patch b/target/linux/generic/pending-5.15/305-mips_module_reloc.patch index 839ba24293..153c463ca0 100644 --- a/target/linux/generic/pending-5.15/305-mips_module_reloc.patch +++ b/target/linux/generic/pending-5.15/305-mips_module_reloc.patch @@ -270,7 +270,7 @@ Signed-off-by: Felix Fietkau static int apply_r_mips_none(struct module *me, u32 *location, u32 base, Elf_Addr v, bool rela) @@ -54,9 +261,40 @@ static int apply_r_mips_32(struct module - return 0; + *location = base + v; } +static Elf_Addr add_plt_entry_to(unsigned *plt_offset, @@ -302,8 +302,8 @@ Signed-off-by: Felix Fietkau + +} + - static int apply_r_mips_26(struct module *me, u32 *location, - u32 base, Elf_Addr v, bool rela) + static int apply_r_mips_26(struct module *me, u32 *location, u32 base, + Elf_Addr v) { + u32 ofs = base & 0x03ffffff; + diff --git a/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch b/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch index 794f027f18..318c0b1b25 100644 --- a/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch +++ b/target/linux/generic/pending-5.15/309-MIPS-Add-CPU-option-reporting-to-proc-cpuinfo.patch @@ -17,7 +17,7 @@ Signed-off-by: Hauke Mehrtens --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c -@@ -138,6 +138,120 @@ static int show_cpuinfo(struct seq_file +@@ -138,6 +138,116 @@ static int show_cpuinfo(struct seq_file seq_printf(m, "micromips kernel\t: %s\n", (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no"); } @@ -45,10 +45,6 @@ Signed-off-by: Hauke Mehrtens + seq_printf(m, "%s", " 3k_cache"); + if (cpu_has_4k_cache) + seq_printf(m, "%s", " 4k_cache"); -+ if (cpu_has_6k_cache) -+ seq_printf(m, "%s", " 6k_cache"); -+ if (cpu_has_8k_cache) -+ seq_printf(m, "%s", " 8k_cache"); + if (cpu_has_tx39_cache) + seq_printf(m, "%s", " tx39_cache"); + if (cpu_has_octeon_cache) diff --git a/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch index 2808c95322..91e4b91149 100644 --- a/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch +++ b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch @@ -238,12 +238,14 @@ Signed-off-by: Yousong Zhou +#endif --- a/arch/mips/kernel/relocate_kernel.S +++ b/arch/mips/kernel/relocate_kernel.S -@@ -10,8 +10,9 @@ +@@ -10,10 +10,11 @@ #include #include #include +#include "machine_kexec.h" + #include + -LEAF(relocate_new_kernel) +LEAF(kexec_relocate_new_kernel) PTR_L a0, arg0 @@ -259,7 +261,7 @@ Signed-off-by: Yousong Zhou #ifdef CONFIG_SMP /* @@ -182,9 +183,15 @@ kexec_indirection_page: - PTR 0 + PTR_WD 0 .size kexec_indirection_page, PTRSIZE -relocate_new_kernel_end: @@ -275,7 +277,7 @@ Signed-off-by: Yousong Zhou -relocate_new_kernel_size: - EXPORT(relocate_new_kernel_size) -- PTR relocate_new_kernel_end - relocate_new_kernel +- PTR_WD relocate_new_kernel_end - relocate_new_kernel - .size relocate_new_kernel_size, PTRSIZE +kexec_relocate_new_kernel_end: + EXPORT(kexec_relocate_new_kernel_end) diff --git a/target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch b/target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch deleted file mode 100644 index 353fa96748..0000000000 --- a/target/linux/generic/pending-5.15/410-mtd-parsers-ofpart-fix-parsing-subpartitions.patch +++ /dev/null @@ -1,76 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Thu, 6 May 2021 12:33:58 +0200 -Subject: [PATCH] mtd: parsers: ofpart: fix parsing subpartitions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -ofpart was recently patched to not scan random partition nodes as -subpartitions. That change unfortunately broke scanning valid -subpartitions like: - -partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - compatible = "fixed-partitions"; - label = "bootloader"; - reg = <0x0 0x100000>; - - partition@0 { - label = "config"; - reg = <0x80000 0x80000>; - }; - }; -}; - -Fix that regression by adding 1 more code path. We actually need 3 -conditional blocks to support 3 possible cases. This change also makes -code easier to understand & follow. - -Reported-by: David Bauer -Fixes: 2d751203aacf ("mtd: parsers: ofpart: limit parsing of deprecated DT syntax -Signed-off-by: Rafał Miłecki ---- - drivers/mtd/parsers/ofpart_core.c | 26 ++++++++++++++------------ - 1 file changed, 14 insertions(+), 12 deletions(-) - ---- a/drivers/mtd/parsers/ofpart_core.c -+++ b/drivers/mtd/parsers/ofpart_core.c -@@ -57,20 +57,22 @@ static int parse_fixed_partitions(struct - if (!mtd_node) - return 0; - -- ofpart_node = of_get_child_by_name(mtd_node, "partitions"); -- if (!ofpart_node && !master->parent) { -- /* -- * We might get here even when ofpart isn't used at all (e.g., -- * when using another parser), so don't be louder than -- * KERN_DEBUG -- */ -- pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", -- master->name, mtd_node); -+ if (!master->parent) { /* Master */ -+ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); -+ if (!ofpart_node) { -+ /* -+ * We might get here even when ofpart isn't used at all (e.g., -+ * when using another parser), so don't be louder than -+ * KERN_DEBUG -+ */ -+ pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", -+ master->name, mtd_node); -+ ofpart_node = mtd_node; -+ dedicated = false; -+ } -+ } else { /* Partition */ - ofpart_node = mtd_node; -- dedicated = false; - } -- if (!ofpart_node) -- return 0; - - of_id = of_match_node(parse_ofpart_match_table, ofpart_node); - if (dedicated && !of_id) { diff --git a/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch index a3cd4ecf1f..2673d720e5 100644 --- a/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch +++ b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch @@ -16,9 +16,9 @@ Signed-off-by: Felix Fietkau names += strlen(names)+1; -#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED - if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { + if (fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { - i++; -- parts[i].offset = parts[i-1].size + parts[i-1].offset; +- parts[i].offset = parts[i - 1].size + parts[i - 1].offset; - parts[i].size = fl->next->img->flash_base - parts[i].offset; - parts[i].name = nullname; - } diff --git a/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch index ab1e09a5f1..b258256db6 100644 --- a/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch +++ b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch @@ -17,9 +17,9 @@ Signed-off-by: Thibaut VARÈNE --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -195,3 +195,12 @@ config MTD_REDBOOT_PARTS_READONLY - 'FIS directory' images, enable this option. - - endif # MTD_REDBOOT_PARTS + help + This provides support for parsing partitions from Shared Memory (SMEM) + for NAND and SPI flash on Qualcomm platforms. + +config MTD_ROUTERBOOT_PARTS + tristate "RouterBoot flash partition parser" @@ -32,7 +32,7 @@ Signed-off-by: Thibaut VARÈNE --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o + obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o +obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o diff --git a/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch index e3c4dd2ef4..0efff2b52f 100644 --- a/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +++ b/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -48,6 +48,6 @@ Signed-off-by: Daniel Golle + if (!mount_ubi_rootfs()) + return; +#endif - #ifdef CONFIG_BLOCK - { - int err = create_dev("/dev/root", ROOT_DEV); + if (ROOT_DEV == 0 && root_device_name && root_fs_names) { + if (mount_nodev_root() == 0) + return; diff --git a/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch index 20483a391d..a648b6c545 100644 --- a/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch +++ b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch @@ -351,7 +351,7 @@ Signed-off-by: Alexandros C. Couloumbis + LZMA_FREE(address); +} + -+static ISzAlloc lzma_alloc = { .Alloc = p_lzma_malloc, .Free = p_lzma_free }; ++static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free}; + +#endif --- /dev/null diff --git a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch index 97e449510d..284ec073ef 100644 --- a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch +++ b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch @@ -15,9 +15,9 @@ Signed-off-by: Felix Fietkau +/* Do not check the TCP window for incoming packets */ +static int nf_ct_tcp_no_window_check __read_mostly = 1; + - /* "Be conservative in what you do, - be liberal in what you accept from others." - If it's non-zero, we mark only out of window RST segments as INVALID. */ + /* FIXME: Examine ipfilter's timeouts and conntrack transitions more + closely. They're more complex. --RR */ + @@ -476,6 +479,9 @@ static bool tcp_in_window(const struct n s32 receiver_offset; bool res, in_recv_win; diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index d85735531b..f3e7eae0ea 100644 --- a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -110,7 +110,7 @@ Signed-off-by: Jonas Gorski return -EINVAL; --- a/net/ipv6/route.c +++ b/net/ipv6/route.c -@@ -95,6 +95,8 @@ static int ip6_pkt_discard(struct sk_bu +@@ -94,6 +94,8 @@ static int ip6_pkt_discard(struct sk_bu static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); static int ip6_pkt_prohibit(struct sk_buff *skb); static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb); @@ -119,7 +119,7 @@ Signed-off-by: Jonas Gorski static void ip6_link_failure(struct sk_buff *skb); static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, -@@ -310,6 +312,18 @@ static const struct rt6_info ip6_prohibi +@@ -309,6 +311,18 @@ static const struct rt6_info ip6_prohibi .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), }; @@ -138,7 +138,7 @@ Signed-off-by: Jonas Gorski static const struct rt6_info ip6_blk_hole_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), -@@ -1031,6 +1045,7 @@ static const int fib6_prop[RTN_MAX + 1] +@@ -1030,6 +1044,7 @@ static const int fib6_prop[RTN_MAX + 1] [RTN_BLACKHOLE] = -EINVAL, [RTN_UNREACHABLE] = -EHOSTUNREACH, [RTN_PROHIBIT] = -EACCES, @@ -146,7 +146,7 @@ Signed-off-by: Jonas Gorski [RTN_THROW] = -EAGAIN, [RTN_NAT] = -EINVAL, [RTN_XRESOLVE] = -EINVAL, -@@ -1066,6 +1081,10 @@ static void ip6_rt_init_dst_reject(struc +@@ -1065,6 +1080,10 @@ static void ip6_rt_init_dst_reject(struc rt->dst.output = ip6_pkt_prohibit_out; rt->dst.input = ip6_pkt_prohibit; break; diff --git a/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch b/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch index 82e81f37c5..2753c76d54 100644 --- a/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch +++ b/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch @@ -15,11 +15,11 @@ early has to be increased. Signed-off-by: Ansuel Smith --- - drivers/of/of_net.c | 43 +++++++++++++++++++++++++++++++++++++++---- + net/core/of_net.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c +--- a/net/core/of_net.c ++++ b/net/core/of_net.c @@ -115,27 +115,62 @@ static int of_get_mac_addr_nvmem(struct * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists * but is all zeros. diff --git a/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch index 03cd763d9d..59dc30bb47 100644 --- a/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch +++ b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch @@ -1,5 +1,5 @@ ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c +--- a/net/core/of_net.c ++++ b/net/core/of_net.c @@ -95,6 +95,27 @@ static int of_get_mac_addr_nvmem(struct return 0; } diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch index 52350ecccc..9aa54082a5 100644 --- a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -765,6 +765,12 @@ struct phy_driver { +@@ -761,6 +761,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch index ecd6e9e7a2..262f1aa35b 100644 --- a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch +++ b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -15,10 +15,10 @@ Signed-off-by: Felix Fietkau --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -56,6 +56,7 @@ struct br_ip_list { - #define BR_MRP_AWARE BIT(17) #define BR_MRP_LOST_CONT BIT(18) #define BR_MRP_LOST_IN_CONT BIT(19) -+#define BR_BPDU_FILTER BIT(20) + #define BR_TX_FWD_OFFLOAD BIT(20) ++#define BR_BPDU_FILTER BIT(21) #define BR_DEFAULT_AGEING_TIME (300 * HZ) @@ -107,9 +107,9 @@ Signed-off-by: Felix Fietkau --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -524,6 +524,7 @@ enum { - IFLA_BRPORT_BACKUP_PORT, - IFLA_BRPORT_MRP_RING_OPEN, IFLA_BRPORT_MRP_IN_OPEN, + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, + IFLA_BRPORT_BPDU_FILTER, __IFLA_BRPORT_MAX }; @@ -135,32 +135,29 @@ Signed-off-by: Felix Fietkau timerval = br_timer_value(&p->message_age_timer); @@ -728,6 +730,7 @@ static const struct nla_policy br_port_p - [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 }, [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, + [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NLA_U32 }, + [IFLA_BRPORT_BPDU_FILTER] = { .type = NLA_U8 }, }; /* Change the state of the port and notify spanning tree */ -@@ -826,6 +829,10 @@ static int br_setport(struct net_bridge_ - if (err) - return err; +@@ -826,6 +829,7 @@ static int br_setport(struct net_bridge_ + br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); + br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, BR_NEIGH_SUPPRESS); + br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); ++ br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); + + changed_mask = old_flags ^ p->flags; -+ err = br_set_port_flag(p, tb, IFLA_BRPORT_BPDU_FILTER, BR_BPDU_FILTER); -+ if (err) -+ return err; -+ - br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false; - err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); - if (err) --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -55,7 +55,7 @@ #include #define RTNL_MAX_TYPE 50 --#define RTNL_SLAVE_MAX_TYPE 36 -+#define RTNL_SLAVE_MAX_TYPE 37 +-#define RTNL_SLAVE_MAX_TYPE 40 ++#define RTNL_SLAVE_MAX_TYPE 41 struct rtnl_link { rtnl_doit_func doit; diff --git a/target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch b/target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch deleted file mode 100644 index c49bb19601..0000000000 --- a/target/linux/generic/pending-5.15/730-net-phy-at803x-fix-feature-detection.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 97ca310aa18a93329ef5cd68c20de89761962f45 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Sun, 13 Jun 2021 12:19:36 +0200 -Subject: [PATCH] net: phy: at803x: fix feature detection - -AR8031/AR8033 have different status registers for copper -and fiber operation. However, the extended status register -is the same for both operation modes. - -As a result of that, ESTATUS_1000_XFULL is set to 1 even when -operating in copper TP mode. - -Remove this mode from the supported link modes, as this driver -currently only supports copper operation. - -Signed-off-by: David Bauer ---- - drivers/net/phy/at803x.c | 30 +++++++++++++++++++++++++++++- - 1 file changed, 29 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/at803x.c -+++ b/drivers/net/phy/at803x.c -@@ -1032,6 +1032,34 @@ static int at803x_set_tunable(struct phy - } - } - -+static int at803x_get_features(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = genphy_read_abilities(phydev); -+ if (err) -+ return err; -+ -+ if (!at803x_match_phy_id(phydev, ATH8031_PHY_ID)) -+ return 0; -+ -+ /* AR8031/AR8033 have different status registers -+ * for copper and fiber operation. However, the -+ * extended status register is the same for both -+ * operation modes. -+ * -+ * As a result of that, ESTATUS_1000_XFULL is set -+ * to 1 even when operating in copper TP mode. -+ * -+ * Remove this mode from the supported link modes, -+ * as this driver currently only supports copper -+ * operation. -+ */ -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->supported); -+ return 0; -+} -+ - static int at803x_cable_test_result_trans(u16 status) - { - switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { -@@ -1364,7 +1392,7 @@ static struct phy_driver at803x_driver[] - .resume = at803x_resume, - .read_page = at803x_read_page, - .write_page = at803x_write_page, -- /* PHY_GBIT_FEATURES */ -+ .get_features = at803x_get_features, - .read_status = at803x_read_status, - .aneg_done = at803x_aneg_done, - .ack_interrupt = &at803x_ack_interrupt, diff --git a/target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch b/target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch deleted file mode 100644 index fbc8342b0e..0000000000 --- a/target/linux/generic/pending-5.15/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 46fe6cecb296d850c1ee2b333e57093ac4b733f3 Mon Sep 17 00:00:00 2001 -From: Tobias Waldekranz -Date: Sat, 16 Jan 2021 02:25:09 +0100 -Subject: [PATCH] net: bridge: switchdev: Refactor br_switchdev_fdb_notify - -Instead of having to add more and more arguments to -br_switchdev_fdb_call_notifiers, get rid of it and build the info -struct directly in br_switchdev_fdb_notify. - -Signed-off-by: Tobias Waldekranz -Reviewed-by: Vladimir Oltean ---- - net/bridge/br_switchdev.c | 41 +++++++++++---------------------------- - 1 file changed, 11 insertions(+), 30 deletions(-) - ---- a/net/bridge/br_switchdev.c -+++ b/net/bridge/br_switchdev.c -@@ -102,25 +102,16 @@ int br_switchdev_set_port_flag(struct ne - return 0; - } - --static void --br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, -- u16 vid, struct net_device *dev, -- bool added_by_user, bool offloaded) --{ -- struct switchdev_notifier_fdb_info info; -- unsigned long notifier_type; -- -- info.addr = mac; -- info.vid = vid; -- info.added_by_user = added_by_user; -- info.offloaded = offloaded; -- notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; -- call_switchdev_notifiers(notifier_type, dev, &info.info, NULL); --} -- - void - br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) - { -+ struct switchdev_notifier_fdb_info info = { -+ .addr = fdb->key.addr.addr, -+ .vid = fdb->key.vlan_id, -+ .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), -+ .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), -+ }; -+ - if (!fdb->dst) - return; - if (test_bit(BR_FDB_LOCAL, &fdb->flags)) -@@ -128,22 +119,12 @@ br_switchdev_fdb_notify(const struct net - - switch (type) { - case RTM_DELNEIGH: -- br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr, -- fdb->key.vlan_id, -- fdb->dst->dev, -- test_bit(BR_FDB_ADDED_BY_USER, -- &fdb->flags), -- test_bit(BR_FDB_OFFLOADED, -- &fdb->flags)); -+ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, -+ fdb->dst->dev, &info.info, NULL); - break; - case RTM_NEWNEIGH: -- br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr, -- fdb->key.vlan_id, -- fdb->dst->dev, -- test_bit(BR_FDB_ADDED_BY_USER, -- &fdb->flags), -- test_bit(BR_FDB_OFFLOADED, -- &fdb->flags)); -+ call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, -+ fdb->dst->dev, &info.info, NULL); - break; - } - } diff --git a/target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch b/target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch deleted file mode 100644 index 41374c88df..0000000000 --- a/target/linux/generic/pending-5.15/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch +++ /dev/null @@ -1,42 +0,0 @@ -From ec5be4f79026282925ae383caa431a8d41e3456a Mon Sep 17 00:00:00 2001 -From: Tobias Waldekranz -Date: Sat, 16 Jan 2021 02:25:10 +0100 -Subject: [PATCH] net: bridge: switchdev: Include local flag in FDB - notifications - -Some switchdev drivers, notably DSA, ignore all dynamically learned -address notifications (!added_by_user) as these are autonomously added -by the switch. Previously, such a notification was indistinguishable -from a local address notification. Include a local bit in the -notification so that the two classes can be discriminated. - -This allows DSA-like devices to add local addresses to the hardware -FDB (with the CPU as the destination), thereby avoiding flows towards -the CPU being flooded by the switch as unknown unicast. - -Signed-off-by: Tobias Waldekranz ---- - include/net/switchdev.h | 1 + - net/bridge/br_switchdev.c | 1 + - 2 files changed, 2 insertions(+) - ---- a/include/net/switchdev.h -+++ b/include/net/switchdev.h -@@ -224,6 +224,7 @@ struct switchdev_notifier_fdb_info { - const unsigned char *addr; - u16 vid; - u8 added_by_user:1, -+ local:1, - offloaded:1; - }; - ---- a/net/bridge/br_switchdev.c -+++ b/net/bridge/br_switchdev.c -@@ -109,6 +109,7 @@ br_switchdev_fdb_notify(const struct net - .addr = fdb->key.addr.addr, - .vid = fdb->key.vlan_id, - .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), -+ .local = test_bit(BR_FDB_LOCAL, &fdb->flags), - .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), - }; - diff --git a/target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch b/target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch deleted file mode 100644 index 630e03bbfd..0000000000 --- a/target/linux/generic/pending-5.15/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 2e50fd9322047253c327550b4485cf8761035a8c Mon Sep 17 00:00:00 2001 -From: Tobias Waldekranz -Date: Sat, 16 Jan 2021 02:25:11 +0100 -Subject: [PATCH] net: bridge: switchdev: Send FDB notifications for host - addresses - -Treat addresses added to the bridge itself in the same way as regular -ports and send out a notification so that drivers may sync it down to -the hardware FDB. - -Signed-off-by: Tobias Waldekranz ---- - net/bridge/br_fdb.c | 4 ++-- - net/bridge/br_private.h | 7 ++++--- - net/bridge/br_switchdev.c | 11 +++++------ - 3 files changed, 11 insertions(+), 11 deletions(-) - ---- a/net/bridge/br_fdb.c -+++ b/net/bridge/br_fdb.c -@@ -602,7 +602,7 @@ void br_fdb_update(struct net_bridge *br - /* fastpath: update of existing entry */ - if (unlikely(source != fdb->dst && - !test_bit(BR_FDB_STICKY, &fdb->flags))) { -- br_switchdev_fdb_notify(fdb, RTM_DELNEIGH); -+ br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH); - fdb->dst = source; - fdb_modified = true; - /* Take over HW learned entry */ -@@ -735,7 +735,7 @@ static void fdb_notify(struct net_bridge - int err = -ENOBUFS; - - if (swdev_notify) -- br_switchdev_fdb_notify(fdb, type); -+ br_switchdev_fdb_notify(br, fdb, type); - - skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); - if (skb == NULL) ---- a/net/bridge/br_private.h -+++ b/net/bridge/br_private.h -@@ -1525,8 +1525,8 @@ bool nbp_switchdev_allowed_egress(const - int br_switchdev_set_port_flag(struct net_bridge_port *p, - unsigned long flags, - unsigned long mask); --void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, -- int type); -+void br_switchdev_fdb_notify(struct net_bridge *br, -+ const struct net_bridge_fdb_entry *fdb, int type); - int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, - struct netlink_ext_ack *extack); - int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid); -@@ -1572,7 +1572,8 @@ static inline int br_switchdev_port_vlan - } - - static inline void --br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) -+br_switchdev_fdb_notify(struct net_bridge *br, -+ const struct net_bridge_fdb_entry *fdb, int type) - { - } - ---- a/net/bridge/br_switchdev.c -+++ b/net/bridge/br_switchdev.c -@@ -103,7 +103,8 @@ int br_switchdev_set_port_flag(struct ne - } - - void --br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) -+br_switchdev_fdb_notify(struct net_bridge *br, -+ const struct net_bridge_fdb_entry *fdb, int type) - { - struct switchdev_notifier_fdb_info info = { - .addr = fdb->key.addr.addr, -@@ -112,20 +113,19 @@ br_switchdev_fdb_notify(const struct net - .local = test_bit(BR_FDB_LOCAL, &fdb->flags), - .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), - }; -+ struct net_device *dev = fdb->dst ? fdb->dst->dev : br->dev; - -- if (!fdb->dst) -- return; - if (test_bit(BR_FDB_LOCAL, &fdb->flags)) - return; - - switch (type) { - case RTM_DELNEIGH: - call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, -- fdb->dst->dev, &info.info, NULL); -+ dev, &info.info, NULL); - break; - case RTM_NEWNEIGH: - call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, -- fdb->dst->dev, &info.info, NULL); -+ dev, &info.info, NULL); - break; - } - } diff --git a/target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch b/target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch deleted file mode 100644 index c0b4fd1d14..0000000000 --- a/target/linux/generic/pending-5.15/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch +++ /dev/null @@ -1,36 +0,0 @@ -From dd082716b43a3684b2f473ae5d1e76d1c076d86d Mon Sep 17 00:00:00 2001 -From: Tobias Waldekranz -Date: Sat, 16 Jan 2021 02:25:12 +0100 -Subject: [PATCH] net: dsa: Include local addresses in assisted CPU port - learning - -Add local addresses (i.e. the ports' MAC addresses) to the hardware -FDB when assisted CPU port learning is enabled. - -NOTE: The bridge's own MAC address is also "local". If that address is -not shared with any port, the bridge's MAC is not be added by this -functionality - but the following commit takes care of that case. - -Signed-off-by: Tobias Waldekranz ---- - net/dsa/slave.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2192,10 +2192,12 @@ static int dsa_slave_switchdev_event(str - fdb_info = ptr; - - if (dsa_slave_dev_check(dev)) { -- if (!fdb_info->added_by_user) -- return NOTIFY_OK; -- - dp = dsa_slave_to_port(dev); -+ -+ if (fdb_info->local && dp->ds->assisted_learning_on_cpu_port) -+ dp = dp->cpu_dp; -+ else if (!fdb_info->added_by_user) -+ return NOTIFY_OK; - } else { - /* Snoop addresses learnt on foreign interfaces - * bridged with us, for switches that don't diff --git a/target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch b/target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch deleted file mode 100644 index 0b644d8300..0000000000 --- a/target/linux/generic/pending-5.15/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0663ebde114a6fb2c28c622ba5212b302d4d2581 Mon Sep 17 00:00:00 2001 -From: Tobias Waldekranz -Date: Sat, 16 Jan 2021 02:25:13 +0100 -Subject: [PATCH] net: dsa: Include bridge addresses in assisted CPU port - learning - -Now that notifications are sent out for addresses added to the bridge -itself, extend DSA to include those addresses in the hardware FDB when -assisted CPU port learning is enabled. - -Signed-off-by: Tobias Waldekranz ---- - net/dsa/slave.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2206,7 +2206,11 @@ static int dsa_slave_switchdev_event(str - struct net_device *br_dev; - struct dsa_slave_priv *p; - -- br_dev = netdev_master_upper_dev_get_rcu(dev); -+ if (netif_is_bridge_master(dev)) -+ br_dev = dev; -+ else -+ br_dev = netdev_master_upper_dev_get_rcu(dev); -+ - if (!br_dev) - return NOTIFY_DONE; - diff --git a/target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch b/target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch deleted file mode 100644 index f71ea16b97..0000000000 --- a/target/linux/generic/pending-5.15/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 81e39fd78db82fb51b05fff309b9c521f1a0bc5a Mon Sep 17 00:00:00 2001 -From: Tobias Waldekranz -Date: Sat, 16 Jan 2021 02:25:14 +0100 -Subject: [PATCH] net: dsa: Sync static FDB entries on foreign interfaces to - hardware - -Reuse the "assisted_learning_on_cpu_port" functionality to always add -entries for user-configured entries on foreign interfaces, even if -assisted_learning_on_cpu_port is not enabled. E.g. in this situation: - - br0 - / \ -swp0 dummy0 - -$ bridge fdb add 02:00:de:ad:00:01 dev dummy0 vlan 1 master - -Results in DSA adding an entry in the hardware FDB, pointing this -address towards the CPU port. - -The same is true for entries added to the bridge itself, e.g: - -$ bridge fdb add 02:00:de:ad:00:01 dev br0 vlan 1 self - -Signed-off-by: Tobias Waldekranz ---- - net/dsa/slave.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -2199,9 +2199,12 @@ static int dsa_slave_switchdev_event(str - else if (!fdb_info->added_by_user) - return NOTIFY_OK; - } else { -- /* Snoop addresses learnt on foreign interfaces -- * bridged with us, for switches that don't -- * automatically learn SA from CPU-injected traffic -+ /* Snoop addresses added to foreign interfaces -+ * bridged with us, or the bridge -+ * itself. Dynamically learned addresses can -+ * also be added for switches that don't -+ * automatically learn SA from CPU-injected -+ * traffic. - */ - struct net_device *br_dev; - struct dsa_slave_priv *p; -@@ -2223,7 +2226,8 @@ static int dsa_slave_switchdev_event(str - - dp = p->dp->cpu_dp; - -- if (!dp->ds->assisted_learning_on_cpu_port) -+ if (!fdb_info->added_by_user && -+ !dp->ds->assisted_learning_on_cpu_port) - return NOTIFY_DONE; - } - diff --git a/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch index 511a9f7555..478a2cb27d 100644 --- a/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch +++ b/target/linux/generic/pending-5.15/800-bcma-get-SoC-device-struct-copy-its-DMA-params-to-th.patch @@ -50,14 +50,23 @@ Signed-off-by: Rafał Miłecki if (err) --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -241,8 +241,10 @@ void bcma_prepare_core(struct bcma_bus * +@@ -236,13 +236,17 @@ EXPORT_SYMBOL(bcma_core_irq); + + void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) + { +- device_initialize(&core->dev); ++ struct device *dev = &core->dev; ++ ++ device_initialize(dev); + core->dev.release = bcma_release_core_dev; core->dev.bus = &bcma_bus_type; - dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); +- dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); ++ dev_set_name(dev, "bcma%d:%d", bus->num, core->core_index); core->dev.parent = bus->dev; - if (bus->dev) + if (bus->dev) { bcma_of_fill_device(bus->dev, core); -+ dma_coerce_mask_and_coherent(&core->dev, bus->dev->coherent_dma_mask); ++ dma_coerce_mask_and_coherent(dev, bus->dev->coherent_dma_mask); + } switch (bus->hosttype) { diff --git a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch index 62f6fed126..f5e444fe46 100644 --- a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch +++ b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch @@ -33,7 +33,7 @@ Signed-off-by: Gabor Juhos /* * The Mellanox Tavor device gives false positive parity errors. Mark this * device with a broken_parity_status to allow PCI scanning code to "skip" -@@ -3323,6 +3324,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I +@@ -3322,6 +3323,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); @@ -42,7 +42,7 @@ Signed-off-by: Gabor Juhos /* * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. * To work around this, query the size it should be configured to by the -@@ -3348,6 +3351,8 @@ static void quirk_intel_ntb(struct pci_d +@@ -3347,6 +3350,8 @@ static void quirk_intel_ntb(struct pci_d DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); @@ -51,7 +51,7 @@ Signed-off-by: Gabor Juhos /* * Some BIOS implementations leave the Intel GPU interrupts enabled, even * though no one is handling them (e.g., if the i915 driver is never -@@ -3386,6 +3391,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN +@@ -3385,6 +3390,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); diff --git a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch index 25cffb1444..95212138b6 100644 --- a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch @@ -134,7 +134,7 @@ Signed-off-by: Daniel Golle /* * Define if arch has non-standard setup. This is a _PCI_ standard -@@ -883,6 +886,12 @@ struct ata_port { +@@ -882,6 +885,12 @@ struct ata_port { #ifdef CONFIG_ATA_ACPI struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ #endif diff --git a/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch b/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch index 9cc37f727e..355c835a6e 100644 --- a/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch +++ b/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch @@ -19,11 +19,11 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -1439,7 +1439,9 @@ static void advk_pcie_handle_int(struct + advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i), PCIE_ISR1_REG); - virq = irq_find_mapping(pcie->irq_domain, i); -- generic_handle_irq(virq); -+ if (generic_handle_irq(virq) == -EINVAL) +- generic_handle_domain_irq(pcie->irq_domain, i); ++ if (generic_handle_domain_irq(pcie->irq_domain, i) == -EINVAL) + dev_err_ratelimited(&pcie->pdev->dev, "unexpected INT%c IRQ\n", + (char)i + 'A'); } diff --git a/target/linux/generic/pending-5.15/920-mangle_bootargs.patch b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch index fc64a4205e..bd9de92000 100644 --- a/target/linux/generic/pending-5.15/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch @@ -66,6 +66,6 @@ Signed-off-by: Imre Kaloz early_security_init(); setup_arch(&command_line); + mangle_bootargs(command_line); - setup_boot_config(command_line); + setup_boot_config(); setup_command_line(command_line); setup_nr_cpu_ids(); From 92fb51bc98814958f4c4d69b6a397a17c83d62c6 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Sun, 7 Nov 2021 22:33:21 +0100 Subject: [PATCH 09/26] generic: 5.15: standardize tcp_no_window_check pending patch Standardize pending patch tcp_no_window_check patch as with new kernel they added a check for global variables. The 2 new condition are that they must be read-only or the data pointer should not point to kernel/module global data. Remove the global variable and move it to a standard place following other variables logic. Signed-off-by: Ansuel Smith --- ...-netfilter_optional_tcp_window_check.patch | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch index 284ec073ef..c7978e5881 100644 --- a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch +++ b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch @@ -8,21 +8,11 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -31,6 +31,9 @@ - #include - #include - -+/* Do not check the TCP window for incoming packets */ -+static int nf_ct_tcp_no_window_check __read_mostly = 1; -+ - /* FIXME: Examine ipfilter's timeouts and conntrack transitions more - closely. They're more complex. --RR */ - @@ -476,6 +479,9 @@ static bool tcp_in_window(const struct n s32 receiver_offset; bool res, in_recv_win; -+ if (nf_ct_tcp_no_window_check) ++ if (net->ct.sysctl_no_window_check) + return true; + /* @@ -33,22 +23,12 @@ Signed-off-by: Felix Fietkau timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) timeout = timeouts[TCP_CONNTRACK_UNACK]; - else if (ct->proto.tcp.last_win == 0 && -+ else if (!nf_ct_tcp_no_window_check && ct->proto.tcp.last_win == 0 && ++ else if (!net->ct.sysctl_no_window_check && ct->proto.tcp.last_win == 0 && timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS]) timeout = timeouts[TCP_CONNTRACK_RETRANS]; else --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c -@@ -25,6 +25,9 @@ - #include - #include - -+/* Do not check the TCP window for incoming packets */ -+static int nf_ct_tcp_no_window_check __read_mostly = 1; -+ - static bool enable_hooks __read_mostly; - MODULE_PARM_DESC(enable_hooks, "Always enable conntrack hooks"); - module_param(enable_hooks, bool, 0000); @@ -660,6 +663,7 @@ enum nf_ct_sysctl_index { NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM, #endif @@ -63,7 +43,7 @@ Signed-off-by: Felix Fietkau #endif + [NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK] = { + .procname = "nf_conntrack_tcp_no_window_check", -+ .data = &nf_ct_tcp_no_window_check, ++ .data = &init_net.ct.sysctl_no_window_check, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec, @@ -71,3 +51,29 @@ Signed-off-by: Felix Fietkau {} }; +@@ -1164,6 +1164,7 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) + #ifdef CONFIG_NF_CONNTRACK_EVENTS + table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events; + #endif ++ table[NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK].data = &net->ct.sysctl_no_window_check; + #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP + table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp; + #endif +@@ -1220,6 +1220,7 @@ + int ret; + + net->ct.sysctl_checksum = 1; ++ net->ct.sysctl_no_window_check = 1; + + ret = nf_conntrack_standalone_init_sysctl(net); + if (ret < 0) +--- a/include/net/netns/conntrack.h ++++ b/include/net/netns/conntrack.h +@@ -109,6 +109,7 @@ struct netns_ct { + u8 sysctl_auto_assign_helper; + u8 sysctl_tstamp; + u8 sysctl_checksum; ++ u8 sysctl_no_window_check; + + struct ct_pcpu __percpu *pcpu_lists; + struct ip_conntrack_stat __percpu *stat; From 7aa0f9365c825045b2c5c0cd9870e61bb76ae881 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Sun, 16 Jan 2022 19:38:18 +0100 Subject: [PATCH 10/26] generic: 5.15: fix affinity warning for qcom target Backport a patch from 5.18 that fix affinity warning from qcom pinctrl driver. Signed-off-by: Ansuel Smith --- ...or-setting-affinity-if-no-IRQ-parent.patch | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch diff --git a/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch b/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch new file mode 100644 index 0000000000..796ca74b4d --- /dev/null +++ b/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch @@ -0,0 +1,50 @@ +From: Manivannan Sadhasivam +To: linus.walleij@linaro.org +Cc: bjorn.andersson@linaro.org, dianders@chromium.org, + linux-arm-msm@vger.kernel.org, linux-gpio@vger.kernel.org, + linux-kernel@vger.kernel.org, + Manivannan Sadhasivam +Subject: [PATCH] pinctrl: qcom: Return -EINVAL for setting affinity if no IRQ + parent +Date: Thu, 13 Jan 2022 21:56:17 +0530 +Message-Id: <20220113162617.131697-1-manivannan.sadhasivam@linaro.org> + +The MSM GPIO IRQ controller relies on the parent IRQ controller to set the +CPU affinity for the IRQ. And this is only valid if there is any wakeup +parent available and defined in DT. + +For the case of no parent IRQ controller defined in DT, +msm_gpio_irq_set_affinity() and msm_gpio_irq_set_vcpu_affinity() should +return -EINVAL instead of 0 as the affinity can't be set. + +Otherwise, below warning will be printed by genirq: + +genirq: irq_chip msmgpio did not update eff. affinity mask of irq 70 + +Signed-off-by: Manivannan Sadhasivam +--- + drivers/pinctrl/qcom/pinctrl-msm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c +index 8476a8ac4451..a42ff4b22a04 100644 +--- a/drivers/pinctrl/qcom/pinctrl-msm.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm.c +@@ -1157,7 +1157,7 @@ static int msm_gpio_irq_set_affinity(struct irq_data *d, + if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs)) + return irq_chip_set_affinity_parent(d, dest, force); + +- return 0; ++ return -EINVAL; + } + + static int msm_gpio_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) +@@ -1168,7 +1168,7 @@ static int msm_gpio_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) + if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs)) + return irq_chip_set_vcpu_affinity_parent(d, vcpu_info); + +- return 0; ++ return -EINVAL; + } + + static void msm_gpio_irq_handler(struct irq_desc *desc) From 07b92c636a0160eb9a36bb00e5d4c0247381d7a2 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 4 Nov 2021 23:22:29 +0100 Subject: [PATCH 11/26] generic: 5.15: refresh config Refresh kernel 5.15 generic config file Signed-off-by: Ansuel Smith [added some missing Kconfig symbols] Signed-off-by: Daniel Golle --- target/linux/generic/config-5.15 | 190 ++++++++++++++++++++++++++++++- target/linux/mediatek/Makefile | 1 + 2 files changed, 187 insertions(+), 4 deletions(-) diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 578b8be764..3657304904 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -31,6 +31,7 @@ CONFIG_64BIT_TIME=y # CONFIG_AD2S1210 is not set # CONFIG_AD2S90 is not set # CONFIG_AD5064 is not set +# CONFIG_AD5110 is not set # CONFIG_AD525X_DPOT is not set # CONFIG_AD5272 is not set # CONFIG_AD5360 is not set @@ -51,6 +52,7 @@ CONFIG_64BIT_TIME=y # CONFIG_AD5764 is not set # CONFIG_AD5770R is not set # CONFIG_AD5791 is not set +# CONFIG_AD5766 is not set # CONFIG_AD5933 is not set # CONFIG_AD7091R5 is not set # CONFIG_AD7124 is not set @@ -178,12 +180,14 @@ CONFIG_ANON_INODES=y # CONFIG_ARCH_ACTIONS is not set # CONFIG_ARCH_AGILEX is not set # CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set # CONFIG_ARCH_ARTPEC is not set # CONFIG_ARCH_ASPEED is not set # CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_AXXIA is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM4908 is not set # CONFIG_ARCH_BCM_21664 is not set # CONFIG_ARCH_BCM_23550 is not set # CONFIG_ARCH_BCM_281XX is not set @@ -213,6 +217,7 @@ CONFIG_ARCH_FLATMEM_ENABLE=y # CONFIG_ARCH_HIGHBANK is not set # CONFIG_ARCH_HISI is not set # CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -388,10 +393,12 @@ CONFIG_ARM_DMA_MEM_BUFFERABLE=y # CONFIG_ARM_ERRATA_852423 is not set # CONFIG_ARM_ERRATA_857271 is not set # CONFIG_ARM_ERRATA_857272 is not set +# CONFIG_ARM_FFA_TRANSPORT is not set CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set # CONFIG_ARM_KPROBES_TEST is not set # CONFIG_ARM_LPAE is not set +# CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set # CONFIG_ARM_MHU is not set # CONFIG_ARM_MODULE_PLTS is not set # CONFIG_ARM_PATCH_PHYS_VIRT is not set @@ -565,6 +572,7 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_BCM_IPROC_ADC is not set # CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_BCM_SBA_RAID is not set +# CONFIG_BCM_VK is not set # CONFIG_BDI_SWITCH is not set # CONFIG_BE2ISCSI is not set # CONFIG_BE2NET is not set @@ -585,6 +593,7 @@ CONFIG_BINFMT_SCRIPT=y CONFIG_BITREVERSE=y # CONFIG_BLK_CGROUP_IOCOST is not set # CONFIG_BLK_CGROUP_IOLATENCY is not set +# CONFIG_BLK_CGROUP_IOPRIO is not set # CONFIG_BLK_CMDLINE_PARSER is not set # CONFIG_BLK_DEBUG_FS is not set CONFIG_BLK_DEV=y @@ -679,6 +688,7 @@ CONFIG_BLOCK=y # CONFIG_BMC150_MAGN_SPI is not set # CONFIG_BME680 is not set # CONFIG_BMG160 is not set +# CONFIG_BMI088_ACCEL is not set # CONFIG_BMI160_I2C is not set # CONFIG_BMI160_SPI is not set # CONFIG_BMIPS_GENERIC is not set @@ -714,6 +724,7 @@ CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_BRCMSMAC is not set # CONFIG_BRCMSTB_GISB_ARB is not set CONFIG_BRIDGE=y +# CONFIG_BRIDGE_CFM is not set # CONFIG_BRIDGE_EBT_802_3 is not set # CONFIG_BRIDGE_EBT_AMONG is not set # CONFIG_BRIDGE_EBT_ARP is not set @@ -853,6 +864,7 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CFG80211 is not set # CONFIG_CFG80211_CERTIFICATION_ONUS is not set # CONFIG_CGROUPS is not set +# CONFIG_CGROUP_MISC is not set # CONFIG_CHARGER_ADP5061 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_CHARGER_BQ2415X is not set @@ -860,6 +872,7 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CHARGER_BQ24257 is not set # CONFIG_CHARGER_BQ24735 is not set # CONFIG_CHARGER_BQ2515X is not set +# CONFIG_CHARGER_BQ256XX is not set # CONFIG_CHARGER_BQ25890 is not set # CONFIG_CHARGER_BQ25980 is not set # CONFIG_CHARGER_DETECTOR_MAX14656 is not set @@ -868,6 +881,7 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_LT3651 is not set # CONFIG_CHARGER_LTC3651 is not set +# CONFIG_CHARGER_LTC4162L is not set # CONFIG_CHARGER_MANAGER is not set # CONFIG_CHARGER_MAX8903 is not set # CONFIG_CHARGER_RT9455 is not set @@ -893,6 +907,7 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y # CONFIG_CIFS_DEBUG is not set # CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_SWN_UPCALL is not set # CONFIG_CIFS_FSCACHE is not set # CONFIG_CIFS_NFSD_EXPORT is not set CONFIG_CIFS_POSIX=y @@ -904,8 +919,10 @@ CONFIG_CIFS_XATTR=y # CONFIG_CIO_DAC is not set # CONFIG_CLEANCACHE is not set # CONFIG_CLKSRC_VERSATILE is not set +# CONFIG_CLK_GFM_LPASS_SM8250 is not set # CONFIG_CLK_HSDK is not set # CONFIG_CLK_QORIQ is not set +# CONFIG_CLK_SP810 is not set # CONFIG_CLOCK_THERMAL is not set CONFIG_CLS_U32_MARK=y # CONFIG_CLS_U32_PERF is not set @@ -925,6 +942,7 @@ CONFIG_CMDLINE="" # CONFIG_CODA_FS is not set # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_COMEDI is not set +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set # CONFIG_COMMON_CLK_CDCE706 is not set # CONFIG_COMMON_CLK_CDCE925 is not set # CONFIG_COMMON_CLK_CS2000_CP is not set @@ -938,6 +956,7 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_MT8167_MFGCFG is not set # CONFIG_COMMON_CLK_MT8167_MMSYS is not set # CONFIG_COMMON_CLK_MT8167_VDECSYS is not set +# CONFIG_COMMON_CLK_MT8192 is not set # CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PIC32 is not set # CONFIG_COMMON_CLK_PWM is not set @@ -1121,6 +1140,7 @@ CONFIG_CRYPTO_CTR=y # CONFIG_CRYPTO_DRBG_MENU is not set # CONFIG_CRYPTO_ECB is not set # CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set # CONFIG_CRYPTO_ECHAINIV is not set # CONFIG_CRYPTO_ECRDSA is not set # CONFIG_CRYPTO_ESSIV is not set @@ -1205,6 +1225,8 @@ CONFIG_CRYPTO_PCRYPT=y # CONFIG_CRYPTO_SHA512_ARM is not set # CONFIG_CRYPTO_SHA512_ARM64 is not set # CONFIG_CRYPTO_SHA512_ARM64_CE is not set +# CONFIG_CRYPTO_BLAKE2S_ARM is not set +# CONFIG_CRYPTO_BLAKE2B_NEON is not set # CONFIG_CRYPTO_SIMD is not set CONFIG_CRYPTO_SKCIPHER=y CONFIG_CRYPTO_SKCIPHER2=y @@ -1238,18 +1260,21 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_CRYPTO_ZSTD is not set # CONFIG_CS5535_MFGPT is not set # CONFIG_CS89x0 is not set +# CONFIG_CS89x0_PLATFORM is not set # CONFIG_CSD_LOCK_WAIT_DEBUG is not set # CONFIG_CUSE is not set # CONFIG_CW1200 is not set # CONFIG_CXD2880_SPI_DRV is not set # CONFIG_CXL_AFU_DRIVER_OPS is not set # CONFIG_CXL_BASE is not set +# CONFIG_CXL_BUS is not set # CONFIG_CXL_EEH is not set # CONFIG_CXL_KERNEL_API is not set # CONFIG_CXL_LIB is not set # CONFIG_CYPRESS_FIRMWARE is not set # CONFIG_DA280 is not set # CONFIG_DA311 is not set +# CONFIG_DAMON is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_DAX is not set # CONFIG_DCB is not set @@ -1263,6 +1288,7 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_EFI is not set # CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS_ALLOW_ALL=y @@ -1275,9 +1301,13 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_INFO_BTF is not set # CONFIG_DEBUG_INFO_COMPRESSED is not set # CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_INFO_REDUCED=y # CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_IRQFLAGS is not set CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KMAP_LOCAL is not set # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_KOBJECT_RELEASE is not set @@ -1396,9 +1426,11 @@ CONFIG_DMA_DECLARE_COHERENT=y # CONFIG_DMA_ENGINE is not set # CONFIG_DMA_FENCE_TRACE is not set # CONFIG_DMA_JZ4780 is not set +# CONFIG_DMA_MAP_BENCHMARK is not set CONFIG_DMA_NONCOHERENT_MMAP=y # CONFIG_DMA_NOOP_OPS is not set # CONFIG_DMA_PERNUMA_CMA is not set +# CONFIG_DMA_RESTRICTED_POOL is not set # CONFIG_DMA_SHARED_BUFFER is not set # CONFIG_DMA_VIRT_OPS is not set # CONFIG_DM_CACHE is not set @@ -1729,6 +1761,7 @@ CONFIG_DVB_MAX_ADAPTERS=16 # CONFIG_DWMAC_DWC_QOS_ETH is not set # CONFIG_DWMAC_INTEL_PLAT is not set # CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_LOONGSON is not set # CONFIG_DWMAC_LPC18XX is not set # CONFIG_DWMAC_MESON is not set # CONFIG_DWMAC_ROCKCHIP is not set @@ -1740,6 +1773,7 @@ CONFIG_DVB_MAX_ADAPTERS=16 # CONFIG_DW_EDMA is not set # CONFIG_DW_EDMA_PCIE is not set # CONFIG_DW_WATCHDOG is not set +# CONFIG_DW_XDATA_PCIE is not set # CONFIG_DYNAMIC_DEBUG is not set CONFIG_DYNAMIC_DEBUG_CORE=y # CONFIG_E100 is not set @@ -1828,6 +1862,7 @@ CONFIG_EXTRA_TARGETS="" # CONFIG_F2FS_FAULT_INJECTION is not set # CONFIG_F2FS_FS is not set # CONFIG_F2FS_FS_COMPRESSION is not set +# CONFIG_F2FS_IOSTAT is not set # CONFIG_F2FS_FS_ENCRYPTION is not set # CONFIG_F2FS_FS_POSIX_ACL is not set # CONFIG_F2FS_FS_SECURITY is not set @@ -2037,6 +2072,8 @@ CONFIG_FW_LOADER=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FXAS21002C is not set +# CONFIG_FXLS8962AF_I2C is not set +# CONFIG_FXLS8962AF_SPI is not set # CONFIG_FXOS8700_I2C is not set # CONFIG_FXOS8700_SPI is not set CONFIG_GACT_PROB=y @@ -2153,6 +2190,7 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GS_FPGABOOT is not set # CONFIG_GTP is not set # CONFIG_GUP_BENCHMARK is not set +# CONFIG_GUP_TEST is not set # CONFIG_GVE is not set # CONFIG_HABANA_AI is not set # CONFIG_HAMACHI is not set @@ -2183,6 +2221,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HFSPLUS_FS_POSIX_ACL is not set # CONFIG_HFS_FS is not set # CONFIG_HFS_FS_POSIX_ACL is not set +# CONFIG_HI6421V600_IRQ is not set # CONFIG_HI8435 is not set # CONFIG_HIBERNATION is not set # CONFIG_HID is not set @@ -2334,6 +2373,7 @@ CONFIG_HPET_MMAP_DEFAULT=y CONFIG_HW_PERF_EVENTS=y # CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_ARM_SMCCC_TRNG is not set # CONFIG_HW_RANDOM_ATMEL is not set # CONFIG_HW_RANDOM_BA431 is not set # CONFIG_HW_RANDOM_CAVIUM is not set @@ -2385,6 +2425,7 @@ CONFIG_HZ_100=y # CONFIG_I2C_CBUS_GPIO is not set # CONFIG_I2C_CHARDEV is not set # CONFIG_I2C_COMPAT is not set +# CONFIG_I2C_CP2615 is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -2400,6 +2441,8 @@ CONFIG_HZ_100=y # CONFIG_I2C_GPIO_FAULT_INJECTOR is not set # CONFIG_I2C_HELPER_AUTO is not set # CONFIG_I2C_HID is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_GOODIX is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_IBM_IIC is not set # CONFIG_I2C_IMG is not set @@ -2451,6 +2494,7 @@ CONFIG_HZ_100=y # CONFIG_I2C_VERSATILE is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VIRTIO is not set # CONFIG_I2C_XILINX is not set # CONFIG_I3C is not set # CONFIG_I40E is not set @@ -2472,6 +2516,7 @@ CONFIG_HZ_100=y # CONFIG_ICP10100 is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_ICS932S401 is not set +# CONFIG_ICST is not set # CONFIG_IDE is not set # CONFIG_IDEAPAD_LAPTOP is not set # CONFIG_IDE_GD is not set @@ -2507,6 +2552,7 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_IIO_ST_ACCEL_3AXIS is not set # CONFIG_IIO_ST_GYRO_3AXIS is not set # CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_ST_LSM9DS0 is not set # CONFIG_IIO_ST_MAGN_3AXIS is not set # CONFIG_IIO_ST_PRESS is not set # CONFIG_IIO_SW_DEVICE is not set @@ -2580,6 +2626,7 @@ CONFIG_INOTIFY_USER=y # CONFIG_INPUT_BMA150 is not set # CONFIG_INPUT_CM109 is not set # CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set # CONFIG_INPUT_DRV260X_HAPTICS is not set # CONFIG_INPUT_DRV2665_HAPTICS is not set # CONFIG_INPUT_DRV2667_HAPTICS is not set @@ -2596,6 +2643,7 @@ CONFIG_INOTIFY_USER=y # CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set # CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_KEYBOARD is not set @@ -2701,6 +2749,7 @@ CONFIG_IO_WQ=y # CONFIG_IPV6_FOU is not set # CONFIG_IPV6_FOU_TUNNEL is not set # CONFIG_IPV6_ILA is not set +# CONFIG_IPV6_IOAM6_LWTUNNEL is not set # CONFIG_IPV6_MIP6 is not set # CONFIG_IPV6_MROUTE is not set # CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set @@ -2857,7 +2906,7 @@ CONFIG_KALLSYMS_BASE_RELATIVE=y # CONFIG_KALLSYMS_UNCOMPRESSED is not set # CONFIG_KARMA_PARTITION is not set # CONFIG_KASAN is not set -CONFIG_KASAN_STACK=1 +CONFIG_KASAN_STACK=y # CONFIG_KCMP is not set # CONFIG_KCOV is not set # CONFIG_KCSAN is not set @@ -2913,6 +2962,7 @@ CONFIG_KERNFS=y # CONFIG_KEYS is not set # CONFIG_KEYS_REQUEST_CACHE is not set # CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_KFENCE is not set # CONFIG_KGDB is not set # CONFIG_KMEMCHECK is not set # CONFIG_KMX61 is not set @@ -3030,6 +3080,7 @@ CONFIG_LEDS_TRIGGER_NETDEV=y # CONFIG_LEDS_TRIGGER_PATTERN is not set CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_TTY is not set # CONFIG_LEDS_TURRIS_OMNIA is not set # CONFIG_LEDS_USER is not set # CONFIG_LED_TRIGGER_PHY is not set @@ -3053,9 +3104,12 @@ CONFIG_LINEAR_RANGES=y # CONFIG_LIQUIDIO is not set # CONFIG_LIQUIDIO_VF is not set # CONFIG_LIS3L02DQ is not set +# CONFIG_LITEX_LITEETH is not set +# CONFIG_LITEX_SOC_CONTROLLER is not set # CONFIG_LKDTM is not set CONFIG_LLC=y # CONFIG_LLC2 is not set +# CONFIG_LMK04832 is not set # CONFIG_LMP91000 is not set # CONFIG_LNET is not set CONFIG_LOCALVERSION="" @@ -3108,7 +3162,6 @@ CONFIG_LZMA_DECOMPRESS=y # CONFIG_MAC80211_MESSAGE_TRACING is not set CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 # CONFIG_MACB is not set -# CONFIG_MACB_USE_HWSTAMP is not set # CONFIG_MACH_ASM9260 is not set # CONFIG_MACH_DECSTATION is not set # CONFIG_MACH_INGENIC is not set @@ -3140,6 +3193,7 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MANDATORY_FILE_LOCKING is not set # CONFIG_MANGLE_BOOTARGS is not set # CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_88X2222_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_MAX1027 is not set # CONFIG_MAX11100 is not set @@ -3159,6 +3213,7 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MAX63XX_WATCHDOG is not set # CONFIG_MAX9611 is not set # CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MAXLINEAR_GPHY is not set CONFIG_MAY_USE_DEVLINK=y # CONFIG_MB1232 is not set # CONFIG_MC3230 is not set @@ -3173,6 +3228,7 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MCP4725 is not set # CONFIG_MCP4922 is not set # CONFIG_MCPM is not set +# CONFIG_MCTP is not set # CONFIG_MD is not set # CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MDIO_BITBANG is not set @@ -3189,6 +3245,7 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MDIO_OCTEON is not set # CONFIG_MDIO_THUNDER is not set # CONFIG_MDIO_XPCS is not set +# CONFIG_MDM_GCC_9607 is not set # CONFIG_MD_FAULTY is not set # CONFIG_MEDIATEK_GE_PHY is not set # CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set @@ -3268,6 +3325,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_AS3722 is not set # CONFIG_MFD_ASIC3 is not set +# CONFIG_MFD_ATC260X_I2C is not set # CONFIG_MFD_ATMEL_FLEXCOM is not set # CONFIG_MFD_ATMEL_HLCDC is not set # CONFIG_MFD_AXP20X is not set @@ -3289,6 +3347,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_GATEWORKS_GSC is not set # CONFIG_MFD_HI6421_PMIC is not set # CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_INTEL_PMT is not set # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_MFD_IQS62X is not set # CONFIG_MFD_JANZ_CMODIO is not set @@ -3315,11 +3374,13 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_MP2629 is not set # CONFIG_MFD_MT6360 is not set # CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_NTXEC is not set # CONFIG_MFD_OMAP_USB_HOST is not set # CONFIG_MFD_PALMAS is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_MFD_PM8921_CORE is not set # CONFIG_MFD_PM8XXX is not set +# CONFIG_MFD_QCOM_PM8008 is not set # CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RETU is not set @@ -3328,6 +3389,10 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_ROHM_BD70528 is not set # CONFIG_MFD_ROHM_BD71828 is not set # CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_RSMU_I2C is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_RT4831 is not set # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_PCI is not set # CONFIG_MFD_RTSX_USB is not set @@ -3481,9 +3546,14 @@ CONFIG_MMC_BLOCK_MINORS=8 CONFIG_MMU=y CONFIG_MMU_GATHER_RCU_TABLE_FREE=y CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MODPROBE_PATH="/sbin/modprobe" CONFIG_MODULES=y # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set # CONFIG_MODULE_COMPRESS is not set +# CONFIG_MODULE_COMPRESS_GZIP is not set +CONFIG_MODULE_COMPRESS_NONE=y +# CONFIG_MODULE_COMPRESS_XZ is not set +# CONFIG_MODULE_COMPRESS_ZSTD is not set # CONFIG_MODULE_FORCE_LOAD is not set # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODULE_SIG is not set @@ -3492,6 +3562,7 @@ CONFIG_MODULE_STRIPPED=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MOST is not set +# CONFIG_MOTORCOMM_PHY is not set # CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_ELAN_I2C is not set # CONFIG_MOUSE_GPIO is not set @@ -3519,6 +3590,8 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MSDOS_PARTITION=y # CONFIG_MSI_BITMAP_SELFTEST is not set # CONFIG_MSI_LAPTOP is not set +# CONFIG_MSM_GCC_8953 is not set +# CONFIG_MSM_MMCC_8994 is not set # CONFIG_MST_IRQ is not set CONFIG_MTD=y # CONFIG_MTD_ABSENT is not set @@ -3561,6 +3634,7 @@ CONFIG_MTD_MAP_BANK_WIDTH_2=y CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set # CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set # CONFIG_MTD_MT81xx_NOR is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_MYLOADER_PARTS is not set @@ -3598,6 +3672,7 @@ CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 # CONFIG_MTD_NAND_GPMI_NAND is not set # CONFIG_MTD_NAND_HISI504 is not set CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_INTEL_LGM is not set # CONFIG_MTD_NAND_JZ4740 is not set # CONFIG_MTD_NAND_MPC5121_NFC is not set # CONFIG_MTD_NAND_MTK is not set @@ -3657,6 +3732,9 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y # CONFIG_MTD_SPINAND_MT29F is not set # CONFIG_MTD_SPI_NAND is not set # CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 # CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE is not set @@ -3687,6 +3765,8 @@ CONFIG_MTD_SPLIT_SUPPORT=y # CONFIG_MTD_UBI_GLUEBI is not set # CONFIG_MTD_UIMAGE_SPLIT is not set # CONFIG_MTD_VIRT_CONCAT is not set +# CONFIG_MTD_NAND_MTK_BMT is not set +# CONFIG_MTK_DEVAPC is not set # CONFIG_MTK_MMC is not set # CONFIG_MTK_MMSYS is not set # CONFIG_MULTIPLEXER is not set @@ -3724,12 +3804,14 @@ CONFIG_NETDEVICES=y # CONFIG_NETFILTER_DEBUG is not set # CONFIG_NETFILTER_INGRESS is not set # CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_NETLINK_HOOK is not set # CONFIG_NETFILTER_NETLINK_ACCT is not set # CONFIG_NETFILTER_NETLINK_GLUE_CT is not set # CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NETFILTER_NETLINK_OSF is not set # CONFIG_NETFILTER_NETLINK_QUEUE is not set # CONFIG_NETFILTER_XTABLES is not set +# CONFIG_NETFILTER_XTABLES_COMPAT is not set # CONFIG_NETFILTER_XT_CONNMARK is not set # CONFIG_NETFILTER_XT_MARK is not set # CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set @@ -3880,17 +3962,22 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_TAG_DSA is not set # CONFIG_NET_DSA_TAG_EDSA is not set # CONFIG_NET_DSA_TAG_GSWIP is not set +# CONFIG_NET_DSA_TAG_HELLCREEK is not set # CONFIG_NET_DSA_TAG_KSZ is not set # CONFIG_NET_DSA_TAG_LAN9303 is not set # CONFIG_NET_DSA_TAG_MTK is not set # CONFIG_NET_DSA_TAG_OCELOT is not set +# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set # CONFIG_NET_DSA_TAG_QCA is not set # CONFIG_NET_DSA_TAG_RTL4_A is not set # CONFIG_NET_DSA_TAG_SJA1105 is not set # CONFIG_NET_DSA_TAG_TRAILER is not set +# CONFIG_NET_DSA_TAG_XRS700X is not set # CONFIG_NET_DSA_VITESSE_VSC73XX is not set # CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM is not set # CONFIG_NET_DSA_VITESSE_VSC73XX_SPI is not set +# CONFIG_NET_DSA_XRS700X_I2C is not set +# CONFIG_NET_DSA_XRS700X_MDIO is not set # CONFIG_NET_EMATCH is not set # CONFIG_NET_EMATCH_CANID is not set # CONFIG_NET_EMATCH_CMP is not set @@ -4001,11 +4088,13 @@ CONFIG_NET_VENDOR_HUAWEI=y CONFIG_NET_VENDOR_I825XX=y CONFIG_NET_VENDOR_IBM=y CONFIG_NET_VENDOR_INTEL=y +# CONFIG_NET_VENDOR_LITEX is not set CONFIG_NET_VENDOR_MARVELL=y CONFIG_NET_VENDOR_MELLANOX=y CONFIG_NET_VENDOR_MICREL=y CONFIG_NET_VENDOR_MICROCHIP=y CONFIG_NET_VENDOR_MICROSEMI=y +# CONFIG_NET_VENDOR_MICROSOFT is not set CONFIG_NET_VENDOR_MYRI=y CONFIG_NET_VENDOR_NATSEMI=y CONFIG_NET_VENDOR_NETERION=y @@ -4068,6 +4157,7 @@ CONFIG_NFS_V3=y # CONFIG_NFT_FIB_IPV4 is not set # CONFIG_NFT_FIB_IPV6 is not set # CONFIG_NFT_FIB_NETDEV is not set +# CONFIG_NFT_REJECT_NETDEV is not set # CONFIG_NFT_FLOW_OFFLOAD is not set # CONFIG_NFT_OBJREF is not set # CONFIG_NFT_OSF is not set @@ -4114,6 +4204,7 @@ CONFIG_NF_CONNTRACK_PROCFS=y # CONFIG_NF_LOG_BRIDGE is not set # CONFIG_NF_LOG_IPV4 is not set # CONFIG_NF_LOG_NETDEV is not set +# CONFIG_NF_LOG_SYSLOG is not set # CONFIG_NF_NAT is not set # CONFIG_NF_NAT_AMANDA is not set # CONFIG_NF_NAT_FTP is not set @@ -4216,23 +4307,30 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NO_HZ_IDLE is not set # CONFIG_NS83820 is not set # CONFIG_NTB is not set +# CONFIG_NTFS3_FS is not set +# CONFIG_NTFS3_64BIT_CLUSTER is not set +# CONFIG_NTFS3_LZX_XPRESS is not set +# CONFIG_NTFS3_FS_POSIX_ACL is not set # CONFIG_NTFS_DEBUG is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_NTP_PPS is not set # CONFIG_NULL_TTY is not set # CONFIG_NUMA is not set +# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set # CONFIG_NVM is not set # CONFIG_NVMEM is not set # CONFIG_NVMEM_BCM_OCOTP is not set # CONFIG_NVMEM_IMX_OCOTP is not set # CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_NVMEM_RMEM is not set # 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_C45_TJA11XX_PHY is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set # CONFIG_NXP_TJA11XX_PHY is not set @@ -4379,6 +4477,8 @@ CONFIG_PCIE_BUS_DEFAULT=y # CONFIG_PCIE_IPROC is not set # CONFIG_PCIE_KIRIN is not set # CONFIG_PCIE_LAYERSCAPE_GEN4 is not set +# CONFIG_PCIE_MEDIATEK_GEN3 is not set +# CONFIG_PCIE_MICROCHIP_HOST is not set # CONFIG_PCIE_PTM is not set # CONFIG_PCIE_XILINX is not set # CONFIG_PCIPCWATCHDOG is not set @@ -4432,6 +4532,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_PCMCIA_XIRCOM is not set # CONFIG_PCNET32 is not set +# CONFIG_PCPU_DEV_REFCNT is not set # CONFIG_PCSPKR_PLATFORM is not set # CONFIG_PCS_XPCS is not set # CONFIG_PD6729 is not set @@ -4451,6 +4552,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHY_CADENCE_SALVO is not set # CONFIG_PHY_CADENCE_SIERRA is not set # CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CAN_TRANSCEIVER is not set # CONFIG_PHY_CPCAP_USB is not set # CONFIG_PHY_EXYNOS_DP_VIDEO is not set # CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set @@ -4459,6 +4561,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHY_MAPPHONE_MDM6600 is not set # CONFIG_PHY_MIXEL_MIPI_DPHY is not set # CONFIG_PHY_MTK_HDMI is not set +# CONFIG_PHY_MTK_MIPI_DSI is not set # CONFIG_PHY_OCELOT_SERDES is not set # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set @@ -4480,14 +4583,26 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL_EXYNOS5440 is not set # CONFIG_PINCTRL_ICELAKE is not set # CONFIG_PINCTRL_INGENIC is not set +# CONFIG_PINCTRL_LPASS_LPI is not set # CONFIG_PINCTRL_MCP23S08 is not set +# CONFIG_PINCTRL_MDM9607 is not set +# CONFIG_PINCTRL_MICROCHIP_SGPIO is not set +# CONFIG_PINCTRL_MSM8953 is not set # CONFIG_PINCTRL_MSM8X74 is not set # CONFIG_PINCTRL_MT6779 is not set # CONFIG_PINCTRL_MT8167 is not set # CONFIG_PINCTRL_MT8192 is not set +# CONFIG_PINCTRL_MT8195 is not set +# CONFIG_PINCTRL_MT8365 is not set # CONFIG_PINCTRL_MTK_V2 is not set # CONFIG_PINCTRL_OCELOT is not set +# CONFIG_PINCTRL_SC7280 is not set +# CONFIG_PINCTRL_SC8180X is not set +# CONFIG_PINCTRL_SDX55 is not set CONFIG_PINCTRL_SINGLE=y +# CONFIG_PINCTRL_SM6115 is not set +# CONFIG_PINCTRL_SM6125 is not set +# CONFIG_PINCTRL_SM8350 is not set # CONFIG_PINCTRL_STMFX is not set # CONFIG_PINCTRL_SX150X is not set # CONFIG_PING is not set @@ -4526,6 +4641,7 @@ CONFIG_POSIX_TIMERS=y # CONFIG_POWER_RESET_LINKSTATION is not set # CONFIG_POWER_RESET_LTC2952 is not set # CONFIG_POWER_RESET_PIIX4_POWEROFF is not set +# CONFIG_POWER_RESET_REGULATOR is not set # CONFIG_POWER_RESET_QNAP is not set # CONFIG_POWER_RESET_RESTART is not set # CONFIG_POWER_RESET_SYSCON is not set @@ -4543,7 +4659,6 @@ CONFIG_PPC_4K_PAGES=y # CONFIG_PPC_DISABLE_WERROR is not set # CONFIG_PPC_EMULATED_STATS is not set # CONFIG_PPC_EPAPR_HV_BYTECHAN is not set -# CONFIG_PPC_QUEUED_SPINLOCKS is not set # CONFIG_PPP is not set # CONFIG_PPPOATM is not set # CONFIG_PPPOE is not set @@ -4573,6 +4688,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_PRIME_NUMBERS is not set CONFIG_PRINTK=y # CONFIG_PRINTK_CALLER is not set +# CONFIG_PRINTK_INDEX is not set CONFIG_PRINTK_NMI=y CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 # CONFIG_PRINTK_TIME is not set @@ -4602,6 +4718,7 @@ CONFIG_PROC_SYSCTL=y # CONFIG_PSTORE_COMPRESS is not set # CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" # CONFIG_PSTORE_CONSOLE is not set +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PSTORE_DEFLATE_COMPRESS is not set # CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT is not set # CONFIG_PSTORE_LZ4HC_COMPRESS is not set @@ -4616,12 +4733,15 @@ CONFIG_PROC_SYSCTL=y # CONFIG_PTP_1588_CLOCK_IDTCM is not set # CONFIG_PTP_1588_CLOCK_IXP46X is not set # CONFIG_PTP_1588_CLOCK_KVM is not set +# CONFIG_PTP_1588_CLOCK_OCP is not set # CONFIG_PTP_1588_CLOCK_PCH is not set # CONFIG_PTP_1588_CLOCK_VMW is not set # CONFIG_PUBLIC_KEY_ALGO_RSA is not set # CONFIG_PVPANIC is not set # CONFIG_PWM is not set +# CONFIG_PWM_ATMEL_TCB is not set # CONFIG_PWM_DEBUG is not set +# CONFIG_PWM_DWC is not set # CONFIG_PWM_FSL_FTM is not set # CONFIG_PWM_JZ4740 is not set # CONFIG_PWM_PCA9685 is not set @@ -4631,12 +4751,15 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_QCA7000 is not set # CONFIG_QCA7000_SPI is not set # CONFIG_QCA7000_UART is not set +# CONFIG_QCOM_A7PLL is not set # CONFIG_QCOM_EMAC is not set # CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set # CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set # CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +# CONFIG_QCOM_GPI_DMA is not set # CONFIG_QCOM_HIDMA is not set # CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_LMH is not set # CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set # CONFIG_QCOM_SPMI_ADC5 is not set # CONFIG_QCOM_SPMI_IADC is not set @@ -4681,6 +4804,7 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_RALINK is not set # CONFIG_RANDOM32_SELFTEST is not set # CONFIG_RANDOMIZE_BASE is not set +# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set # CONFIG_RANDOM_TRUST_BOOTLOADER is not set # CONFIG_RANDOM_TRUST_CPU is not set # CONFIG_RAPIDIO is not set @@ -4688,7 +4812,7 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_RAW_DRIVER is not set # CONFIG_RBTREE_TEST is not set # CONFIG_RCU_BOOST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_EQS_DEBUG is not set # CONFIG_RCU_EXPEDITE_BOOT is not set # CONFIG_RCU_EXPERT is not set @@ -4732,6 +4856,7 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_ACT8865 is not set # CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9121 is not set # CONFIG_REGULATOR_DA9210 is not set # CONFIG_REGULATOR_DA9211 is not set # CONFIG_REGULATOR_DEBUG is not set @@ -4752,6 +4877,7 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_MAX77826 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8893 is not set # CONFIG_REGULATOR_MAX8952 is not set # CONFIG_REGULATOR_MAX8973 is not set # CONFIG_REGULATOR_MCP16502 is not set @@ -4760,7 +4886,9 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_MP886X is not set # CONFIG_REGULATOR_MPQ7920 is not set # CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_MT6315 is not set # CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF8X00 is not set # CONFIG_REGULATOR_PFUZE100 is not set # CONFIG_REGULATOR_PV88060 is not set # CONFIG_REGULATOR_PV88080 is not set @@ -4768,7 +4896,11 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_PWM is not set # CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set # CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RT6160 is not set +# CONFIG_REGULATOR_RT6245 is not set # CONFIG_REGULATOR_RTMV20 is not set +# CONFIG_REGULATOR_RTQ2134 is not set +# CONFIG_REGULATOR_RTQ6752 is not set # CONFIG_REGULATOR_SLG51000 is not set # CONFIG_REGULATOR_SY8106A is not set # CONFIG_REGULATOR_SY8824X is not set @@ -4865,6 +4997,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_FTRTC010 is not set # CONFIG_RTC_DRV_GENERIC is not set +# CONFIG_RTC_DRV_GOLDFISH is not set # CONFIG_RTC_DRV_HID_SENSOR_TIME is not set # CONFIG_RTC_DRV_HYM8563 is not set # CONFIG_RTC_DRV_ISL12022 is not set @@ -4982,6 +5115,7 @@ CONFIG_SATA_MOBILE_LPM_POLICY=0 CONFIG_SBITMAP=y # CONFIG_SC92031 is not set # CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set # CONFIG_SCACHE_DEBUGFS is not set # CONFIG_SCC is not set # CONFIG_SCD30_CORE is not set @@ -5048,6 +5182,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set # CONFIG_SCSI_LPFC is not set CONFIG_SCSI_MOD=y +# CONFIG_SCSI_MPI3MR is not set # CONFIG_SCSI_MPT2SAS is not set # CONFIG_SCSI_MPT3SAS is not set # CONFIG_SCSI_MQ_DEFAULT is not set @@ -5084,12 +5219,22 @@ CONFIG_SCSI_PROC_FS=y # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_VIRTIO is not set # CONFIG_SCSI_WD719X is not set +# CONFIG_SC_CAMCC_7180 is not set +# CONFIG_SC_DISPCC_7280 is not set +# CONFIG_SC_GCC_7280 is not set +# CONFIG_SC_GCC_8180X is not set +# CONFIG_SC_GPUCC_7280 is not set +# CONFIG_SC_VIDEOCC_7280 is not set # CONFIG_SCx200_ACB is not set # CONFIG_SDIO_UART is not set +# CONFIG_SDM_GPUCC_660 is not set +# CONFIG_SDM_MMCC_660 is not set # CONFIG_SDR_MAX2175 is not set # CONFIG_SDR_PLATFORM_DRIVERS is not set +# CONFIG_SDX_GCC_55 is not set # CONFIG_SD_ADC_MODULATOR is not set # CONFIG_SECCOMP is not set +# CONFIG_SECCOMP_CACHE_DEBUG is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set @@ -5110,6 +5255,7 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 # CONFIG_SECURITY_YAMA is not set CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSIRION_SGP30 is not set +# CONFIG_SENSIRION_SGP40 is not set # CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ABITUGURU3 is not set # CONFIG_SENSORS_ACPI_POWER is not set @@ -5136,6 +5282,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AHT10 is not set # CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_APDS990X is not set # CONFIG_SENSORS_APPLESMC is not set @@ -5221,6 +5368,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_LTC2947_SPI is not set # CONFIG_SENSORS_LTC2978 is not set # CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2992 is not set # CONFIG_SENSORS_LTC3815 is not set # CONFIG_SENSORS_LTC4151 is not set # CONFIG_SENSORS_LTC4215 is not set @@ -5230,6 +5378,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_LTC4261 is not set # CONFIG_SENSORS_LTQ_CPUTEMP is not set # CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX127 is not set # CONFIG_SENSORS_MAX16064 is not set # CONFIG_SENSORS_MAX16065 is not set # CONFIG_SENSORS_MAX1619 is not set @@ -5269,12 +5418,15 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_PXE1610 is not set # CONFIG_SENSORS_RM3100_I2C is not set # CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSORS_SBRMI is not set +# CONFIG_SENSORS_SBTSI is not set # CONFIG_SENSORS_SCH5627 is not set # CONFIG_SENSORS_SCH5636 is not set # CONFIG_SENSORS_SCH56XX_COMMON is not set # CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHT4x is not set # CONFIG_SENSORS_SHTC1 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMM665 is not set @@ -5291,6 +5443,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set # CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_TPS23861 is not set # CONFIG_SENSORS_TPS40422 is not set # CONFIG_SENSORS_TPS53679 is not set # CONFIG_SENSORS_TSL2550 is not set @@ -5453,6 +5606,7 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SLUB_MEMCG_SYSFS_ON is not set # CONFIG_SLUB_STATS is not set # CONFIG_SMARTJOYPLUS_FF is not set +# CONFIG_SMB_SERVER is not set # CONFIG_SMC911X is not set # CONFIG_SMC9194 is not set # CONFIG_SMC91X is not set @@ -5462,7 +5616,12 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SMSC_PHY is not set # CONFIG_SMS_SDIO_DRV is not set # CONFIG_SMS_USB_DRV is not set +# CONFIG_SM_CAMCC_8250 is not set # CONFIG_SM_FTL is not set +# CONFIG_SM_GCC_6115 is not set +# CONFIG_SM_GCC_6125 is not set +# CONFIG_SM_GCC_6350 is not set +# CONFIG_SM_GCC_8350 is not set # CONFIG_SND is not set # CONFIG_SND_AC97_POWER_SAVE is not set # CONFIG_SND_AD1816A is not set @@ -5969,10 +6128,13 @@ CONFIG_SQUASHFS_XZ=y CONFIG_SSB_POSSIBLE=y # CONFIG_SSB_SDIOHOST is not set # CONFIG_SSB_SILENT is not set +# CONFIG_SPS30_I2C is not set +# CONFIG_SPS30_SERIAL is not set # CONFIG_SSFDC is not set # CONFIG_STACKPROTECTOR is not set # CONFIG_STACKPROTECTOR_STRONG is not set # CONFIG_STACKTRACE is not set +# CONFIG_STACKTRACE_BUILD_ID is not set CONFIG_STACKTRACE_SUPPORT=y # CONFIG_STACK_TRACER is not set # CONFIG_STACK_VALIDATION is not set @@ -6070,6 +6232,7 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TCG_TIS_I2C_INFINEON is not set # CONFIG_TCG_TIS_I2C_NUVOTON is not set # CONFIG_TCG_TIS_SPI is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set # CONFIG_TCG_TIS_ST33ZP24_I2C is not set # CONFIG_TCG_TIS_ST33ZP24_SPI is not set # CONFIG_TCG_TPM is not set @@ -6107,6 +6270,7 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_BITOPS is not set # CONFIG_TEST_BLACKHOLE_DEV is not set # CONFIG_TEST_BPF is not set +# CONFIG_TEST_DIV64 is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_FREE_PAGES is not set # CONFIG_TEST_HASH is not set @@ -6125,6 +6289,7 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_POWER is not set # CONFIG_TEST_PRINTF is not set # CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_SCANF is not set # CONFIG_TEST_SORT is not set # CONFIG_TEST_STACKINIT is not set # CONFIG_TEST_STATIC_KEYS is not set @@ -6191,6 +6356,7 @@ CONFIG_TINY_RCU=y # CONFIG_TI_ADC161S626 is not set # CONFIG_TI_ADS1015 is not set # CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set # CONFIG_TI_ADS7950 is not set # CONFIG_TI_ADS8344 is not set # CONFIG_TI_ADS8688 is not set @@ -6209,11 +6375,13 @@ CONFIG_TINY_RCU=y # CONFIG_TI_ST is not set # CONFIG_TI_SYSCON_RESET is not set # CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set # CONFIG_TLAN is not set # CONFIG_TLS is not set # CONFIG_TMD_HERMES is not set # CONFIG_TMP006 is not set # CONFIG_TMP007 is not set +# CONFIG_TMP117 is not set CONFIG_TMPFS=y # CONFIG_TMPFS_INODE64 is not set # CONFIG_TMPFS_POSIX_ACL is not set @@ -6368,6 +6536,7 @@ CONFIG_TRAD_SIGNALS=y # CONFIG_TRUSTED_FOUNDATIONS is not set # CONFIG_TRUSTED_KEYS is not set # CONFIG_TSL2583 is not set +# CONFIG_TSL2591 is not set # CONFIG_TSL2772 is not set # CONFIG_TSL2x7x is not set # CONFIG_TSL4531 is not set @@ -6449,6 +6618,7 @@ CONFIG_USB_BELKIN=y # CONFIG_USB_CATC is not set # CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS_SUPPORT is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_USB_CHIPIDEA is not set # CONFIG_USB_CHIPIDEA_GENERIC is not set @@ -6622,6 +6792,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=2 # CONFIG_USB_NET2272 is not set # CONFIG_USB_NET2280 is not set # CONFIG_USB_NET_AQC111 is not set +# CONFIG_USB_RTL8153_ECM is not set # CONFIG_USB_NET_AX88179_178A is not set # CONFIG_USB_NET_AX8817X is not set # CONFIG_USB_NET_CDCETHER is not set @@ -7008,6 +7179,7 @@ CONFIG_VLAN_8021Q=y # CONFIG_VLAN_8021Q_GVRP is not set # CONFIG_VLAN_8021Q_MVRP is not set # CONFIG_VME_BUS is not set +# CONFIG_VMLINUX_MAP is not set # CONFIG_VMSPLIT_1G is not set # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_2G_OPT is not set @@ -7061,6 +7233,7 @@ CONFIG_VMSPLIT_3G=y CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_CORE is not set CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set # CONFIG_WATCHDOG_NOWAYOUT is not set CONFIG_WATCHDOG_OPEN_TIMEOUT=0 # CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set @@ -7069,6 +7242,7 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0 # CONFIG_WD80x3 is not set # CONFIG_WDAT_WDT is not set # CONFIG_WDTPCI is not set +# CONFIG_WERROR is not set CONFIG_WEXT_CORE=y CONFIG_WEXT_PRIV=y CONFIG_WEXT_PROC=y @@ -7105,6 +7279,7 @@ CONFIG_WLAN=y # CONFIG_WLCORE is not set CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y # CONFIG_WQ_WATCHDOG is not set +# CONFIG_WWAN is not set # CONFIG_WW_MUTEX_SELFTEST is not set # CONFIG_X25 is not set # CONFIG_X509_CERTIFICATE_PARSER is not set @@ -7142,6 +7317,7 @@ CONFIG_XFRM=y # CONFIG_XILINX_ZYNQMP_DMA is not set # CONFIG_XILINX_ZYNQMP_DPDMA is not set # CONFIG_XILLYBUS is not set +# CONFIG_XILLYUSB is not set # CONFIG_XIL_AXIS_FIFO is not set # CONFIG_XIP_KERNEL is not set # CONFIG_XMON is not set @@ -7155,6 +7331,7 @@ CONFIG_XZ_DEC=y # CONFIG_XZ_DEC_TEST is not set # CONFIG_XZ_DEC_X86 is not set # CONFIG_YAM is not set +# CONFIG_YAMAHA_YAS530 is not set # CONFIG_YELLOWFIN is not set # CONFIG_YENTA is not set # CONFIG_YENTA_O2 is not set @@ -7165,6 +7342,7 @@ CONFIG_XZ_DEC=y # CONFIG_ZD1211RW is not set # CONFIG_ZD1211RW_DEBUG is not set # CONFIG_ZEROPLUS_FF is not set +# CONFIG_ZERO_CALL_USED_REGS is not set # CONFIG_ZIIRAVE_WATCHDOG is not set # CONFIG_ZISOFS is not set # CONFIG_ZLIB_DEFLATE is not set @@ -7175,5 +7353,9 @@ CONFIG_ZONE_DMA=y # CONFIG_ZPOOL is not set # CONFIG_ZRAM is not set # CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_ZRAM_DEF_COMP_LZORLE is not set +# CONFIG_ZRAM_DEF_COMP_ZSTD is not set +# CONFIG_ZRAM_DEF_COMP_LZ4 is not set +# CONFIG_ZRAM_DEF_COMP_LZO is not set # CONFIG_ZSMALLOC is not set # CONFIG_ZX_TDM is not set diff --git a/target/linux/mediatek/Makefile b/target/linux/mediatek/Makefile index 466fe6dee2..2b4f240429 100644 --- a/target/linux/mediatek/Makefile +++ b/target/linux/mediatek/Makefile @@ -9,6 +9,7 @@ SUBTARGETS:=mt7622 mt7623 mt7629 FEATURES:=dt-overlay emmc fpu gpio nand pci pcie rootfs-part separate_ramdisk squashfs usb KERNEL_PATCHVER:=5.10 +KERNEL_TESTING_PATCHVER:=5.15 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ From b268ec5ff8baed74037d04a74f61c0417d931ad9 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Sun, 16 Jan 2022 03:51:05 +0100 Subject: [PATCH 12/26] generic: 5.15: add support for new kernel version Add hash/version file and enable kernel 5.15 for openwrt. Signed-off-by: Ansuel Smith --- include/kernel-5.15 | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 include/kernel-5.15 diff --git a/include/kernel-5.15 b/include/kernel-5.15 new file mode 100644 index 0000000000..4271b8948c --- /dev/null +++ b/include/kernel-5.15 @@ -0,0 +1,2 @@ +LINUX_VERSION-5.15 = .31 +LINUX_KERNEL_HASH-5.15.31 = f621384b47d5bed927910bf5211e7b4ccac925f28218e483bb1a9c484b246b88 From bd0db6017b1921c935785cdccdf0243fddf0b949 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 4 Nov 2021 21:59:09 +0100 Subject: [PATCH 13/26] kernel: 5.15: add new module Add new module require in 5.15 - Changes in block module - Changes in netfilter module (log module unified) - Changes in fs module (mainly new depends for cifs and new ntfs3 module) - Changes in lib add shared lib now used by more than 1 kmod - Changes in crypto, dropped one crypto algo added arm crypto accellerator - Changes in other, add zram default compressor choice and missing lib by tpm module Signed-off-by: Ansuel Smith --- include/netfilter.mk | 7 ++-- package/kernel/linux/modules/block.mk | 4 +- package/kernel/linux/modules/crypto.mk | 33 +++++++++++++---- package/kernel/linux/modules/fs.mk | 43 +++++++++++++++++++--- package/kernel/linux/modules/input.mk | 4 +- package/kernel/linux/modules/lib.mk | 10 +++++ package/kernel/linux/modules/netfilter.mk | 2 +- package/kernel/linux/modules/netsupport.mk | 3 +- package/kernel/linux/modules/other.mk | 29 +++++++++++++-- 9 files changed, 112 insertions(+), 23 deletions(-) diff --git a/include/netfilter.mk b/include/netfilter.mk index 2ef8f83e4c..24255ebe6d 100644 --- a/include/netfilter.mk +++ b/include/netfilter.mk @@ -48,8 +48,9 @@ $(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_MATCH_COMMENT, $(P_XT)xt_comme $(eval $(call nf_add,IPT_CLUSTER,CONFIG_NETFILTER_XT_MATCH_CLUSTER, $(P_XT)xt_cluster)) $(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_LOG, $(P_XT)xt_LOG)) -$(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_LOG, $(P_XT)nf_log_common)) -$(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_LOG, $(P_V4)nf_log_ipv4)) +$(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_LOG, $(P_XT)nf_log_common, lt 5.13)) +$(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_LOG, $(P_V4)nf_log_ipv4, lt 5.13)) +$(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_LOG, $(P_XT)nf_log_syslog, ge 5.13)) $(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_TARGET_TCPMSS, $(P_XT)xt_TCPMSS)) $(eval $(call nf_add,IPT_CORE,CONFIG_IP_NF_TARGET_REJECT, $(P_V4)ipt_REJECT)) $(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_MATCH_TIME, $(P_XT)xt_time)) @@ -156,7 +157,7 @@ $(eval $(if $(NF_KMOD),$(call nf_add,NF_CONNTRACK,CONFIG_NF_DEFRAG_IPV6, $(P_V6) $(eval $(if $(NF_KMOD),$(call nf_add,IPT_IPV6,CONFIG_IP6_NF_FILTER, $(P_V6)ip6table_filter),)) $(eval $(if $(NF_KMOD),$(call nf_add,IPT_IPV6,CONFIG_IP6_NF_MANGLE, $(P_V6)ip6table_mangle),)) -$(eval $(if $(NF_KMOD),$(call nf_add,IPT_IPV6,CONFIG_NF_LOG_IPV6, $(P_V6)nf_log_ipv6),)) +$(eval $(if $(NF_KMOD),$(call nf_add,IPT_IPV6,CONFIG_NF_LOG_IPV6, $(P_V6)nf_log_ipv6,lt 5.13),)) $(eval $(if $(NF_KMOD),,$(call nf_add,IPT_IPV6,CONFIG_IP6_NF_IPTABLES, ip6t_icmp6))) diff --git a/package/kernel/linux/modules/block.mk b/package/kernel/linux/modules/block.mk index e5822d95d7..dfb529db3b 100644 --- a/package/kernel/linux/modules/block.mk +++ b/package/kernel/linux/modules/block.mk @@ -513,11 +513,13 @@ define KernelPackage/scsi-core TITLE:=SCSI device support KCONFIG:= \ CONFIG_SCSI \ + CONFIG_SCSI_COMMON@ge5.15 \ CONFIG_BLK_DEV_SD FILES:= \ $(LINUX_DIR)/drivers/scsi/scsi_mod.ko \ + $(LINUX_DIR)/drivers/scsi/scsi_common.ko@ge5.15 \ $(LINUX_DIR)/drivers/scsi/sd_mod.ko - AUTOLOAD:=$(call AutoLoad,40,scsi_mod sd_mod,1) + AUTOLOAD:=$(call AutoLoad,40,scsi_mod scsi_common@ge5.15 sd_mod,1) endef $(eval $(call KernelPackage,scsi-core)) diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index 4097957277..6fd53f6080 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -451,9 +451,7 @@ define KernelPackage/crypto-lib-blake2s TITLE:=BLAKE2s hash function library KCONFIG:=CONFIG_CRYPTO_LIB_BLAKE2S HIDDEN:=1 - FILES:= \ - $(LINUX_DIR)/lib/crypto/libblake2s.ko \ - $(LINUX_DIR)/lib/crypto/libblake2s-generic.ko + FILES:=$(LINUX_DIR)/lib/crypto/libblake2s.ko $(call AddDepends/crypto,+PACKAGE_kmod-crypto-hash:kmod-crypto-hash) endef @@ -463,9 +461,30 @@ endef define KernelPackage/crypto-lib-blake2s/x86/64 KCONFIG+=CONFIG_CRYPTO_BLAKE2S_X86 - FILES+=$(LINUX_DIR)/arch/x86/crypto/blake2s-x86_64.ko + FILES+=\ + $(LINUX_DIR)/lib/crypto/libblake2s-generic.ko \ + $(LINUX_DIR)/arch/x86/crypto/blake2s-x86_64.ko endef +define KernelPackage/crypto-lib-blake2s/arm + KCONFIG+=CONFIG_CRYPTO_BLAKE2S_ARM + FILES+=\ + $(LINUX_DIR)/lib/crypto/libblake2s-generic.ko@lt5.12 \ + $(LINUX_DIR)/arch/arm/crypto/blake2s-arm.ko@ge5.12 +endef + +ifndef KernelPackage/crypto-lib-blake2s/$(CRYPTO_TARGET) + define KernelPackage/crypto-lib-blake2s/$(CRYPTO_TARGET) + KCONFIG+=CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC + FILES+=$(LINUX_DIR)/lib/crypto/libblake2s-generic.ko + endef +endif + +ifdef KernelPackage/crypto-lib-blake2s/$(ARCH) + KernelPackage/crypto-lib-blake2s/$(CRYPTO_TARGET)=\ + $(KernelPackage/crypto-lib-blake2s/$(ARCH)) +endif + $(eval $(call KernelPackage,crypto-lib-blake2s)) @@ -683,7 +702,7 @@ define KernelPackage/crypto-misc CONFIG_CRYPTO_KHAZAD \ CONFIG_CRYPTO_SERPENT \ CONFIG_CRYPTO_TEA \ - CONFIG_CRYPTO_TGR192 \ + CONFIG_CRYPTO_TGR192@lt5.12 \ CONFIG_CRYPTO_TWOFISH \ CONFIG_CRYPTO_TWOFISH_COMMON \ CONFIG_CRYPTO_TWOFISH_586 \ @@ -696,7 +715,7 @@ define KernelPackage/crypto-misc $(LINUX_DIR)/crypto/cast6_generic.ko \ $(LINUX_DIR)/crypto/khazad.ko \ $(LINUX_DIR)/crypto/tea.ko \ - $(LINUX_DIR)/crypto/tgr192.ko \ + $(LINUX_DIR)/crypto/tgr192.ko@lt5.12 \ $(LINUX_DIR)/crypto/twofish_common.ko \ $(LINUX_DIR)/crypto/wp512.ko \ $(LINUX_DIR)/crypto/twofish_generic.ko \ @@ -704,7 +723,7 @@ define KernelPackage/crypto-misc $(LINUX_DIR)/crypto/blowfish_generic.ko \ $(LINUX_DIR)/crypto/serpent_generic.ko AUTOLOAD:=$(call AutoLoad,10,anubis camellia_generic cast_common \ - cast5_generic cast6_generic khazad tea tgr192 twofish_common \ + cast5_generic cast6_generic khazad tea tgr192@lt5.12 twofish_common \ wp512 blowfish_common serpent_generic) ifndef CONFIG_TARGET_x86 AUTOLOAD+= $(call AutoLoad,10,twofish_generic blowfish_generic) diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index 91cf1ea233..e580a94c60 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -87,24 +87,31 @@ define KernelPackage/fs-cifs SUBMENU:=$(FS_MENU) TITLE:=CIFS support KCONFIG:= \ + CONFIG_SMBFS_COMMON@ge5.15 \ CONFIG_CIFS \ CONFIG_CIFS_DFS_UPCALL=n \ CONFIG_CIFS_UPCALL=n - FILES:=$(LINUX_DIR)/fs/cifs/cifs.ko + FILES:= \ + $(LINUX_DIR)/fs/smbfs_common/cifs_arc4.ko@ge5.15 \ + $(LINUX_DIR)/fs/smbfs_common/cifs_md4.ko@ge5.15 \ + $(LINUX_DIR)/fs/cifs/cifs.ko AUTOLOAD:=$(call AutoLoad,30,cifs) $(call AddDepends/nls) DEPENDS+= \ - +kmod-crypto-md4 \ + +(LINUX_5_4||LINUX_5_10):kmod-crypto-md4\ +kmod-crypto-md5 \ +kmod-crypto-sha256 \ +kmod-crypto-sha512 \ +kmod-crypto-cmac \ +kmod-crypto-hmac \ - +kmod-crypto-arc4 \ + +(LINUX_5_4||LINUX_5_10):kmod-crypto-arc4 \ +kmod-crypto-aead \ +kmod-crypto-ccm \ +kmod-crypto-ecb \ - +kmod-crypto-des + +kmod-crypto-des \ + +(LINUX_5_15):kmod-asn1-decoder \ + +(LINUX_5_15):kmod-oid-registry \ + +(LINUX_5_15):kmod-dnsresolver endef define KernelPackage/fs-cifs/description @@ -239,10 +246,21 @@ endef $(eval $(call KernelPackage,fs-f2fs)) +define KernelPackage/fs-netfs + SUBMENU:=$(FS_MENU) + TITLE:=Network Filesystems support + DEPENDS:=@LINUX_5_15 + KCONFIG:= CONFIG_NETFS_SUPPORT + FILES:=$(LINUX_DIR)/fs/netfs/netfs.ko + AUTOLOAD:=$(call AutoLoad,28,netfs) +endef + +$(eval $(call KernelPackage,fs-netfs)) + define KernelPackage/fs-fscache SUBMENU:=$(FS_MENU) TITLE:=General filesystem local cache manager - DEPENDS:= + DEPENDS:=+kmod-fs-netfs KCONFIG:=\ CONFIG_FSCACHE=m \ CONFIG_FSCACHE_STATS=y \ @@ -616,3 +634,18 @@ define KernelPackage/fuse/description endef $(eval $(call KernelPackage,fuse)) + + +define KernelPackage/fs-ntfs3 + SUBMENU:=$(FS_MENU) + TITLE:=Ntfs3 support + KCONFIG:= CONFIG_NTFS3_FS CONFIG_NTFS3_FS_POSIX_ACL=y + FILES:=$(LINUX_DIR)/fs/ntfs3/ntfs3.ko + AUTOLOAD:=$(call AutoLoad,80,ntfs3) +endef + +define KernelPackage/fuse/description + Kernel module for new NTFS3 filesystem support +endef + +$(eval $(call KernelPackage,fs-ntfs3)) diff --git a/package/kernel/linux/modules/input.mk b/package/kernel/linux/modules/input.mk index e870bf7f8b..e052a7afac 100644 --- a/package/kernel/linux/modules/input.mk +++ b/package/kernel/linux/modules/input.mk @@ -179,10 +179,10 @@ define KernelPackage/input-touchscreen-ads7846 DEPENDS:=+kmod-hwmon-core +kmod-input-core +kmod-spi-bitbang KCONFIG:= \ CONFIG_INPUT_TOUCHSCREEN=y \ - CONFIG_TOUCHSCREEN_PROPERTIES=y \ + CONFIG_TOUCHSCREEN_PROPERTIES=y@lt5.13 \ CONFIG_TOUCHSCREEN_ADS7846 FILES:=$(LINUX_DIR)/drivers/input/touchscreen/ads7846.ko \ - $(LINUX_DIR)/drivers/input/touchscreen/of_touchscreen.ko + $(LINUX_DIR)/drivers/input/touchscreen/of_touchscreen.ko@lt5.13 AUTOLOAD:=$(call AutoProbe,ads7846) endef diff --git a/package/kernel/linux/modules/lib.mk b/package/kernel/linux/modules/lib.mk index c52a8133be..81ceb1f76c 100644 --- a/package/kernel/linux/modules/lib.mk +++ b/package/kernel/linux/modules/lib.mk @@ -274,6 +274,16 @@ endef $(eval $(call KernelPackage,asn1-decoder)) +define KernelPackage/asn1-encoder + SUBMENU:=$(LIB_MENU) + TITLE:=Simple ASN1 encoder + KCONFIG:= CONFIG_ASN1_ENCODER + HIDDEN:=1 + FILES:=$(LINUX_DIR)/lib/asn1_encoder.ko +endef + +$(eval $(call KernelPackage,asn1-encoder)) + define KernelPackage/oid-registry SUBMENU:=$(LIB_MENU) TITLE:=Object identifier registry diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk index 1707bf2d9f..6427d07c94 100644 --- a/package/kernel/linux/modules/netfilter.mk +++ b/package/kernel/linux/modules/netfilter.mk @@ -1124,7 +1124,7 @@ define KernelPackage/nft-bridge FILES:=$(foreach mod,$(NFT_BRIDGE-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_BRIDGE-m))) KCONFIG:= \ - CONFIG_NF_LOG_BRIDGE=n \ + CONFIG_NF_LOG_BRIDGE=n@lt5.13 \ $(KCONFIG_NFT_BRIDGE) endef diff --git a/package/kernel/linux/modules/netsupport.mk b/package/kernel/linux/modules/netsupport.mk index fd9051586a..76187df50f 100644 --- a/package/kernel/linux/modules/netsupport.mk +++ b/package/kernel/linux/modules/netsupport.mk @@ -1111,7 +1111,8 @@ define KernelPackage/sctp CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y FILES:= $(LINUX_DIR)/net/sctp/sctp.ko AUTOLOAD:= $(call AutoLoad,32,sctp) - DEPENDS:=+kmod-lib-crc32c +kmod-crypto-md5 +kmod-crypto-hmac + DEPENDS:=+kmod-lib-crc32c +kmod-crypto-md5 +kmod-crypto-hmac \ + +LINUX_5_15:kmod-udptunnel4 +LINUX_5_15:kmod-udptunnel6 endef define KernelPackage/sctp/description diff --git a/package/kernel/linux/modules/other.mk b/package/kernel/linux/modules/other.mk index d343ff8d28..499a4080ea 100644 --- a/package/kernel/linux/modules/other.mk +++ b/package/kernel/linux/modules/other.mk @@ -959,7 +959,6 @@ $(eval $(call KernelPackage,ikconfig)) define KernelPackage/zram SUBMENU:=$(OTHER_MENU) TITLE:=ZRAM - DEPENDS:=+kmod-lib-lzo KCONFIG:= \ CONFIG_ZSMALLOC \ CONFIG_ZRAM \ @@ -976,8 +975,31 @@ define KernelPackage/zram/description Compressed RAM block device support endef -$(eval $(call KernelPackage,zram)) +define KernelPackage/zram/config + choice + prompt "ZRAM Default compressor" + default ZRAM_DEF_COMP_LZORLE + config ZRAM_DEF_COMP_LZORLE + bool "lzo-rle" + select PACKAGE_kmod-lib-lzo + + config ZRAM_DEF_COMP_LZO + bool "lzo" + select PACKAGE_kmod-lib-lzo + + config ZRAM_DEF_COMP_LZ4 + bool "lz4" + select PACKAGE_kmod-lib-lz4 + + config ZRAM_DEF_COMP_ZSTD + bool "zstd" + select PACKAGE_kmod-lib-zstd + + endchoice +endef + +$(eval $(call KernelPackage,zram)) define KernelPackage/pps SUBMENU:=$(OTHER_MENU) @@ -1190,7 +1212,8 @@ $(eval $(call KernelPackage,keys-trusted)) define KernelPackage/tpm SUBMENU:=$(OTHER_MENU) TITLE:=TPM Hardware Support - DEPENDS:= +kmod-random-core + DEPENDS:= +kmod-random-core +(LINUX_5_15):kmod-asn1-decoder \ + +(LINUX_5_15):kmod-asn1-encoder +(LINUX_5_15):kmod-oid-registry KCONFIG:= CONFIG_TCG_TPM FILES:= $(LINUX_DIR)/drivers/char/tpm/tpm.ko AUTOLOAD:=$(call AutoLoad,10,tpm,1) From ec818e5d291169784f183680c2b4013174324b68 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Sun, 19 Dec 2021 03:37:53 +0100 Subject: [PATCH 14/26] generic: 5.15: backport mirror mode and LAG feature for qca8k Backport LAG and mirror mode feature for qca8k. Signed-off-by: Ansuel Smith --- ...sa-qca8k-add-support-for-mirror-mode.patch | 162 ++++++++++ ...t-next-net-dsa-qca8k-add-LAG-support.patch | 295 ++++++++++++++++++ ...dsa-qca8k-fix-warning-in-LAG-feature.patch | 45 +++ 3 files changed, 502 insertions(+) create mode 100644 target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch create mode 100644 target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch create mode 100644 target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch diff --git a/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch b/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch new file mode 100644 index 0000000000..4ebdfda651 --- /dev/null +++ b/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch @@ -0,0 +1,162 @@ +From 2c1bdbc7e7560d7de754cad277d968d56bb1899e Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 23 Nov 2021 03:59:10 +0100 +Subject: net: dsa: qca8k: add support for mirror mode + +The switch supports mirror mode. Only one port can set as mirror port and +every other port can set to both ingress and egress mode. The mirror +port is disabled and reverted to normal operation once every port is +removed from sending packet to it. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 4 +++ + 2 files changed, 99 insertions(+) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 67742fbd80409..bd9d756f40011 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -2022,6 +2022,99 @@ qca8k_port_mdb_del(struct dsa_switch *ds, int port, + return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid); + } + ++static int ++qca8k_port_mirror_add(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror, ++ bool ingress) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int monitor_port, ret; ++ u32 reg, val; ++ ++ /* Check for existent entry */ ++ if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) ++ return -EEXIST; ++ ++ ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val); ++ if (ret) ++ return ret; ++ ++ /* QCA83xx can have only one port set to mirror mode. ++ * Check that the correct port is requested and return error otherwise. ++ * When no mirror port is set, the values is set to 0xF ++ */ ++ monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val); ++ if (monitor_port != 0xF && monitor_port != mirror->to_local_port) ++ return -EEXIST; ++ ++ /* Set the monitor port */ ++ val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, ++ mirror->to_local_port); ++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, ++ QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val); ++ if (ret) ++ return ret; ++ ++ if (ingress) { ++ reg = QCA8K_PORT_LOOKUP_CTRL(port); ++ val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN; ++ } else { ++ reg = QCA8K_REG_PORT_HOL_CTRL1(port); ++ val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN; ++ } ++ ++ ret = regmap_update_bits(priv->regmap, reg, val, val); ++ if (ret) ++ return ret; ++ ++ /* Track mirror port for tx and rx to decide when the ++ * mirror port has to be disabled. ++ */ ++ if (ingress) ++ priv->mirror_rx |= BIT(port); ++ else ++ priv->mirror_tx |= BIT(port); ++ ++ return 0; ++} ++ ++static void ++qca8k_port_mirror_del(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ u32 reg, val; ++ int ret; ++ ++ if (mirror->ingress) { ++ reg = QCA8K_PORT_LOOKUP_CTRL(port); ++ val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN; ++ } else { ++ reg = QCA8K_REG_PORT_HOL_CTRL1(port); ++ val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN; ++ } ++ ++ ret = regmap_clear_bits(priv->regmap, reg, val); ++ if (ret) ++ goto err; ++ ++ if (mirror->ingress) ++ priv->mirror_rx &= ~BIT(port); ++ else ++ priv->mirror_tx &= ~BIT(port); ++ ++ /* No port set to send packet to mirror port. Disable mirror port */ ++ if (!priv->mirror_rx && !priv->mirror_tx) { ++ val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF); ++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, ++ QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val); ++ if (ret) ++ goto err; ++ } ++err: ++ dev_err(priv->dev, "Failed to del mirror port from %d", port); ++} ++ + static int + qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, + struct netlink_ext_ack *extack) +@@ -2132,6 +2225,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + .port_fdb_dump = qca8k_port_fdb_dump, + .port_mdb_add = qca8k_port_mdb_add, + .port_mdb_del = qca8k_port_mdb_del, ++ .port_mirror_add = qca8k_port_mirror_add, ++ .port_mirror_del = qca8k_port_mirror_del, + .port_vlan_filtering = qca8k_port_vlan_filtering, + .port_vlan_add = qca8k_port_vlan_add, + .port_vlan_del = qca8k_port_vlan_del, +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 40ec8012622f7..7c87a968c0104 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -180,6 +180,7 @@ + #define QCA8K_ATU_AGE_TIME(x) FIELD_PREP(QCA8K_ATU_AGE_TIME_MASK, (x)) + #define QCA8K_REG_GLOBAL_FW_CTRL0 0x620 + #define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) ++#define QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM GENMASK(7, 4) + #define QCA8K_REG_GLOBAL_FW_CTRL1 0x624 + #define QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK GENMASK(30, 24) + #define QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK GENMASK(22, 16) +@@ -201,6 +202,7 @@ + #define QCA8K_PORT_LOOKUP_STATE_LEARNING QCA8K_PORT_LOOKUP_STATE(0x3) + #define QCA8K_PORT_LOOKUP_STATE_FORWARD QCA8K_PORT_LOOKUP_STATE(0x4) + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) ++#define QCA8K_PORT_LOOKUP_ING_MIRROR_EN BIT(25) + + #define QCA8K_REG_GLOBAL_FC_THRESH 0x800 + #define QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK GENMASK(24, 16) +@@ -305,6 +307,8 @@ struct qca8k_ports_config { + struct qca8k_priv { + u8 switch_id; + u8 switch_revision; ++ u8 mirror_rx; ++ u8 mirror_tx; + bool legacy_phy_port_mapping; + struct qca8k_ports_config ports_config; + struct regmap *regmap; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch b/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch new file mode 100644 index 0000000000..9967211828 --- /dev/null +++ b/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch @@ -0,0 +1,295 @@ +From def975307c01191b6f0170048c3724b0ed3348af Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 23 Nov 2021 03:59:11 +0100 +Subject: net: dsa: qca8k: add LAG support + +Add LAG support to this switch. In Documentation this is described as +trunk mode. A max of 4 LAGs are supported and each can support up to 4 +port. The current tx mode supported is Hash mode with both L2 and L2+3 +mode. +When no port are present in the trunk, the trunk is disabled in the +switch. +When a port is disconnected, the traffic is redirected to the other +available port. +The hash mode is global and each LAG require to have the same hash mode +set. To change the hash mode when multiple LAG are configured, it's +required to remove each LAG and set the desired hash mode to the last. +An error is printed when it's asked to set a not supported hadh mode. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 33 +++++++++ + 2 files changed, 210 insertions(+) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index bd9d756f40011..6516df08a5d5f 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -1336,6 +1336,9 @@ qca8k_setup(struct dsa_switch *ds) + ds->ageing_time_min = 7000; + ds->ageing_time_max = 458745000; + ++ /* Set max number of LAGs supported */ ++ ds->num_lag_ids = QCA8K_NUM_LAGS; ++ + return 0; + } + +@@ -2203,6 +2206,178 @@ qca8k_get_tag_protocol(struct dsa_switch *ds, int port, + return DSA_TAG_PROTO_QCA; + } + ++static bool ++qca8k_lag_can_offload(struct dsa_switch *ds, ++ struct net_device *lag, ++ struct netdev_lag_upper_info *info) ++{ ++ struct dsa_port *dp; ++ int id, members = 0; ++ ++ id = dsa_lag_id(ds->dst, lag); ++ if (id < 0 || id >= ds->num_lag_ids) ++ return false; ++ ++ dsa_lag_foreach_port(dp, ds->dst, lag) ++ /* Includes the port joining the LAG */ ++ members++; ++ ++ if (members > QCA8K_NUM_PORTS_FOR_LAG) ++ return false; ++ ++ if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) ++ return false; ++ ++ if (info->hash_type != NETDEV_LAG_HASH_L2 || ++ info->hash_type != NETDEV_LAG_HASH_L23) ++ return false; ++ ++ return true; ++} ++ ++static int ++qca8k_lag_setup_hash(struct dsa_switch *ds, ++ struct net_device *lag, ++ struct netdev_lag_upper_info *info) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ bool unique_lag = true; ++ int i, id; ++ u32 hash; ++ ++ id = dsa_lag_id(ds->dst, lag); ++ ++ switch (info->hash_type) { ++ case NETDEV_LAG_HASH_L23: ++ hash |= QCA8K_TRUNK_HASH_SIP_EN; ++ hash |= QCA8K_TRUNK_HASH_DIP_EN; ++ fallthrough; ++ case NETDEV_LAG_HASH_L2: ++ hash |= QCA8K_TRUNK_HASH_SA_EN; ++ hash |= QCA8K_TRUNK_HASH_DA_EN; ++ break; ++ default: /* We should NEVER reach this */ ++ return -EOPNOTSUPP; ++ } ++ ++ /* Check if we are the unique configured LAG */ ++ dsa_lags_foreach_id(i, ds->dst) ++ if (i != id && dsa_lag_dev(ds->dst, i)) { ++ unique_lag = false; ++ break; ++ } ++ ++ /* Hash Mode is global. Make sure the same Hash Mode ++ * is set to all the 4 possible lag. ++ * If we are the unique LAG we can set whatever hash ++ * mode we want. ++ * To change hash mode it's needed to remove all LAG ++ * and change the mode with the latest. ++ */ ++ if (unique_lag) { ++ priv->lag_hash_mode = hash; ++ } else if (priv->lag_hash_mode != hash) { ++ netdev_err(lag, "Error: Mismateched Hash Mode across different lag is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ return regmap_update_bits(priv->regmap, QCA8K_TRUNK_HASH_EN_CTRL, ++ QCA8K_TRUNK_HASH_MASK, hash); ++} ++ ++static int ++qca8k_lag_refresh_portmap(struct dsa_switch *ds, int port, ++ struct net_device *lag, bool delete) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int ret, id, i; ++ u32 val; ++ ++ id = dsa_lag_id(ds->dst, lag); ++ ++ /* Read current port member */ ++ ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0, &val); ++ if (ret) ++ return ret; ++ ++ /* Shift val to the correct trunk */ ++ val >>= QCA8K_REG_GOL_TRUNK_SHIFT(id); ++ val &= QCA8K_REG_GOL_TRUNK_MEMBER_MASK; ++ if (delete) ++ val &= ~BIT(port); ++ else ++ val |= BIT(port); ++ ++ /* Update port member. With empty portmap disable trunk */ ++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL0, ++ QCA8K_REG_GOL_TRUNK_MEMBER(id) | ++ QCA8K_REG_GOL_TRUNK_EN(id), ++ !val << QCA8K_REG_GOL_TRUNK_SHIFT(id) | ++ val << QCA8K_REG_GOL_TRUNK_SHIFT(id)); ++ ++ /* Search empty member if adding or port on deleting */ ++ for (i = 0; i < QCA8K_NUM_PORTS_FOR_LAG; i++) { ++ ret = regmap_read(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id), &val); ++ if (ret) ++ return ret; ++ ++ val >>= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i); ++ val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_MASK; ++ ++ if (delete) { ++ /* If port flagged to be disabled assume this member is ++ * empty ++ */ ++ if (val != QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK) ++ continue; ++ ++ val &= QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK; ++ if (val != port) ++ continue; ++ } else { ++ /* If port flagged to be enabled assume this member is ++ * already set ++ */ ++ if (val == QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK) ++ continue; ++ } ++ ++ /* We have found the member to add/remove */ ++ break; ++ } ++ ++ /* Set port in the correct port mask or disable port if in delete mode */ ++ return regmap_update_bits(priv->regmap, QCA8K_REG_GOL_TRUNK_CTRL(id), ++ QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN(id, i) | ++ QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT(id, i), ++ !delete << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i) | ++ port << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(id, i)); ++} ++ ++static int ++qca8k_port_lag_join(struct dsa_switch *ds, int port, ++ struct net_device *lag, ++ struct netdev_lag_upper_info *info) ++{ ++ int ret; ++ ++ if (!qca8k_lag_can_offload(ds, lag, info)) ++ return -EOPNOTSUPP; ++ ++ ret = qca8k_lag_setup_hash(ds, lag, info); ++ if (ret) ++ return ret; ++ ++ return qca8k_lag_refresh_portmap(ds, port, lag, false); ++} ++ ++static int ++qca8k_port_lag_leave(struct dsa_switch *ds, int port, ++ struct net_device *lag) ++{ ++ return qca8k_lag_refresh_portmap(ds, port, lag, true); ++} ++ + static const struct dsa_switch_ops qca8k_switch_ops = { + .get_tag_protocol = qca8k_get_tag_protocol, + .setup = qca8k_setup, +@@ -2236,6 +2411,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + .phylink_mac_link_down = qca8k_phylink_mac_link_down, + .phylink_mac_link_up = qca8k_phylink_mac_link_up, + .get_phy_flags = qca8k_get_phy_flags, ++ .port_lag_join = qca8k_port_lag_join, ++ .port_lag_leave = qca8k_port_lag_leave, + }; + + static int qca8k_read_switch_id(struct qca8k_priv *priv) +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 7c87a968c0104..ab4a417b25a9c 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -15,6 +15,8 @@ + #define QCA8K_NUM_PORTS 7 + #define QCA8K_NUM_CPU_PORTS 2 + #define QCA8K_MAX_MTU 9000 ++#define QCA8K_NUM_LAGS 4 ++#define QCA8K_NUM_PORTS_FOR_LAG 4 + + #define PHY_ID_QCA8327 0x004dd034 + #define QCA8K_ID_QCA8327 0x12 +@@ -122,6 +124,14 @@ + #define QCA8K_REG_EEE_CTRL 0x100 + #define QCA8K_REG_EEE_CTRL_LPI_EN(_i) ((_i + 1) * 2) + ++/* TRUNK_HASH_EN registers */ ++#define QCA8K_TRUNK_HASH_EN_CTRL 0x270 ++#define QCA8K_TRUNK_HASH_SIP_EN BIT(3) ++#define QCA8K_TRUNK_HASH_DIP_EN BIT(2) ++#define QCA8K_TRUNK_HASH_SA_EN BIT(1) ++#define QCA8K_TRUNK_HASH_DA_EN BIT(0) ++#define QCA8K_TRUNK_HASH_MASK GENMASK(3, 0) ++ + /* ACL registers */ + #define QCA8K_REG_PORT_VLAN_CTRL0(_i) (0x420 + (_i * 8)) + #define QCA8K_PORT_VLAN_CVID_MASK GENMASK(27, 16) +@@ -204,6 +214,28 @@ + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) + #define QCA8K_PORT_LOOKUP_ING_MIRROR_EN BIT(25) + ++#define QCA8K_REG_GOL_TRUNK_CTRL0 0x700 ++/* 4 max trunk first ++ * first 6 bit for member bitmap ++ * 7th bit is to enable trunk port ++ */ ++#define QCA8K_REG_GOL_TRUNK_SHIFT(_i) ((_i) * 8) ++#define QCA8K_REG_GOL_TRUNK_EN_MASK BIT(7) ++#define QCA8K_REG_GOL_TRUNK_EN(_i) (QCA8K_REG_GOL_TRUNK_EN_MASK << QCA8K_REG_GOL_TRUNK_SHIFT(_i)) ++#define QCA8K_REG_GOL_TRUNK_MEMBER_MASK GENMASK(6, 0) ++#define QCA8K_REG_GOL_TRUNK_MEMBER(_i) (QCA8K_REG_GOL_TRUNK_MEMBER_MASK << QCA8K_REG_GOL_TRUNK_SHIFT(_i)) ++/* 0x704 for TRUNK 0-1 --- 0x708 for TRUNK 2-3 */ ++#define QCA8K_REG_GOL_TRUNK_CTRL(_i) (0x704 + (((_i) / 2) * 4)) ++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_MASK GENMASK(3, 0) ++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK BIT(3) ++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK GENMASK(2, 0) ++#define QCA8K_REG_GOL_TRUNK_ID_SHIFT(_i) (((_i) / 2) * 16) ++#define QCA8K_REG_GOL_MEM_ID_SHIFT(_i) ((_i) * 4) ++/* Complex shift: FIRST shift for port THEN shift for trunk */ ++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(_i, _j) (QCA8K_REG_GOL_MEM_ID_SHIFT(_j) + QCA8K_REG_GOL_TRUNK_ID_SHIFT(_i)) ++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN(_i, _j) (QCA8K_REG_GOL_TRUNK_ID_MEM_ID_EN_MASK << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(_i, _j)) ++#define QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT(_i, _j) (QCA8K_REG_GOL_TRUNK_ID_MEM_ID_PORT_MASK << QCA8K_REG_GOL_TRUNK_ID_MEM_ID_SHIFT(_i, _j)) ++ + #define QCA8K_REG_GLOBAL_FC_THRESH 0x800 + #define QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK GENMASK(24, 16) + #define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) FIELD_PREP(QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK, x) +@@ -309,6 +341,7 @@ struct qca8k_priv { + u8 switch_revision; + u8 mirror_rx; + u8 mirror_tx; ++ u8 lag_hash_mode; + bool legacy_phy_port_mapping; + struct qca8k_ports_config ports_config; + struct regmap *regmap; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch b/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch new file mode 100644 index 0000000000..2bde440093 --- /dev/null +++ b/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch @@ -0,0 +1,45 @@ +From 0898ca67b86e14207d4feb3f3fea8b87cec5aab1 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 23 Nov 2021 16:44:46 +0100 +Subject: net: dsa: qca8k: fix warning in LAG feature + +Fix warning reported by bot. +Make sure hash is init to 0 and fix wrong logic for hash_type in +qca8k_lag_can_offload. + +Reported-by: kernel test robot +Fixes: def975307c01 ("net: dsa: qca8k: add LAG support") +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20211123154446.31019-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/qca8k.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 6516df08a5d5f..d04b25eca2503 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -2228,7 +2228,7 @@ qca8k_lag_can_offload(struct dsa_switch *ds, + if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) + return false; + +- if (info->hash_type != NETDEV_LAG_HASH_L2 || ++ if (info->hash_type != NETDEV_LAG_HASH_L2 && + info->hash_type != NETDEV_LAG_HASH_L23) + return false; + +@@ -2242,8 +2242,8 @@ qca8k_lag_setup_hash(struct dsa_switch *ds, + { + struct qca8k_priv *priv = ds->priv; + bool unique_lag = true; ++ u32 hash = 0; + int i, id; +- u32 hash; + + id = dsa_lag_id(ds->dst, lag); + +-- +cgit 1.2.3-1.el7 + From 81fdb6afe3e4068d8ebac127523b5c6175eb551a Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 8 Jan 2022 14:39:54 +0100 Subject: [PATCH 15/26] generic: 5.15: fix new AQR PHY patches After fixing the original 720 patch, it looks like more were added for additional AQR ID-s. Patches that add the additional AQR PHY ID-s is just copy/paste from 5.10 and kernel 5.11 dropped the ack_interrupt method for PHY IRQ handling, instead handle_interrupt is used. So, simply switch to using handle_interrupt like other upstream AQR PHY-s. Signed-off-by: Robert Marko --- .../722-net-phy-aquantia-enable-AQR112-and-AQR412.patch | 4 ++-- .../724-net-phy-aquantia-Add-AQR113-driver-support.patch | 2 +- ...725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index e3541400d7..6ab7bc7569 100644 --- a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -119,7 +119,7 @@ Signed-off-by: Alex Marginean + .probe = aqr107_probe, + .config_aneg = aqr_config_aneg_set_prot, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr107_read_status, + .get_sset_count = aqr107_get_sset_count, + .get_strings = aqr107_get_strings, @@ -131,7 +131,7 @@ Signed-off-by: Alex Marginean + .probe = aqr107_probe, + .config_aneg = aqr_config_aneg_set_prot, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr107_read_status, + .get_sset_count = aqr107_get_sset_count, + .get_strings = aqr107_get_strings, diff --git a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch index 7a661309f9..1fc7658ff3 100644 --- a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch @@ -26,7 +26,7 @@ Add a new entry for AQR113 PHY_ID + .name = "Aquantia AQR113", + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr107_read_status, +}, +{ diff --git a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index 40ad0ff583..ba9f3ee120 100644 --- a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -30,7 +30,7 @@ Signed-off-by: Daniel Golle + .probe = aqr107_probe, + .config_aneg = aqr_config_aneg_set_prot, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr107_read_status, + .get_sset_count = aqr107_get_sset_count, + .get_strings = aqr107_get_strings, @@ -42,7 +42,7 @@ Signed-off-by: Daniel Golle + .probe = aqr107_probe, + .config_aneg = aqr_config_aneg_set_prot, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr107_read_status, + .get_sset_count = aqr107_get_sset_count, + .get_strings = aqr107_get_strings, From 71efd34700e59f553367abb1b5de28c01f4c2d12 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 6 Mar 2022 12:33:35 +0100 Subject: [PATCH 16/26] generic: 5.15: fix AQR 113C and 813 Patches that add the additional AQR PHY ID-s is just copy/paste from 5.10 and kernel 5.11 dropped the ack_interrupt method for PHY IRQ handling, instead handle_interrupt is used. So, simply switch to using handle_interrupt like other upstream AQR PHY-s. Signed-off-by: Robert Marko Signed-off-by: Ansuel Smith --- target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch index 4d4420aa2f..979308a908 100644 --- a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch +++ b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch @@ -89,7 +89,7 @@ Signed-off-by: Birger Koblitz + .config_init = aqr107_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr113c_read_status, + .get_tunable = aqr107_get_tunable, + .set_tunable = aqr107_set_tunable, @@ -115,7 +115,7 @@ Signed-off-by: Birger Koblitz + .config_init = aqr107_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, ++ .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr113c_read_status, + .get_tunable = aqr107_get_tunable, + .set_tunable = aqr107_set_tunable, From 30a5e073906ab671c31063cb0deed00686369277 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 7 Jan 2022 17:39:42 +0000 Subject: [PATCH 17/26] generic: 5.15: get uImage.FIT partition parser ready Prepare uImage.FIT partition parser for Linux 5.15 Signed-off-by: Daniel Golle Signed-off-by: Ansuel Smith --- .../generic/files/block/partitions/fit.c | 10 ++- ...don-t-reply-on-mtdblock-device-minor.patch | 84 ------------------- ...rans-call-add-disks-after-mtd-device.patch | 14 ++-- .../410-block-fit-partition-parser.patch | 67 ++++----------- .../420-mtd-set-rootfs-to-be-root-dev.patch | 5 +- 5 files changed, 31 insertions(+), 149 deletions(-) delete mode 100644 target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch diff --git a/target/linux/generic/files/block/partitions/fit.c b/target/linux/generic/files/block/partitions/fit.c index 75516af493..46ccef62ee 100644 --- a/target/linux/generic/files/block/partitions/fit.c +++ b/target/linux/generic/files/block/partitions/fit.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "check.h" @@ -72,7 +73,12 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector, u64 sectors, int *slot, int add_remain) { - struct address_space *mapping = state->bdev->bd_inode->i_mapping; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) + struct block_device *bdev = state->disk->part0; +#else + struct block_device *bdev = state->bdev; +#endif + struct address_space *mapping = bdev->bd_inode->i_mapping; struct page *page; void *fit, *init_fit; struct partition_meta_info *info; @@ -116,7 +122,7 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector, return 0; } - dsectors = get_capacity(state->bdev->bd_disk); + dsectors = get_capacity(bdev->bd_disk); if (sectors) dsectors = (dsectors>sectors)?sectors:dsectors; diff --git a/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch b/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch deleted file mode 100644 index 8f985c0b8f..0000000000 --- a/target/linux/generic/hack-5.15/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch +++ /dev/null @@ -1,84 +0,0 @@ -From f9760b158f610b1792a222cc924073724c061bfb Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 7 Apr 2021 22:37:57 +0100 -Subject: [PATCH 1/2] mtd: super: don't reply on mtdblock device minor -To: linux-mtd@lists.infradead.org -Cc: Vignesh Raghavendra , - Richard Weinberger , - Miquel Raynal , - David Woodhouse - -For blktrans devices with partitions (ie. part_bits != 0) the -assumption that the minor number of the mtdblock device matches -the mtdnum doesn't hold true. -Properly resolve mtd device from blktrans layer instead. - -Signed-off-by: Daniel Golle ---- - drivers/mtd/mtdsuper.c | 33 ++++++++++++++++++++++++++------- - 1 file changed, 26 insertions(+), 7 deletions(-) - ---- a/drivers/mtd/mtdsuper.c -+++ b/drivers/mtd/mtdsuper.c -@@ -9,6 +9,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -120,8 +121,9 @@ int get_tree_mtd(struct fs_context *fc, - struct fs_context *fc)) - { - #ifdef CONFIG_BLOCK -- dev_t dev; -- int ret; -+ struct mtd_blktrans_dev *blktrans_dev; -+ struct block_device *bdev; -+ int ret, part_bits; - #endif - int mtdnr; - -@@ -169,16 +171,36 @@ int get_tree_mtd(struct fs_context *fc, - /* try the old way - the hack where we allowed users to mount - * /dev/mtdblock$(n) but didn't actually _use_ the blockdev - */ -- ret = lookup_bdev(fc->source, &dev); -- if (ret) { -+ bdev = blkdev_get_by_path(fc->source, FMODE_READ, NULL); -+ if (IS_ERR(bdev)) { -+ ret = PTR_ERR(bdev); - errorf(fc, "MTD: Couldn't look up '%s': %d", fc->source, ret); - return ret; - } -- pr_debug("MTDSB: lookup_bdev() returned 0\n"); -+ pr_debug("MTDSB: blkdev_get_by_path() returned 0\n"); - -- if (MAJOR(dev) == MTD_BLOCK_MAJOR) -- return mtd_get_sb_by_nr(fc, MINOR(dev), fill_super); -+ if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { -+ if (!bdev->bd_disk) { -+ blkdev_put(bdev, FMODE_READ); -+ BUG(); -+ return -EINVAL; -+ } - -+ blktrans_dev = (struct mtd_blktrans_dev *)(bdev->bd_disk->private_data); -+ if (!blktrans_dev || !blktrans_dev->tr) { -+ blkdev_put(bdev, FMODE_READ); -+ BUG(); -+ return -EINVAL; -+ } -+ mtdnr = blktrans_dev->devnum; -+ part_bits = blktrans_dev->tr->part_bits; -+ blkdev_put(bdev, FMODE_READ); -+ if (MINOR(bdev->bd_dev) != (mtdnr << part_bits)) -+ return -EINVAL; -+ -+ return mtd_get_sb_by_nr(fc, mtdnr, fill_super); -+ } -+ blkdev_put(bdev, FMODE_READ); - #endif /* CONFIG_BLOCK */ - - if (!(fc->sb_flags & SB_SILENT)) diff --git a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch index a715d17f3b..c9821b57eb 100644 --- a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch +++ b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -25,7 +25,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c -@@ -457,13 +457,6 @@ int add_mtd_blktrans_dev(struct mtd_blkt +@@ -384,13 +384,6 @@ int add_mtd_blktrans_dev(struct mtd_blkt if (new->readonly) set_disk_ro(gd, 1); @@ -37,9 +37,9 @@ Signed-off-by: Daniel Golle - WARN_ON(ret); - } return 0; - error4: - kfree(new->tag_set); -@@ -475,6 +468,27 @@ error1: + + out_free_tag_set: +@@ -402,6 +395,27 @@ out_list_del: return ret; } @@ -77,9 +77,9 @@ Signed-off-by: Daniel Golle #include "mtdcore.h" -@@ -851,6 +852,8 @@ int mtd_device_parse_register(struct mtd - register_reboot_notifier(&mtd->reboot_notifier); - } +@@ -1000,6 +1001,8 @@ int mtd_device_parse_register(struct mtd + + ret = mtd_otp_nvmem_add(mtd); + register_mtd_blktrans_devs(); + diff --git a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch index b8cada98e6..65438807de 100644 --- a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch +++ b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch @@ -80,10 +80,10 @@ +#ifdef CONFIG_FIT_PARTITION + if ((state->parts[p].flags & ADDPART_FLAG_ROOTDEV) && ROOT_DEV == 0) -+ ROOT_DEV = part_to_dev(part)->devt; ++ ROOT_DEV = part->bd_dev; + + if (state->parts[p].flags & ADDPART_FLAG_READONLY) -+ part->policy = true; ++ set_disk_ro(disk, true); +#endif + return true; @@ -91,20 +91,8 @@ --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -396,7 +396,11 @@ int ubiblock_create(struct ubi_volume_in - - gd->fops = &ubiblock_ops; - gd->major = ubiblock_major; -+#ifdef CONFIG_FIT_PARTITION -+ gd->minors = 0; -+#else - gd->minors = 1; -+#endif - gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL); - if (gd->first_minor < 0) { - dev_err(disk_to_dev(gd), @@ -413,6 +417,9 @@ int ubiblock_create(struct ubi_volume_in - goto out_put_disk; + goto out_cleanup_disk; } gd->private_data = dev; +#ifdef CONFIG_FIT_PARTITION @@ -113,6 +101,18 @@ sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); set_capacity(gd, disk_capacity); dev->gd = gd; +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -345,6 +345,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) + gd->first_minor = (new->devnum) << tr->part_bits; + gd->minors = 1 << tr->part_bits; + gd->fops = &mtd_block_ops; ++#ifdef CONFIG_FIT_PARTITION ++ gd->flags |= GENHD_FL_EXT_DEVT; ++#endif + + if (tr->part_bits) + if (new->devnum < 26) --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -706,6 +706,9 @@ int efi_partition(struct parsed_partitio @@ -149,43 +149,6 @@ typedef struct _gpt_header { __le64 signature; ---- a/drivers/mtd/mtdblock.c -+++ b/drivers/mtd/mtdblock.c -@@ -334,7 +334,11 @@ static void mtdblock_remove_dev(struct m - static struct mtd_blktrans_ops mtdblock_tr = { - .name = "mtdblock", - .major = MTD_BLOCK_MAJOR, -+#ifdef CONFIG_FIT_PARTITION -+ .part_bits = 2, -+#else - .part_bits = 0, -+#endif - .blksize = 512, - .open = mtdblock_open, - .flush = mtdblock_flush, ---- a/drivers/mtd/mtd_blkdevs.c -+++ b/drivers/mtd/mtd_blkdevs.c -@@ -407,18 +407,8 @@ int add_mtd_blktrans_dev(struct mtd_blkt - gd->first_minor = (new->devnum) << tr->part_bits; - gd->fops = &mtd_block_ops; - -- if (tr->part_bits) -- if (new->devnum < 26) -- snprintf(gd->disk_name, sizeof(gd->disk_name), -- "%s%c", tr->name, 'a' + new->devnum); -- else -- snprintf(gd->disk_name, sizeof(gd->disk_name), -- "%s%c%c", tr->name, -- 'a' - 1 + new->devnum / 26, -- 'a' + new->devnum % 26); -- else -- snprintf(gd->disk_name, sizeof(gd->disk_name), -- "%s%d", tr->name, new->devnum); -+ snprintf(gd->disk_name, sizeof(gd->disk_name), -+ "%s%d", tr->name, new->devnum); - - set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); - --- a/block/partitions/msdos.c +++ b/block/partitions/msdos.c @@ -563,6 +563,15 @@ static void parse_minix(struct parsed_pa diff --git a/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch b/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch index b071ac61ec..80122277e9 100644 --- a/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch +++ b/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch @@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos #include #include -@@ -694,6 +695,19 @@ int add_mtd_device(struct mtd_info *mtd) +@@ -694,6 +695,16 @@ int add_mtd_device(struct mtd_info *mtd) of this try_ nonsense, and no bitching about it either. :) */ __module_get(THIS_MODULE); @@ -31,9 +31,6 @@ Signed-off-by: Gabor Juhos + unsigned int index = mtd->index; + pr_notice("mtd: device %d (%s) set to be root filesystem\n", + mtd->index, mtd->name); -+#ifdef CONFIG_FIT_PARTITION -+ index <<= 2; -+#endif + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, index); + } + From 327b6dbd98ed98be04eb891d9682ae212fe9f09d Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Wed, 2 Feb 2022 22:32:57 +0100 Subject: [PATCH 18/26] generic: 5.15: backport mdio improvement patch for qca8k Backport qca8k mdio improvement patch merged upstream, where we use eth packet when available to send mdio commands. This should improve speed and cause less load on the CPU. Signed-off-by: Ansuel Smith --- ...uce-tagger-owned-storage-for-private.patch | 290 ++++++++++++++ ...ocols-connect-to-individual-switches.patch | 285 ++++++++++++++ ...PHY-initialization-with-MTU-setup-in.patch | 57 +++ ...nl_lock-sections-in-dsa_slave_create.patch | 39 ++ ...op-updating-master-MTU-from-master.c.patch | 96 +++++ ...l_mutex-when-calling-dsa_master_-set.patch | 85 ++++ ...t-up-shared-ports-then-non-shared-po.patch | 123 ++++++ ...xt-net-dsa-setup-master-before-ports.patch | 120 ++++++ ...switch-operations-for-tracking-the-m.patch | 267 +++++++++++++ ...aster-state-events-in-dsa_tree_-setu.patch | 94 +++++ ...t-dsa-tag_qca-convert-to-FIELD-macro.patch | 92 +++++ ...qca-move-define-to-include-linux-dsa.patch | 79 ++++ ...ag_qca-enable-promisc_on_master-flag.patch | 32 ++ ...add-define-for-handling-mgmt-Etherne.patch | 117 ++++++ ...a-add-define-for-handling-MIB-packet.patch | 52 +++ ...add-support-for-handling-mgmt-and-MI.patch | 123 ++++++ ...8k-add-tracking-state-of-master-port.patch | 74 ++++ ...d-support-for-mgmt-read-write-in-Eth.patch | 370 ++++++++++++++++++ ...d-support-for-mib-autocast-in-Ethern.patch | 233 +++++++++++ ...d-support-for-phy-read-write-with-mg.patch | 294 ++++++++++++++ ...qca8k-move-page-cache-to-driver-priv.patch | 215 ++++++++++ ...qca8k-cache-lo-and-hi-for-mdio-write.patch | 171 ++++++++ ...d-support-for-larger-read-write-size.patch | 211 ++++++++++ ...troduce-qca8k_bulk_read-write-functi.patch | 109 ++++++ 24 files changed, 3628 insertions(+) create mode 100644 target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch create mode 100644 target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch create mode 100644 target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch create mode 100644 target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch create mode 100644 target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch create mode 100644 target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch create mode 100644 target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch create mode 100644 target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch create mode 100644 target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch create mode 100644 target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch create mode 100644 target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch create mode 100644 target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch create mode 100644 target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch create mode 100644 target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch create mode 100644 target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch create mode 100644 target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch create mode 100644 target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch create mode 100644 target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch create mode 100644 target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch create mode 100644 target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch create mode 100644 target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch create mode 100644 target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch create mode 100644 target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch create mode 100644 target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch diff --git a/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch b/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch new file mode 100644 index 0000000000..019d0d5ee8 --- /dev/null +++ b/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch @@ -0,0 +1,290 @@ +From dc452a471dbae8aca8257c565174212620880093 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Fri, 10 Dec 2021 01:34:37 +0200 +Subject: net: dsa: introduce tagger-owned storage for private and shared data + +Ansuel is working on register access over Ethernet for the qca8k switch +family. This requires the qca8k tagging protocol driver to receive +frames which aren't intended for the network stack, but instead for the +qca8k switch driver itself. + +The dp->priv is currently the prevailing method for passing data back +and forth between the tagging protocol driver and the switch driver. +However, this method is riddled with caveats. + +The DSA design allows in principle for any switch driver to return any +protocol it desires in ->get_tag_protocol(). The dsa_loop driver can be +modified to do just that. But in the current design, the memory behind +dp->priv has to be allocated by the switch driver, so if the tagging +protocol is paired to an unexpected switch driver, we may end up in NULL +pointer dereferences inside the kernel, or worse (a switch driver may +allocate dp->priv according to the expectations of a different tagger). + +The latter possibility is even more plausible considering that DSA +switches can dynamically change tagging protocols in certain cases +(dsa <-> edsa, ocelot <-> ocelot-8021q), and the current design lends +itself to mistakes that are all too easy to make. + +This patch proposes that the tagging protocol driver should manage its +own memory, instead of relying on the switch driver to do so. +After analyzing the different in-tree needs, it can be observed that the +required tagger storage is per switch, therefore a ds->tagger_data +pointer is introduced. In principle, per-port storage could also be +introduced, although there is no need for it at the moment. Future +changes will replace the current usage of dp->priv with ds->tagger_data. + +We define a "binding" event between the DSA switch tree and the tagging +protocol. During this binding event, the tagging protocol's ->connect() +method is called first, and this may allocate some memory for each +switch of the tree. Then a cross-chip notifier is emitted for the +switches within that tree, and they are given the opportunity to fix up +the tagger's memory (for example, they might set up some function +pointers that represent virtual methods for consuming packets). +Because the memory is owned by the tagger, there exists a ->disconnect() +method for the tagger (which is the place to free the resources), but +there doesn't exist a ->disconnect() method for the switch driver. +This is part of the design. The switch driver should make minimal use of +the public part of the tagger data, and only after type-checking it +using the supplied "proto" argument. + +In the code there are in fact two binding events, one is the initial +event in dsa_switch_setup_tag_protocol(). At this stage, the cross chip +notifier chains aren't initialized, so we call each switch's connect() +method by hand. Then there is dsa_tree_bind_tag_proto() during +dsa_tree_change_tag_proto(), and here we have an old protocol and a new +one. We first connect to the new one before disconnecting from the old +one, to simplify error handling a bit and to ensure we remain in a valid +state at all times. + +Co-developed-by: Ansuel Smith +Signed-off-by: Ansuel Smith +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 12 +++++++++ + net/dsa/dsa2.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++--- + net/dsa/dsa_priv.h | 1 + + net/dsa/switch.c | 14 +++++++++++ + 4 files changed, 96 insertions(+), 4 deletions(-) + +diff --git a/include/net/dsa.h b/include/net/dsa.h +index bdf308a5c55ee..8b496c7e62ef8 100644 +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -82,12 +82,15 @@ enum dsa_tag_protocol { + }; + + struct dsa_switch; ++struct dsa_switch_tree; + + struct dsa_device_ops { + struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); + struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev); + void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, + int *offset); ++ int (*connect)(struct dsa_switch_tree *dst); ++ void (*disconnect)(struct dsa_switch_tree *dst); + unsigned int needed_headroom; + unsigned int needed_tailroom; + const char *name; +@@ -337,6 +340,8 @@ struct dsa_switch { + */ + void *priv; + ++ void *tagger_data; ++ + /* + * Configuration data for this switch. + */ +@@ -689,6 +694,13 @@ struct dsa_switch_ops { + enum dsa_tag_protocol mprot); + int (*change_tag_protocol)(struct dsa_switch *ds, int port, + enum dsa_tag_protocol proto); ++ /* ++ * Method for switch drivers to connect to the tagging protocol driver ++ * in current use. The switch driver can provide handlers for certain ++ * types of packets for switch management. ++ */ ++ int (*connect_tag_protocol)(struct dsa_switch *ds, ++ enum dsa_tag_protocol proto); + + /* Optional switch-wide initialization and destruction methods */ + int (*setup)(struct dsa_switch *ds); +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index 8814fa0e44c84..cf65661686209 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -248,8 +248,12 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index) + + static void dsa_tree_free(struct dsa_switch_tree *dst) + { +- if (dst->tag_ops) ++ if (dst->tag_ops) { ++ if (dst->tag_ops->disconnect) ++ dst->tag_ops->disconnect(dst); ++ + dsa_tag_driver_put(dst->tag_ops); ++ } + list_del(&dst->list); + kfree(dst); + } +@@ -822,7 +826,7 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) + int err; + + if (tag_ops->proto == dst->default_proto) +- return 0; ++ goto connect; + + dsa_switch_for_each_cpu_port(cpu_dp, ds) { + rtnl_lock(); +@@ -836,6 +840,17 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) + } + } + ++connect: ++ if (ds->ops->connect_tag_protocol) { ++ err = ds->ops->connect_tag_protocol(ds, tag_ops->proto); ++ if (err) { ++ dev_err(ds->dev, ++ "Unable to connect to tag protocol \"%s\": %pe\n", ++ tag_ops->name, ERR_PTR(err)); ++ return err; ++ } ++ } ++ + return 0; + } + +@@ -1136,6 +1151,46 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) + dst->setup = false; + } + ++static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, ++ const struct dsa_device_ops *tag_ops) ++{ ++ const struct dsa_device_ops *old_tag_ops = dst->tag_ops; ++ struct dsa_notifier_tag_proto_info info; ++ int err; ++ ++ dst->tag_ops = tag_ops; ++ ++ /* Notify the new tagger about the connection to this tree */ ++ if (tag_ops->connect) { ++ err = tag_ops->connect(dst); ++ if (err) ++ goto out_revert; ++ } ++ ++ /* Notify the switches from this tree about the connection ++ * to the new tagger ++ */ ++ info.tag_ops = tag_ops; ++ err = dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_CONNECT, &info); ++ if (err && err != -EOPNOTSUPP) ++ goto out_disconnect; ++ ++ /* Notify the old tagger about the disconnection from this tree */ ++ if (old_tag_ops->disconnect) ++ old_tag_ops->disconnect(dst); ++ ++ return 0; ++ ++out_disconnect: ++ /* Revert the new tagger's connection to this tree */ ++ if (tag_ops->disconnect) ++ tag_ops->disconnect(dst); ++out_revert: ++ dst->tag_ops = old_tag_ops; ++ ++ return err; ++} ++ + /* Since the dsa/tagging sysfs device attribute is per master, the assumption + * is that all DSA switches within a tree share the same tagger, otherwise + * they would have formed disjoint trees (different "dsa,member" values). +@@ -1168,12 +1223,15 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, + goto out_unlock; + } + ++ /* Notify the tag protocol change */ + info.tag_ops = tag_ops; + err = dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO, &info); + if (err) +- goto out_unwind_tagger; ++ return err; + +- dst->tag_ops = tag_ops; ++ err = dsa_tree_bind_tag_proto(dst, tag_ops); ++ if (err) ++ goto out_unwind_tagger; + + rtnl_unlock(); + +@@ -1260,6 +1318,7 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, + struct dsa_switch_tree *dst = ds->dst; + const struct dsa_device_ops *tag_ops; + enum dsa_tag_protocol default_proto; ++ int err; + + /* Find out which protocol the switch would prefer. */ + default_proto = dsa_get_tag_protocol(dp, master); +@@ -1307,6 +1366,12 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, + */ + dsa_tag_driver_put(tag_ops); + } else { ++ if (tag_ops->connect) { ++ err = tag_ops->connect(dst); ++ if (err) ++ return err; ++ } ++ + dst->tag_ops = tag_ops; + } + +diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h +index 38ce5129a33dc..0db2b26b0c83c 100644 +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -37,6 +37,7 @@ enum { + DSA_NOTIFIER_VLAN_DEL, + DSA_NOTIFIER_MTU, + DSA_NOTIFIER_TAG_PROTO, ++ DSA_NOTIFIER_TAG_PROTO_CONNECT, + DSA_NOTIFIER_MRP_ADD, + DSA_NOTIFIER_MRP_DEL, + DSA_NOTIFIER_MRP_ADD_RING_ROLE, +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index 9c92edd969612..06948f5368296 100644 +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -647,6 +647,17 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds, + return 0; + } + ++static int dsa_switch_connect_tag_proto(struct dsa_switch *ds, ++ struct dsa_notifier_tag_proto_info *info) ++{ ++ const struct dsa_device_ops *tag_ops = info->tag_ops; ++ ++ if (!ds->ops->connect_tag_protocol) ++ return -EOPNOTSUPP; ++ ++ return ds->ops->connect_tag_protocol(ds, tag_ops->proto); ++} ++ + static int dsa_switch_mrp_add(struct dsa_switch *ds, + struct dsa_notifier_mrp_info *info) + { +@@ -766,6 +777,9 @@ static int dsa_switch_event(struct notifier_block *nb, + case DSA_NOTIFIER_TAG_PROTO: + err = dsa_switch_change_tag_proto(ds, info); + break; ++ case DSA_NOTIFIER_TAG_PROTO_CONNECT: ++ err = dsa_switch_connect_tag_proto(ds, info); ++ break; + case DSA_NOTIFIER_MRP_ADD: + err = dsa_switch_mrp_add(ds, info); + break; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch b/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch new file mode 100644 index 0000000000..fa3752ac34 --- /dev/null +++ b/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch @@ -0,0 +1,285 @@ +From 7f2973149c22e7a6fee4c0c9fa6b8e4108e9c208 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 14 Dec 2021 03:45:36 +0200 +Subject: net: dsa: make tagging protocols connect to individual switches from + a tree + +On the NXP Bluebox 3 board which uses a multi-switch setup with sja1105, +the mechanism through which the tagger connects to the switch tree is +broken, due to improper DSA code design. At the time when tag_ops->connect() +is called in dsa_port_parse_cpu(), DSA hasn't finished "touching" all +the ports, so it doesn't know how large the tree is and how many ports +it has. It has just seen the first CPU port by this time. As a result, +this function will call the tagger's ->connect method too early, and the +tagger will connect only to the first switch from the tree. + +This could be perhaps addressed a bit more simply by just moving the +tag_ops->connect(dst) call a bit later (for example in dsa_tree_setup), +but there is already a design inconsistency at present: on the switch +side, the notification is on a per-switch basis, but on the tagger side, +it is on a per-tree basis. Furthermore, the persistent storage itself is +per switch (ds->tagger_data). And the tagger connect and disconnect +procedures (at least the ones that exist currently) could see a fair bit +of simplification if they didn't have to iterate through the switches of +a tree. + +To fix the issue, this change transforms tag_ops->connect(dst) into +tag_ops->connect(ds) and moves it somewhere where we already iterate +over all switches of a tree. That is in dsa_switch_setup_tag_protocol(), +which is a good placement because we already have there the connection +call to the switch side of things. + +As for the dsa_tree_bind_tag_proto() method (called from the code path +that changes the tag protocol), things are a bit more complicated +because we receive the tree as argument, yet when we unwind on errors, +it would be nice to not call tag_ops->disconnect(ds) where we didn't +previously call tag_ops->connect(ds). We didn't have this problem before +because the tag_ops connection operations passed the entire dst before, +and this is more fine grained now. To solve the error rewind case using +the new API, we have to create yet one more cross-chip notifier for +disconnection, and stay connected with the old tag protocol to all the +switches in the tree until we've succeeded to connect with the new one +as well. So if something fails half way, the whole tree is still +connected to the old tagger. But there may still be leaks if the tagger +fails to connect to the 2nd out of 3 switches in a tree: somebody needs +to tell the tagger to disconnect from the first switch. Nothing comes +for free, and this was previously handled privately by the tagging +protocol driver before, but now we need to emit a disconnect cross-chip +notifier for that, because DSA has to take care of the unwind path. We +assume that the tagging protocol has connected to a switch if it has set +ds->tagger_data to something, otherwise we avoid calling its +disconnection method in the error rewind path. + +The rest of the changes are in the tagging protocol drivers, and have to +do with the replacement of dst with ds. The iteration is removed and the +error unwind path is simplified, as mentioned above. + +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 5 ++-- + net/dsa/dsa2.c | 44 +++++++++++++----------------- + net/dsa/dsa_priv.h | 1 + + net/dsa/switch.c | 52 ++++++++++++++++++++++++++++++++--- + net/dsa/tag_ocelot_8021q.c | 53 +++++++++++------------------------- + net/dsa/tag_sja1105.c | 67 ++++++++++++++++------------------------------ + 6 files changed, 109 insertions(+), 113 deletions(-) + +diff --git a/include/net/dsa.h b/include/net/dsa.h +index 64d71968aa91a..f16959444ae12 100644 +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -82,15 +82,14 @@ enum dsa_tag_protocol { + }; + + struct dsa_switch; +-struct dsa_switch_tree; + + struct dsa_device_ops { + struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); + struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev); + void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, + int *offset); +- int (*connect)(struct dsa_switch_tree *dst); +- void (*disconnect)(struct dsa_switch_tree *dst); ++ int (*connect)(struct dsa_switch *ds); ++ void (*disconnect)(struct dsa_switch *ds); + unsigned int needed_headroom; + unsigned int needed_tailroom; + const char *name; +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index cf65661686209..c18b22c0bf55e 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -248,12 +248,8 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index) + + static void dsa_tree_free(struct dsa_switch_tree *dst) + { +- if (dst->tag_ops) { +- if (dst->tag_ops->disconnect) +- dst->tag_ops->disconnect(dst); +- ++ if (dst->tag_ops) + dsa_tag_driver_put(dst->tag_ops); +- } + list_del(&dst->list); + kfree(dst); + } +@@ -841,17 +837,29 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) + } + + connect: ++ if (tag_ops->connect) { ++ err = tag_ops->connect(ds); ++ if (err) ++ return err; ++ } ++ + if (ds->ops->connect_tag_protocol) { + err = ds->ops->connect_tag_protocol(ds, tag_ops->proto); + if (err) { + dev_err(ds->dev, + "Unable to connect to tag protocol \"%s\": %pe\n", + tag_ops->name, ERR_PTR(err)); +- return err; ++ goto disconnect; + } + } + + return 0; ++ ++disconnect: ++ if (tag_ops->disconnect) ++ tag_ops->disconnect(ds); ++ ++ return err; + } + + static int dsa_switch_setup(struct dsa_switch *ds) +@@ -1160,13 +1168,6 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, + + dst->tag_ops = tag_ops; + +- /* Notify the new tagger about the connection to this tree */ +- if (tag_ops->connect) { +- err = tag_ops->connect(dst); +- if (err) +- goto out_revert; +- } +- + /* Notify the switches from this tree about the connection + * to the new tagger + */ +@@ -1176,16 +1177,14 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, + goto out_disconnect; + + /* Notify the old tagger about the disconnection from this tree */ +- if (old_tag_ops->disconnect) +- old_tag_ops->disconnect(dst); ++ info.tag_ops = old_tag_ops; ++ dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_DISCONNECT, &info); + + return 0; + + out_disconnect: +- /* Revert the new tagger's connection to this tree */ +- if (tag_ops->disconnect) +- tag_ops->disconnect(dst); +-out_revert: ++ info.tag_ops = tag_ops; ++ dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_DISCONNECT, &info); + dst->tag_ops = old_tag_ops; + + return err; +@@ -1318,7 +1317,6 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, + struct dsa_switch_tree *dst = ds->dst; + const struct dsa_device_ops *tag_ops; + enum dsa_tag_protocol default_proto; +- int err; + + /* Find out which protocol the switch would prefer. */ + default_proto = dsa_get_tag_protocol(dp, master); +@@ -1366,12 +1364,6 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, + */ + dsa_tag_driver_put(tag_ops); + } else { +- if (tag_ops->connect) { +- err = tag_ops->connect(dst); +- if (err) +- return err; +- } +- + dst->tag_ops = tag_ops; + } + +diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h +index 0db2b26b0c83c..edfaae7b59672 100644 +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -38,6 +38,7 @@ enum { + DSA_NOTIFIER_MTU, + DSA_NOTIFIER_TAG_PROTO, + DSA_NOTIFIER_TAG_PROTO_CONNECT, ++ DSA_NOTIFIER_TAG_PROTO_DISCONNECT, + DSA_NOTIFIER_MRP_ADD, + DSA_NOTIFIER_MRP_DEL, + DSA_NOTIFIER_MRP_ADD_RING_ROLE, +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index 06948f5368296..393f2d8a860a9 100644 +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -647,15 +647,58 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds, + return 0; + } + +-static int dsa_switch_connect_tag_proto(struct dsa_switch *ds, +- struct dsa_notifier_tag_proto_info *info) ++/* We use the same cross-chip notifiers to inform both the tagger side, as well ++ * as the switch side, of connection and disconnection events. ++ * Since ds->tagger_data is owned by the tagger, it isn't a hard error if the ++ * switch side doesn't support connecting to this tagger, and therefore, the ++ * fact that we don't disconnect the tagger side doesn't constitute a memory ++ * leak: the tagger will still operate with persistent per-switch memory, just ++ * with the switch side unconnected to it. What does constitute a hard error is ++ * when the switch side supports connecting but fails. ++ */ ++static int ++dsa_switch_connect_tag_proto(struct dsa_switch *ds, ++ struct dsa_notifier_tag_proto_info *info) + { + const struct dsa_device_ops *tag_ops = info->tag_ops; ++ int err; ++ ++ /* Notify the new tagger about the connection to this switch */ ++ if (tag_ops->connect) { ++ err = tag_ops->connect(ds); ++ if (err) ++ return err; ++ } + + if (!ds->ops->connect_tag_protocol) + return -EOPNOTSUPP; + +- return ds->ops->connect_tag_protocol(ds, tag_ops->proto); ++ /* Notify the switch about the connection to the new tagger */ ++ err = ds->ops->connect_tag_protocol(ds, tag_ops->proto); ++ if (err) { ++ /* Revert the new tagger's connection to this tree */ ++ if (tag_ops->disconnect) ++ tag_ops->disconnect(ds); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int ++dsa_switch_disconnect_tag_proto(struct dsa_switch *ds, ++ struct dsa_notifier_tag_proto_info *info) ++{ ++ const struct dsa_device_ops *tag_ops = info->tag_ops; ++ ++ /* Notify the tagger about the disconnection from this switch */ ++ if (tag_ops->disconnect && ds->tagger_data) ++ tag_ops->disconnect(ds); ++ ++ /* No need to notify the switch, since it shouldn't have any ++ * resources to tear down ++ */ ++ return 0; + } + + static int dsa_switch_mrp_add(struct dsa_switch *ds, +@@ -780,6 +823,9 @@ static int dsa_switch_event(struct notifier_block *nb, + case DSA_NOTIFIER_TAG_PROTO_CONNECT: + err = dsa_switch_connect_tag_proto(ds, info); + break; ++ case DSA_NOTIFIER_TAG_PROTO_DISCONNECT: ++ err = dsa_switch_disconnect_tag_proto(ds, info); ++ break; + case DSA_NOTIFIER_MRP_ADD: + err = dsa_switch_mrp_add(ds, info); + break; +-- +cgit 1.2.3-1.el7 + diff --git a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch new file mode 100644 index 0000000000..25c6ac2e8f --- /dev/null +++ b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch @@ -0,0 +1,57 @@ +From 904e112ad431492b34f235f59738e8312802bbf9 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 6 Jan 2022 01:11:12 +0200 +Subject: [PATCH 1/6] net: dsa: reorder PHY initialization with MTU setup in + slave.c + +In dsa_slave_create() there are 2 sections that take rtnl_lock(): +MTU change and netdev registration. They are separated by PHY +initialization. + +There isn't any strict ordering requirement except for the fact that +netdev registration should be last. Therefore, we can perform the MTU +change a bit later, after the PHY setup. A future change will then be +able to merge the two rtnl_lock sections into one. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/slave.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/net/dsa/slave.c b/net/dsa/slave.c +index 88f7b8686dac..88bcdba92fa7 100644 +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2011,13 +2011,6 @@ int dsa_slave_create(struct dsa_port *port) + port->slave = slave_dev; + dsa_slave_setup_tagger(slave_dev); + +- rtnl_lock(); +- ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN); +- rtnl_unlock(); +- if (ret && ret != -EOPNOTSUPP) +- dev_warn(ds->dev, "nonfatal error %d setting MTU to %d on port %d\n", +- ret, ETH_DATA_LEN, port->index); +- + netif_carrier_off(slave_dev); + + ret = dsa_slave_phy_setup(slave_dev); +@@ -2028,6 +2021,13 @@ int dsa_slave_create(struct dsa_port *port) + goto out_gcells; + } + ++ rtnl_lock(); ++ ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN); ++ rtnl_unlock(); ++ if (ret && ret != -EOPNOTSUPP) ++ dev_warn(ds->dev, "nonfatal error %d setting MTU to %d on port %d\n", ++ ret, ETH_DATA_LEN, port->index); ++ + rtnl_lock(); + + ret = register_netdevice(slave_dev); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch new file mode 100644 index 0000000000..c383bd93fb --- /dev/null +++ b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch @@ -0,0 +1,39 @@ +From e31dbd3b6aba585231cd84a87adeb22e7c6a8c19 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 6 Jan 2022 01:11:13 +0200 +Subject: [PATCH 2/6] net: dsa: merge rtnl_lock sections in dsa_slave_create + +Currently dsa_slave_create() has two sequences of rtnl_lock/rtnl_unlock +in a row. Remove the rtnl_unlock() and rtnl_lock() in between, such that +the operation can execute slighly faster. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/slave.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/net/dsa/slave.c b/net/dsa/slave.c +index 88bcdba92fa7..22241afcac81 100644 +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2022,14 +2022,12 @@ int dsa_slave_create(struct dsa_port *port) + } + + rtnl_lock(); ++ + ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN); +- rtnl_unlock(); + if (ret && ret != -EOPNOTSUPP) + dev_warn(ds->dev, "nonfatal error %d setting MTU to %d on port %d\n", + ret, ETH_DATA_LEN, port->index); + +- rtnl_lock(); +- + ret = register_netdevice(slave_dev); + if (ret) { + netdev_err(master, "error %d registering interface %s\n", +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch b/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch new file mode 100644 index 0000000000..c81bedaaf8 --- /dev/null +++ b/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch @@ -0,0 +1,96 @@ +From a1ff94c2973c43bc1e2677ac63ebb15b1d1ff846 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 6 Jan 2022 01:11:14 +0200 +Subject: [PATCH 3/6] net: dsa: stop updating master MTU from master.c + +At present there are two paths for changing the MTU of the DSA master. + +The first is: + +dsa_tree_setup +-> dsa_tree_setup_ports + -> dsa_port_setup + -> dsa_slave_create + -> dsa_slave_change_mtu + -> dev_set_mtu(master) + +The second is: + +dsa_tree_setup +-> dsa_tree_setup_master + -> dsa_master_setup + -> dev_set_mtu(dev) + +So the dev_set_mtu() call from dsa_master_setup() has been effectively +superseded by the dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN) that is +done from dsa_slave_create() for each user port. The later function also +updates the master MTU according to the largest user port MTU from the +tree. Therefore, updating the master MTU through a separate code path +isn't needed. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/master.c | 25 +------------------------ + 1 file changed, 1 insertion(+), 24 deletions(-) + +diff --git a/net/dsa/master.c b/net/dsa/master.c +index e8e19857621b..f4efb244f91d 100644 +--- a/net/dsa/master.c ++++ b/net/dsa/master.c +@@ -330,28 +330,13 @@ static const struct attribute_group dsa_group = { + .attrs = dsa_slave_attrs, + }; + +-static void dsa_master_reset_mtu(struct net_device *dev) +-{ +- int err; +- +- rtnl_lock(); +- err = dev_set_mtu(dev, ETH_DATA_LEN); +- if (err) +- netdev_dbg(dev, +- "Unable to reset MTU to exclude DSA overheads\n"); +- rtnl_unlock(); +-} +- + static struct lock_class_key dsa_master_addr_list_lock_key; + + int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) + { +- const struct dsa_device_ops *tag_ops = cpu_dp->tag_ops; + struct dsa_switch *ds = cpu_dp->ds; + struct device_link *consumer_link; +- int mtu, ret; +- +- mtu = ETH_DATA_LEN + dsa_tag_protocol_overhead(tag_ops); ++ int ret; + + /* The DSA master must use SET_NETDEV_DEV for this to work. */ + consumer_link = device_link_add(ds->dev, dev->dev.parent, +@@ -361,13 +346,6 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) + "Failed to create a device link to DSA switch %s\n", + dev_name(ds->dev)); + +- rtnl_lock(); +- ret = dev_set_mtu(dev, mtu); +- rtnl_unlock(); +- if (ret) +- netdev_warn(dev, "error %d setting MTU to %d to include DSA overhead\n", +- ret, mtu); +- + /* If we use a tagging format that doesn't have an ethertype + * field, make sure that all packets from this point on get + * sent to the tag format's receive function. +@@ -405,7 +383,6 @@ void dsa_master_teardown(struct net_device *dev) + sysfs_remove_group(&dev->dev.kobj, &dsa_group); + dsa_netdev_ops_set(dev, NULL); + dsa_master_ethtool_teardown(dev); +- dsa_master_reset_mtu(dev); + dsa_master_set_promiscuity(dev, -1); + + dev->dsa_ptr = NULL; +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch b/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch new file mode 100644 index 0000000000..cbbe52b0cc --- /dev/null +++ b/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch @@ -0,0 +1,85 @@ +From c146f9bc195a9dc3ad7fd000a14540e7c9df952d Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 6 Jan 2022 01:11:15 +0200 +Subject: [PATCH 4/6] net: dsa: hold rtnl_mutex when calling + dsa_master_{setup,teardown} + +DSA needs to simulate master tracking events when a binding is first +with a DSA master established and torn down, in order to give drivers +the simplifying guarantee that ->master_state_change calls are made +only when the master's readiness state to pass traffic changes. +master_state_change() provide a operational bool that DSA driver can use +to understand if DSA master is operational or not. +To avoid races, we need to block the reception of +NETDEV_UP/NETDEV_CHANGE/NETDEV_GOING_DOWN events in the netdev notifier +chain while we are changing the master's dev->dsa_ptr (this changes what +netdev_uses_dsa(dev) reports). + +The dsa_master_setup() and dsa_master_teardown() functions optionally +require the rtnl_mutex to be held, if the tagger needs the master to be +promiscuous, these functions call dev_set_promiscuity(). Move the +rtnl_lock() from that function and make it top-level. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/dsa2.c | 8 ++++++++ + net/dsa/master.c | 4 ++-- + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index a0d84f9f864f..52fb1958b535 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -1038,6 +1038,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) + struct dsa_port *dp; + int err; + ++ rtnl_lock(); ++ + list_for_each_entry(dp, &dst->ports, list) { + if (dsa_port_is_cpu(dp)) { + err = dsa_master_setup(dp->master, dp); +@@ -1046,6 +1048,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) + } + } + ++ rtnl_unlock(); ++ + return 0; + } + +@@ -1053,9 +1057,13 @@ static void dsa_tree_teardown_master(struct dsa_switch_tree *dst) + { + struct dsa_port *dp; + ++ rtnl_lock(); ++ + list_for_each_entry(dp, &dst->ports, list) + if (dsa_port_is_cpu(dp)) + dsa_master_teardown(dp->master); ++ ++ rtnl_unlock(); + } + + static int dsa_tree_setup_lags(struct dsa_switch_tree *dst) +diff --git a/net/dsa/master.c b/net/dsa/master.c +index f4efb244f91d..2199104ca7df 100644 +--- a/net/dsa/master.c ++++ b/net/dsa/master.c +@@ -267,9 +267,9 @@ static void dsa_master_set_promiscuity(struct net_device *dev, int inc) + if (!ops->promisc_on_master) + return; + +- rtnl_lock(); ++ ASSERT_RTNL(); ++ + dev_set_promiscuity(dev, inc); +- rtnl_unlock(); + } + + static ssize_t tagging_show(struct device *d, struct device_attribute *attr, +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch b/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch new file mode 100644 index 0000000000..fbd63a5743 --- /dev/null +++ b/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch @@ -0,0 +1,123 @@ +From 1e3f407f3cacc5dcfe27166c412ed9bc263d82bf Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 6 Jan 2022 01:11:16 +0200 +Subject: [PATCH 5/6] net: dsa: first set up shared ports, then non-shared + ports + +After commit a57d8c217aad ("net: dsa: flush switchdev workqueue before +tearing down CPU/DSA ports"), the port setup and teardown procedure +became asymmetric. + +The fact of the matter is that user ports need the shared ports to be up +before they can be used for CPU-initiated termination. And since we +register net devices for the user ports, those won't be functional until +we also call the setup for the shared (CPU, DSA) ports. But we may do +that later, depending on the port numbering scheme of the hardware we +are dealing with. + +It just makes sense that all shared ports are brought up before any user +port is. I can't pinpoint any issue due to the current behavior, but +let's change it nonetheless, for consistency's sake. + +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + net/dsa/dsa2.c | 50 +++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 37 insertions(+), 13 deletions(-) + +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index 52fb1958b535..ea0f02a24b8b 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -1003,23 +1003,28 @@ static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst) + dsa_switch_teardown(dp->ds); + } + +-static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) ++/* Bring shared ports up first, then non-shared ports */ ++static int dsa_tree_setup_ports(struct dsa_switch_tree *dst) + { + struct dsa_port *dp; +- int err; ++ int err = 0; + + list_for_each_entry(dp, &dst->ports, list) { +- err = dsa_switch_setup(dp->ds); +- if (err) +- goto teardown; ++ if (dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp)) { ++ err = dsa_port_setup(dp); ++ if (err) ++ goto teardown; ++ } + } + + list_for_each_entry(dp, &dst->ports, list) { +- err = dsa_port_setup(dp); +- if (err) { +- err = dsa_port_reinit_as_unused(dp); +- if (err) +- goto teardown; ++ if (dsa_port_is_user(dp) || dsa_port_is_unused(dp)) { ++ err = dsa_port_setup(dp); ++ if (err) { ++ err = dsa_port_reinit_as_unused(dp); ++ if (err) ++ goto teardown; ++ } + } + } + +@@ -1028,7 +1033,21 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) + teardown: + dsa_tree_teardown_ports(dst); + +- dsa_tree_teardown_switches(dst); ++ return err; ++} ++ ++static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) ++{ ++ struct dsa_port *dp; ++ int err = 0; ++ ++ list_for_each_entry(dp, &dst->ports, list) { ++ err = dsa_switch_setup(dp->ds); ++ if (err) { ++ dsa_tree_teardown_switches(dst); ++ break; ++ } ++ } + + return err; + } +@@ -1115,10 +1134,14 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) + if (err) + goto teardown_cpu_ports; + +- err = dsa_tree_setup_master(dst); ++ err = dsa_tree_setup_ports(dst); + if (err) + goto teardown_switches; + ++ err = dsa_tree_setup_master(dst); ++ if (err) ++ goto teardown_ports; ++ + err = dsa_tree_setup_lags(dst); + if (err) + goto teardown_master; +@@ -1131,8 +1154,9 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) + + teardown_master: + dsa_tree_teardown_master(dst); +-teardown_switches: ++teardown_ports: + dsa_tree_teardown_ports(dst); ++teardown_switches: + dsa_tree_teardown_switches(dst); + teardown_cpu_ports: + dsa_tree_teardown_cpu_ports(dst); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch b/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch new file mode 100644 index 0000000000..3f5b71945b --- /dev/null +++ b/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch @@ -0,0 +1,120 @@ +From 11fd667dac315ea3f2469961f6d2869271a46cae Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 6 Jan 2022 01:11:17 +0200 +Subject: [PATCH 6/6] net: dsa: setup master before ports + +It is said that as soon as a network interface is registered, all its +resources should have already been prepared, so that it is available for +sending and receiving traffic. One of the resources needed by a DSA +slave interface is the master. + +dsa_tree_setup +-> dsa_tree_setup_ports + -> dsa_port_setup + -> dsa_slave_create + -> register_netdevice +-> dsa_tree_setup_master + -> dsa_master_setup + -> sets up master->dsa_ptr, which enables reception + +Therefore, there is a short period of time after register_netdevice() +during which the master isn't prepared to pass traffic to the DSA layer +(master->dsa_ptr is checked by eth_type_trans). Same thing during +unregistration, there is a time frame in which packets might be missed. + +Note that this change opens us to another race: dsa_master_find_slave() +will get invoked potentially earlier than the slave creation, and later +than the slave deletion. Since dp->slave starts off as a NULL pointer, +the earlier calls aren't a problem, but the later calls are. To avoid +use-after-free, we should zeroize dp->slave before calling +dsa_slave_destroy(). + +In practice I cannot really test real life improvements brought by this +change, since in my systems, netdevice creation races with PHY autoneg +which takes a few seconds to complete, and that masks quite a few races. +Effects might be noticeable in a setup with fixed links all the way to +an external system. + +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +--- + net/dsa/dsa2.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index ea0f02a24b8b..3d21521453fe 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -561,6 +561,7 @@ static void dsa_port_teardown(struct dsa_port *dp) + struct devlink_port *dlp = &dp->devlink_port; + struct dsa_switch *ds = dp->ds; + struct dsa_mac_addr *a, *tmp; ++ struct net_device *slave; + + if (!dp->setup) + return; +@@ -582,9 +583,11 @@ static void dsa_port_teardown(struct dsa_port *dp) + dsa_port_link_unregister_of(dp); + break; + case DSA_PORT_TYPE_USER: +- if (dp->slave) { +- dsa_slave_destroy(dp->slave); ++ slave = dp->slave; ++ ++ if (slave) { + dp->slave = NULL; ++ dsa_slave_destroy(slave); + } + break; + } +@@ -1134,17 +1137,17 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) + if (err) + goto teardown_cpu_ports; + +- err = dsa_tree_setup_ports(dst); ++ err = dsa_tree_setup_master(dst); + if (err) + goto teardown_switches; + +- err = dsa_tree_setup_master(dst); ++ err = dsa_tree_setup_ports(dst); + if (err) +- goto teardown_ports; ++ goto teardown_master; + + err = dsa_tree_setup_lags(dst); + if (err) +- goto teardown_master; ++ goto teardown_ports; + + dst->setup = true; + +@@ -1152,10 +1155,10 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) + + return 0; + +-teardown_master: +- dsa_tree_teardown_master(dst); + teardown_ports: + dsa_tree_teardown_ports(dst); ++teardown_master: ++ dsa_tree_teardown_master(dst); + teardown_switches: + dsa_tree_teardown_switches(dst); + teardown_cpu_ports: +@@ -1173,10 +1176,10 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) + + dsa_tree_teardown_lags(dst); + +- dsa_tree_teardown_master(dst); +- + dsa_tree_teardown_ports(dst); + ++ dsa_tree_teardown_master(dst); ++ + dsa_tree_teardown_switches(dst); + + dsa_tree_teardown_cpu_ports(dst); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch new file mode 100644 index 0000000000..2cfb488aee --- /dev/null +++ b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch @@ -0,0 +1,267 @@ +From 295ab96f478d0fa56393e85406f19a867e26ce22 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 2 Feb 2022 01:03:20 +0100 +Subject: [PATCH 01/16] net: dsa: provide switch operations for tracking the + master state + +Certain drivers may need to send management traffic to the switch for +things like register access, FDB dump, etc, to accelerate what their +slow bus (SPI, I2C, MDIO) can already do. + +Ethernet is faster (especially in bulk transactions) but is also more +unreliable, since the user may decide to bring the DSA master down (or +not bring it up), therefore severing the link between the host and the +attached switch. + +Drivers needing Ethernet-based register access already should have +fallback logic to the slow bus if the Ethernet method fails, but that +fallback may be based on a timeout, and the I/O to the switch may slow +down to a halt if the master is down, because every Ethernet packet will +have to time out. The driver also doesn't have the option to turn off +Ethernet-based I/O momentarily, because it wouldn't know when to turn it +back on. + +Which is where this change comes in. By tracking NETDEV_CHANGE, +NETDEV_UP and NETDEV_GOING_DOWN events on the DSA master, we should know +the exact interval of time during which this interface is reliably +available for traffic. Provide this information to switches so they can +use it as they wish. + +An helper is added dsa_port_master_is_operational() to check if a master +port is operational. + +Signed-off-by: Vladimir Oltean +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 17 +++++++++++++++++ + net/dsa/dsa2.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + net/dsa/dsa_priv.h | 13 +++++++++++++ + net/dsa/slave.c | 32 ++++++++++++++++++++++++++++++++ + net/dsa/switch.c | 15 +++++++++++++++ + 5 files changed, 123 insertions(+) + +diff --git a/include/net/dsa.h b/include/net/dsa.h +index 57b3e4e7413b..43c4153ef53a 100644 +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -278,6 +278,10 @@ struct dsa_port { + struct list_head mdbs; + + bool setup; ++ /* Master state bits, valid only on CPU ports */ ++ u8 master_admin_up:1; ++ u8 master_oper_up:1; ++ + }; + + /* TODO: ideally DSA ports would have a single dp->link_dp member, +@@ -478,6 +482,12 @@ static inline bool dsa_port_is_unused(struct dsa_port *dp) + return dp->type == DSA_PORT_TYPE_UNUSED; + } + ++static inline bool dsa_port_master_is_operational(struct dsa_port *dp) ++{ ++ return dsa_port_is_cpu(dp) && dp->master_admin_up && ++ dp->master_oper_up; ++} ++ + static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p) + { + return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED; +@@ -1036,6 +1046,13 @@ struct dsa_switch_ops { + int (*tag_8021q_vlan_add)(struct dsa_switch *ds, int port, u16 vid, + u16 flags); + int (*tag_8021q_vlan_del)(struct dsa_switch *ds, int port, u16 vid); ++ ++ /* ++ * DSA master tracking operations ++ */ ++ void (*master_state_change)(struct dsa_switch *ds, ++ const struct net_device *master, ++ bool operational); + }; + + #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \ +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index 3d21521453fe..ff998c0ede02 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -1279,6 +1279,52 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, + return err; + } + ++static void dsa_tree_master_state_change(struct dsa_switch_tree *dst, ++ struct net_device *master) ++{ ++ struct dsa_notifier_master_state_info info; ++ struct dsa_port *cpu_dp = master->dsa_ptr; ++ ++ info.master = master; ++ info.operational = dsa_port_master_is_operational(cpu_dp); ++ ++ dsa_tree_notify(dst, DSA_NOTIFIER_MASTER_STATE_CHANGE, &info); ++} ++ ++void dsa_tree_master_admin_state_change(struct dsa_switch_tree *dst, ++ struct net_device *master, ++ bool up) ++{ ++ struct dsa_port *cpu_dp = master->dsa_ptr; ++ bool notify = false; ++ ++ if ((dsa_port_master_is_operational(cpu_dp)) != ++ (up && cpu_dp->master_oper_up)) ++ notify = true; ++ ++ cpu_dp->master_admin_up = up; ++ ++ if (notify) ++ dsa_tree_master_state_change(dst, master); ++} ++ ++void dsa_tree_master_oper_state_change(struct dsa_switch_tree *dst, ++ struct net_device *master, ++ bool up) ++{ ++ struct dsa_port *cpu_dp = master->dsa_ptr; ++ bool notify = false; ++ ++ if ((dsa_port_master_is_operational(cpu_dp)) != ++ (cpu_dp->master_admin_up && up)) ++ notify = true; ++ ++ cpu_dp->master_oper_up = up; ++ ++ if (notify) ++ dsa_tree_master_state_change(dst, master); ++} ++ + static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index) + { + struct dsa_switch_tree *dst = ds->dst; +diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h +index 760306f0012f..2bbfa9efe9f8 100644 +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -40,6 +40,7 @@ enum { + DSA_NOTIFIER_TAG_PROTO_DISCONNECT, + DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, + DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, ++ DSA_NOTIFIER_MASTER_STATE_CHANGE, + }; + + /* DSA_NOTIFIER_AGEING_TIME */ +@@ -109,6 +110,12 @@ struct dsa_notifier_tag_8021q_vlan_info { + u16 vid; + }; + ++/* DSA_NOTIFIER_MASTER_STATE_CHANGE */ ++struct dsa_notifier_master_state_info { ++ const struct net_device *master; ++ bool operational; ++}; ++ + struct dsa_switchdev_event_work { + struct dsa_switch *ds; + int port; +@@ -482,6 +489,12 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, + struct net_device *master, + const struct dsa_device_ops *tag_ops, + const struct dsa_device_ops *old_tag_ops); ++void dsa_tree_master_admin_state_change(struct dsa_switch_tree *dst, ++ struct net_device *master, ++ bool up); ++void dsa_tree_master_oper_state_change(struct dsa_switch_tree *dst, ++ struct net_device *master, ++ bool up); + int dsa_bridge_num_get(const struct net_device *bridge_dev, int max); + void dsa_bridge_num_put(const struct net_device *bridge_dev, int bridge_num); + +diff --git a/net/dsa/slave.c b/net/dsa/slave.c +index 22241afcac81..2b5b0f294233 100644 +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2346,6 +2346,36 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, + err = dsa_port_lag_change(dp, info->lower_state_info); + return notifier_from_errno(err); + } ++ case NETDEV_CHANGE: ++ case NETDEV_UP: { ++ /* Track state of master port. ++ * DSA driver may require the master port (and indirectly ++ * the tagger) to be available for some special operation. ++ */ ++ if (netdev_uses_dsa(dev)) { ++ struct dsa_port *cpu_dp = dev->dsa_ptr; ++ struct dsa_switch_tree *dst = cpu_dp->ds->dst; ++ ++ /* Track when the master port is UP */ ++ dsa_tree_master_oper_state_change(dst, dev, ++ netif_oper_up(dev)); ++ ++ /* Track when the master port is ready and can accept ++ * packet. ++ * NETDEV_UP event is not enough to flag a port as ready. ++ * We also have to wait for linkwatch_do_dev to dev_activate ++ * and emit a NETDEV_CHANGE event. ++ * We check if a master port is ready by checking if the dev ++ * have a qdisc assigned and is not noop. ++ */ ++ dsa_tree_master_admin_state_change(dst, dev, ++ !qdisc_tx_is_noop(dev)); ++ ++ return NOTIFY_OK; ++ } ++ ++ return NOTIFY_DONE; ++ } + case NETDEV_GOING_DOWN: { + struct dsa_port *dp, *cpu_dp; + struct dsa_switch_tree *dst; +@@ -2357,6 +2387,8 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, + cpu_dp = dev->dsa_ptr; + dst = cpu_dp->ds->dst; + ++ dsa_tree_master_admin_state_change(dst, dev, false); ++ + list_for_each_entry(dp, &dst->ports, list) { + if (!dsa_port_is_user(dp)) + continue; +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index 517cc83d13cc..4866b58649e4 100644 +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -697,6 +697,18 @@ dsa_switch_disconnect_tag_proto(struct dsa_switch *ds, + return 0; + } + ++static int ++dsa_switch_master_state_change(struct dsa_switch *ds, ++ struct dsa_notifier_master_state_info *info) ++{ ++ if (!ds->ops->master_state_change) ++ return 0; ++ ++ ds->ops->master_state_change(ds, info->master, info->operational); ++ ++ return 0; ++} ++ + static int dsa_switch_event(struct notifier_block *nb, + unsigned long event, void *info) + { +@@ -770,6 +782,9 @@ static int dsa_switch_event(struct notifier_block *nb, + case DSA_NOTIFIER_TAG_8021Q_VLAN_DEL: + err = dsa_switch_tag_8021q_vlan_del(ds, info); + break; ++ case DSA_NOTIFIER_MASTER_STATE_CHANGE: ++ err = dsa_switch_master_state_change(ds, info); ++ break; + default: + err = -EOPNOTSUPP; + break; +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch b/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch new file mode 100644 index 0000000000..d9356c3b7d --- /dev/null +++ b/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch @@ -0,0 +1,94 @@ +From e83d56537859849f2223b90749e554831b1f3c27 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 2 Feb 2022 01:03:21 +0100 +Subject: [PATCH 02/16] net: dsa: replay master state events in + dsa_tree_{setup,teardown}_master + +In order for switch driver to be able to make simple and reliable use of +the master tracking operations, they must also be notified of the +initial state of the DSA master, not just of the changes. This is +because they might enable certain features only during the time when +they know that the DSA master is up and running. + +Therefore, this change explicitly checks the state of the DSA master +under the same rtnl_mutex as we were holding during the +dsa_master_setup() and dsa_master_teardown() call. The idea being that +if the DSA master became operational in between the moment in which it +became a DSA master (dsa_master_setup set dev->dsa_ptr) and the moment +when we checked for the master being up, there is a chance that we +would emit a ->master_state_change() call with no actual state change. +We need to avoid that by serializing the concurrent netdevice event with +us. If the netdevice event started before, we force it to finish before +we begin, because we take rtnl_lock before making netdev_uses_dsa() +return true. So we also handle that early event and do nothing on it. +Similarly, if the dev_open() attempt is concurrent with us, it will +attempt to take the rtnl_mutex, but we're holding it. We'll see that +the master flag IFF_UP isn't set, then when we release the rtnl_mutex +we'll process the NETDEV_UP notifier. + +Signed-off-by: Vladimir Oltean +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/dsa2.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index ff998c0ede02..909b045c9b11 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "dsa_priv.h" + +@@ -1064,9 +1065,18 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) + + list_for_each_entry(dp, &dst->ports, list) { + if (dsa_port_is_cpu(dp)) { +- err = dsa_master_setup(dp->master, dp); ++ struct net_device *master = dp->master; ++ bool admin_up = (master->flags & IFF_UP) && ++ !qdisc_tx_is_noop(master); ++ ++ err = dsa_master_setup(master, dp); + if (err) + return err; ++ ++ /* Replay master state event */ ++ dsa_tree_master_admin_state_change(dst, master, admin_up); ++ dsa_tree_master_oper_state_change(dst, master, ++ netif_oper_up(master)); + } + } + +@@ -1081,9 +1091,19 @@ static void dsa_tree_teardown_master(struct dsa_switch_tree *dst) + + rtnl_lock(); + +- list_for_each_entry(dp, &dst->ports, list) +- if (dsa_port_is_cpu(dp)) +- dsa_master_teardown(dp->master); ++ list_for_each_entry(dp, &dst->ports, list) { ++ if (dsa_port_is_cpu(dp)) { ++ struct net_device *master = dp->master; ++ ++ /* Synthesizing an "admin down" state is sufficient for ++ * the switches to get a notification if the master is ++ * currently up and running. ++ */ ++ dsa_tree_master_admin_state_change(dst, master, false); ++ ++ dsa_master_teardown(master); ++ } ++ } + + rtnl_unlock(); + } +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch b/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch new file mode 100644 index 0000000000..84fd918cb3 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch @@ -0,0 +1,92 @@ +From 6b0458299297ca4ab6fb295800e29a4e501d50c1 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:22 +0100 +Subject: [PATCH 03/16] net: dsa: tag_qca: convert to FIELD macro + +Convert driver to FIELD macro to drop redundant define. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/tag_qca.c | 34 +++++++++++++++------------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index 1ea9401b8ace..55fa6b96b4eb 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -4,29 +4,24 @@ + */ + + #include ++#include + + #include "dsa_priv.h" + + #define QCA_HDR_LEN 2 + #define QCA_HDR_VERSION 0x2 + +-#define QCA_HDR_RECV_VERSION_MASK GENMASK(15, 14) +-#define QCA_HDR_RECV_VERSION_S 14 +-#define QCA_HDR_RECV_PRIORITY_MASK GENMASK(13, 11) +-#define QCA_HDR_RECV_PRIORITY_S 11 +-#define QCA_HDR_RECV_TYPE_MASK GENMASK(10, 6) +-#define QCA_HDR_RECV_TYPE_S 6 ++#define QCA_HDR_RECV_VERSION GENMASK(15, 14) ++#define QCA_HDR_RECV_PRIORITY GENMASK(13, 11) ++#define QCA_HDR_RECV_TYPE GENMASK(10, 6) + #define QCA_HDR_RECV_FRAME_IS_TAGGED BIT(3) +-#define QCA_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) +- +-#define QCA_HDR_XMIT_VERSION_MASK GENMASK(15, 14) +-#define QCA_HDR_XMIT_VERSION_S 14 +-#define QCA_HDR_XMIT_PRIORITY_MASK GENMASK(13, 11) +-#define QCA_HDR_XMIT_PRIORITY_S 11 +-#define QCA_HDR_XMIT_CONTROL_MASK GENMASK(10, 8) +-#define QCA_HDR_XMIT_CONTROL_S 8 ++#define QCA_HDR_RECV_SOURCE_PORT GENMASK(2, 0) ++ ++#define QCA_HDR_XMIT_VERSION GENMASK(15, 14) ++#define QCA_HDR_XMIT_PRIORITY GENMASK(13, 11) ++#define QCA_HDR_XMIT_CONTROL GENMASK(10, 8) + #define QCA_HDR_XMIT_FROM_CPU BIT(7) +-#define QCA_HDR_XMIT_DP_BIT_MASK GENMASK(6, 0) ++#define QCA_HDR_XMIT_DP_BIT GENMASK(6, 0) + + static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) + { +@@ -40,8 +35,9 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) + phdr = dsa_etype_header_pos_tx(skb); + + /* Set the version field, and set destination port information */ +- hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S | +- QCA_HDR_XMIT_FROM_CPU | BIT(dp->index); ++ hdr = FIELD_PREP(QCA_HDR_XMIT_VERSION, QCA_HDR_VERSION); ++ hdr |= QCA_HDR_XMIT_FROM_CPU; ++ hdr |= FIELD_PREP(QCA_HDR_XMIT_DP_BIT, BIT(dp->index)); + + *phdr = htons(hdr); + +@@ -62,7 +58,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + hdr = ntohs(*phdr); + + /* Make sure the version is correct */ +- ver = (hdr & QCA_HDR_RECV_VERSION_MASK) >> QCA_HDR_RECV_VERSION_S; ++ ver = FIELD_GET(QCA_HDR_RECV_VERSION, hdr); + if (unlikely(ver != QCA_HDR_VERSION)) + return NULL; + +@@ -71,7 +67,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + dsa_strip_etype_header(skb, QCA_HDR_LEN); + + /* Get source port information */ +- port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK); ++ port = FIELD_GET(QCA_HDR_RECV_SOURCE_PORT, hdr); + + skb->dev = dsa_master_find_slave(dev, 0, port); + if (!skb->dev) +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch b/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch new file mode 100644 index 0000000000..21221dbbef --- /dev/null +++ b/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch @@ -0,0 +1,79 @@ +From 3ec762fb13c7e7273800b94c80db1c2cc37590d1 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:23 +0100 +Subject: [PATCH 04/16] net: dsa: tag_qca: move define to include linux/dsa + +Move tag_qca define to include dir linux/dsa as the qca8k require access +to the tagger define to support in-band mdio read/write using ethernet +packet. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/linux/dsa/tag_qca.h | 21 +++++++++++++++++++++ + net/dsa/tag_qca.c | 16 +--------------- + 2 files changed, 22 insertions(+), 15 deletions(-) + create mode 100644 include/linux/dsa/tag_qca.h + +diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h +new file mode 100644 +index 000000000000..c02d2d39ff4a +--- /dev/null ++++ b/include/linux/dsa/tag_qca.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef __TAG_QCA_H ++#define __TAG_QCA_H ++ ++#define QCA_HDR_LEN 2 ++#define QCA_HDR_VERSION 0x2 ++ ++#define QCA_HDR_RECV_VERSION GENMASK(15, 14) ++#define QCA_HDR_RECV_PRIORITY GENMASK(13, 11) ++#define QCA_HDR_RECV_TYPE GENMASK(10, 6) ++#define QCA_HDR_RECV_FRAME_IS_TAGGED BIT(3) ++#define QCA_HDR_RECV_SOURCE_PORT GENMASK(2, 0) ++ ++#define QCA_HDR_XMIT_VERSION GENMASK(15, 14) ++#define QCA_HDR_XMIT_PRIORITY GENMASK(13, 11) ++#define QCA_HDR_XMIT_CONTROL GENMASK(10, 8) ++#define QCA_HDR_XMIT_FROM_CPU BIT(7) ++#define QCA_HDR_XMIT_DP_BIT GENMASK(6, 0) ++ ++#endif /* __TAG_QCA_H */ +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index 55fa6b96b4eb..34e565e00ece 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -5,24 +5,10 @@ + + #include + #include ++#include + + #include "dsa_priv.h" + +-#define QCA_HDR_LEN 2 +-#define QCA_HDR_VERSION 0x2 +- +-#define QCA_HDR_RECV_VERSION GENMASK(15, 14) +-#define QCA_HDR_RECV_PRIORITY GENMASK(13, 11) +-#define QCA_HDR_RECV_TYPE GENMASK(10, 6) +-#define QCA_HDR_RECV_FRAME_IS_TAGGED BIT(3) +-#define QCA_HDR_RECV_SOURCE_PORT GENMASK(2, 0) +- +-#define QCA_HDR_XMIT_VERSION GENMASK(15, 14) +-#define QCA_HDR_XMIT_PRIORITY GENMASK(13, 11) +-#define QCA_HDR_XMIT_CONTROL GENMASK(10, 8) +-#define QCA_HDR_XMIT_FROM_CPU BIT(7) +-#define QCA_HDR_XMIT_DP_BIT GENMASK(6, 0) +- + static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch b/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch new file mode 100644 index 0000000000..d0dd4513f3 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch @@ -0,0 +1,32 @@ +From 101c04c3463b87061e6a3d4f72c1bc57670685a6 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:24 +0100 +Subject: [PATCH 05/16] net: dsa: tag_qca: enable promisc_on_master flag + +Ethernet MDIO packets are non-standard and DSA master expects the first +6 octets to be the MAC DA. To address these kind of packet, enable +promisc_on_master flag for the tagger. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + net/dsa/tag_qca.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index 34e565e00ece..f8df49d5956f 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -68,6 +68,7 @@ static const struct dsa_device_ops qca_netdev_ops = { + .xmit = qca_tag_xmit, + .rcv = qca_tag_rcv, + .needed_headroom = QCA_HDR_LEN, ++ .promisc_on_master = true, + }; + + MODULE_LICENSE("GPL"); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch b/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch new file mode 100644 index 0000000000..6981e7b187 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch @@ -0,0 +1,117 @@ +From c2ee8181fddb293d296477f60b3eb4fa3ce4e1a6 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:25 +0100 +Subject: [PATCH 06/16] net: dsa: tag_qca: add define for handling mgmt + Ethernet packet + +Add all the required define to prepare support for mgmt read/write in +Ethernet packet. Any packet of this type has to be dropped as the only +use of these special packet is receive ack for an mgmt write request or +receive data for an mgmt read request. +A struct is used that emulates the Ethernet header but is used for a +different purpose. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/linux/dsa/tag_qca.h | 44 +++++++++++++++++++++++++++++++++++++ + net/dsa/tag_qca.c | 15 ++++++++++--- + 2 files changed, 56 insertions(+), 3 deletions(-) + +diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h +index c02d2d39ff4a..f366422ab7a0 100644 +--- a/include/linux/dsa/tag_qca.h ++++ b/include/linux/dsa/tag_qca.h +@@ -12,10 +12,54 @@ + #define QCA_HDR_RECV_FRAME_IS_TAGGED BIT(3) + #define QCA_HDR_RECV_SOURCE_PORT GENMASK(2, 0) + ++/* Packet type for recv */ ++#define QCA_HDR_RECV_TYPE_NORMAL 0x0 ++#define QCA_HDR_RECV_TYPE_MIB 0x1 ++#define QCA_HDR_RECV_TYPE_RW_REG_ACK 0x2 ++ + #define QCA_HDR_XMIT_VERSION GENMASK(15, 14) + #define QCA_HDR_XMIT_PRIORITY GENMASK(13, 11) + #define QCA_HDR_XMIT_CONTROL GENMASK(10, 8) + #define QCA_HDR_XMIT_FROM_CPU BIT(7) + #define QCA_HDR_XMIT_DP_BIT GENMASK(6, 0) + ++/* Packet type for xmit */ ++#define QCA_HDR_XMIT_TYPE_NORMAL 0x0 ++#define QCA_HDR_XMIT_TYPE_RW_REG 0x1 ++ ++/* Check code for a valid mgmt packet. Switch will ignore the packet ++ * with this wrong. ++ */ ++#define QCA_HDR_MGMT_CHECK_CODE_VAL 0x5 ++ ++/* Specific define for in-band MDIO read/write with Ethernet packet */ ++#define QCA_HDR_MGMT_SEQ_LEN 4 /* 4 byte for the seq */ ++#define QCA_HDR_MGMT_COMMAND_LEN 4 /* 4 byte for the command */ ++#define QCA_HDR_MGMT_DATA1_LEN 4 /* First 4 byte for the mdio data */ ++#define QCA_HDR_MGMT_HEADER_LEN (QCA_HDR_MGMT_SEQ_LEN + \ ++ QCA_HDR_MGMT_COMMAND_LEN + \ ++ QCA_HDR_MGMT_DATA1_LEN) ++ ++#define QCA_HDR_MGMT_DATA2_LEN 12 /* Other 12 byte for the mdio data */ ++#define QCA_HDR_MGMT_PADDING_LEN 34 /* Padding to reach the min Ethernet packet */ ++ ++#define QCA_HDR_MGMT_PKT_LEN (QCA_HDR_MGMT_HEADER_LEN + \ ++ QCA_HDR_LEN + \ ++ QCA_HDR_MGMT_DATA2_LEN + \ ++ QCA_HDR_MGMT_PADDING_LEN) ++ ++#define QCA_HDR_MGMT_SEQ_NUM GENMASK(31, 0) /* 63, 32 */ ++#define QCA_HDR_MGMT_CHECK_CODE GENMASK(31, 29) /* 31, 29 */ ++#define QCA_HDR_MGMT_CMD BIT(28) /* 28 */ ++#define QCA_HDR_MGMT_LENGTH GENMASK(23, 20) /* 23, 20 */ ++#define QCA_HDR_MGMT_ADDR GENMASK(18, 0) /* 18, 0 */ ++ ++/* Special struct emulating a Ethernet header */ ++struct qca_mgmt_ethhdr { ++ u32 command; /* command bit 31:0 */ ++ u32 seq; /* seq 63:32 */ ++ u32 mdio_data; /* first 4byte mdio */ ++ __be16 hdr; /* qca hdr */ ++} __packed; ++ + #endif /* __TAG_QCA_H */ +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index f8df49d5956f..f17ed5be20c2 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -32,10 +32,12 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) + + static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + { +- u8 ver; +- u16 hdr; +- int port; ++ u8 ver, pk_type; + __be16 *phdr; ++ int port; ++ u16 hdr; ++ ++ BUILD_BUG_ON(sizeof(struct qca_mgmt_ethhdr) != QCA_HDR_MGMT_HEADER_LEN + QCA_HDR_LEN); + + if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) + return NULL; +@@ -48,6 +50,13 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + if (unlikely(ver != QCA_HDR_VERSION)) + return NULL; + ++ /* Get pk type */ ++ pk_type = FIELD_GET(QCA_HDR_RECV_TYPE, hdr); ++ ++ /* Ethernet MDIO read/write packet */ ++ if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) ++ return NULL; ++ + /* Remove QCA tag and recalculate checksum */ + skb_pull_rcsum(skb, QCA_HDR_LEN); + dsa_strip_etype_header(skb, QCA_HDR_LEN); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch b/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch new file mode 100644 index 0000000000..497518097e --- /dev/null +++ b/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch @@ -0,0 +1,52 @@ +From 18be654a4345f7d937b4bfbad74bea8093e3a93c Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:26 +0100 +Subject: [PATCH 07/16] net: dsa: tag_qca: add define for handling MIB packet + +Add struct to correctly parse a mib Ethernet packet. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/linux/dsa/tag_qca.h | 10 ++++++++++ + net/dsa/tag_qca.c | 4 ++++ + 2 files changed, 14 insertions(+) + +diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h +index f366422ab7a0..1fff57f2937b 100644 +--- a/include/linux/dsa/tag_qca.h ++++ b/include/linux/dsa/tag_qca.h +@@ -62,4 +62,14 @@ struct qca_mgmt_ethhdr { + __be16 hdr; /* qca hdr */ + } __packed; + ++enum mdio_cmd { ++ MDIO_WRITE = 0x0, ++ MDIO_READ ++}; ++ ++struct mib_ethhdr { ++ u32 data[3]; /* first 3 mib counter */ ++ __be16 hdr; /* qca hdr */ ++} __packed; ++ + #endif /* __TAG_QCA_H */ +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index f17ed5be20c2..be792cf687d9 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -57,6 +57,10 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) + return NULL; + ++ /* Ethernet MIB counter packet */ ++ if (pk_type == QCA_HDR_RECV_TYPE_MIB) ++ return NULL; ++ + /* Remove QCA tag and recalculate checksum */ + skb_pull_rcsum(skb, QCA_HDR_LEN); + dsa_strip_etype_header(skb, QCA_HDR_LEN); +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch b/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch new file mode 100644 index 0000000000..4375cd08b8 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch @@ -0,0 +1,123 @@ +From 31eb6b4386ad91930417e3f5c8157a4b5e31cbd5 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:27 +0100 +Subject: [PATCH 08/16] net: dsa: tag_qca: add support for handling mgmt and + MIB Ethernet packet + +Add connect/disconnect helper to assign private struct to the DSA switch. +Add support for Ethernet mgmt and MIB if the DSA driver provide an handler +to correctly parse and elaborate the data. + +Signed-off-by: Ansuel Smith +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/linux/dsa/tag_qca.h | 7 +++++++ + net/dsa/tag_qca.c | 39 ++++++++++++++++++++++++++++++++++--- + 2 files changed, 43 insertions(+), 3 deletions(-) + +diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h +index 1fff57f2937b..4359fb0221cf 100644 +--- a/include/linux/dsa/tag_qca.h ++++ b/include/linux/dsa/tag_qca.h +@@ -72,4 +72,11 @@ struct mib_ethhdr { + __be16 hdr; /* qca hdr */ + } __packed; + ++struct qca_tagger_data { ++ void (*rw_reg_ack_handler)(struct dsa_switch *ds, ++ struct sk_buff *skb); ++ void (*mib_autocast_handler)(struct dsa_switch *ds, ++ struct sk_buff *skb); ++}; ++ + #endif /* __TAG_QCA_H */ +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index be792cf687d9..57d2e00f1e5d 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + + #include "dsa_priv.h" +@@ -32,6 +33,9 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) + + static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + { ++ struct qca_tagger_data *tagger_data; ++ struct dsa_port *dp = dev->dsa_ptr; ++ struct dsa_switch *ds = dp->ds; + u8 ver, pk_type; + __be16 *phdr; + int port; +@@ -39,6 +43,8 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + + BUILD_BUG_ON(sizeof(struct qca_mgmt_ethhdr) != QCA_HDR_MGMT_HEADER_LEN + QCA_HDR_LEN); + ++ tagger_data = ds->tagger_data; ++ + if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) + return NULL; + +@@ -53,13 +59,19 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + /* Get pk type */ + pk_type = FIELD_GET(QCA_HDR_RECV_TYPE, hdr); + +- /* Ethernet MDIO read/write packet */ +- if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) ++ /* Ethernet mgmt read/write packet */ ++ if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) { ++ if (likely(tagger_data->rw_reg_ack_handler)) ++ tagger_data->rw_reg_ack_handler(ds, skb); + return NULL; ++ } + + /* Ethernet MIB counter packet */ +- if (pk_type == QCA_HDR_RECV_TYPE_MIB) ++ if (pk_type == QCA_HDR_RECV_TYPE_MIB) { ++ if (likely(tagger_data->mib_autocast_handler)) ++ tagger_data->mib_autocast_handler(ds, skb); + return NULL; ++ } + + /* Remove QCA tag and recalculate checksum */ + skb_pull_rcsum(skb, QCA_HDR_LEN); +@@ -75,9 +87,30 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) + return skb; + } + ++static int qca_tag_connect(struct dsa_switch *ds) ++{ ++ struct qca_tagger_data *tagger_data; ++ ++ tagger_data = kzalloc(sizeof(*tagger_data), GFP_KERNEL); ++ if (!tagger_data) ++ return -ENOMEM; ++ ++ ds->tagger_data = tagger_data; ++ ++ return 0; ++} ++ ++static void qca_tag_disconnect(struct dsa_switch *ds) ++{ ++ kfree(ds->tagger_data); ++ ds->tagger_data = NULL; ++} ++ + static const struct dsa_device_ops qca_netdev_ops = { + .name = "qca", + .proto = DSA_TAG_PROTO_QCA, ++ .connect = qca_tag_connect, ++ .disconnect = qca_tag_disconnect, + .xmit = qca_tag_xmit, + .rcv = qca_tag_rcv, + .needed_headroom = QCA_HDR_LEN, +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch b/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch new file mode 100644 index 0000000000..d2799f9e7a --- /dev/null +++ b/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch @@ -0,0 +1,74 @@ +From cddbec19466a1dfb4d45ddd507d9f09f991d54ae Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:28 +0100 +Subject: [PATCH 09/16] net: dsa: qca8k: add tracking state of master port + +MDIO/MIB Ethernet require the master port and the tagger availabale to +correctly work. Use the new api master_state_change to track when master +is operational or not and set a bool in qca8k_priv. +We cache the first cached master available and we check if other cpu +port are operational when the cached one goes down. +This cached master will later be used by mdio read/write and mib request to +correctly use the working function. + +qca8k implementation for MDIO/MIB Ethernet is bad. CPU port0 is the only +one that answers with the ack packet or sends MIB Ethernet packets. For +this reason the master_state_change ignore CPU port6 and only checks +CPU port0 if it's operational and enables this mode. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 15 +++++++++++++++ + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 16 insertions(+) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 039694518788..ec062b9a918d 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -2383,6 +2383,20 @@ qca8k_port_lag_leave(struct dsa_switch *ds, int port, + return qca8k_lag_refresh_portmap(ds, port, lag, true); + } + ++static void ++qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, ++ bool operational) ++{ ++ struct dsa_port *dp = master->dsa_ptr; ++ struct qca8k_priv *priv = ds->priv; ++ ++ /* Ethernet MIB/MDIO is only supported for CPU port 0 */ ++ if (dp->index != 0) ++ return; ++ ++ priv->mgmt_master = operational ? (struct net_device *)master : NULL; ++} ++ + static const struct dsa_switch_ops qca8k_switch_ops = { + .get_tag_protocol = qca8k_get_tag_protocol, + .setup = qca8k_setup, +@@ -2418,6 +2432,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + .get_phy_flags = qca8k_get_phy_flags, + .port_lag_join = qca8k_port_lag_join, + .port_lag_leave = qca8k_port_lag_leave, ++ .master_state_change = qca8k_master_change, + }; + + static int qca8k_read_switch_id(struct qca8k_priv *priv) +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index ab4a417b25a9..b81aad98a116 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -353,6 +353,7 @@ struct qca8k_priv { + struct dsa_switch_ops ops; + struct gpio_desc *reset_gpio; + unsigned int port_mtu[QCA8K_NUM_PORTS]; ++ struct net_device *mgmt_master; /* Track if mdio/mib Ethernet is available */ + }; + + struct qca8k_mib_desc { +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch b/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch new file mode 100644 index 0000000000..dedffbc074 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch @@ -0,0 +1,370 @@ +From 5950c7c0a68c915b336c70f79388626e2d576ab7 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:29 +0100 +Subject: [PATCH 10/16] net: dsa: qca8k: add support for mgmt read/write in + Ethernet packet + +Add qca8k side support for mgmt read/write in Ethernet packet. +qca8k supports some specially crafted Ethernet packet that can be used +for mgmt read/write instead of the legacy method uart/internal mdio. +This add support for the qca8k side to craft the packet and enqueue it. +Each port and the qca8k_priv have a special struct to put data in it. +The completion API is used to wait for the packet to be received back +with the requested data. + +The various steps are: +1. Craft the special packet with the qca hdr set to mgmt read/write + mode. +2. Set the lock in the dedicated mgmt struct. +3. Increment the seq number and set it in the mgmt pkt +4. Reinit the completion. +5. Enqueue the packet. +6. Wait the packet to be received. +7. Use the data set by the tagger to complete the mdio operation. + +If the completion timeouts or the ack value is not true, the legacy +mdio way is used. + +It has to be considered that in the initial setup mdio is still used and +mdio is still used until DSA is ready to accept and tag packet. + +tag_proto_connect() is used to fill the required handler for the tagger +to correctly parse and elaborate the special Ethernet mdio packet. + +Locking is added to qca8k_master_change() to make sure no mgmt Ethernet +are in progress. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 225 ++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 13 +++ + 2 files changed, 238 insertions(+) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index ec062b9a918d..e3a215f04559 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include "qca8k.h" + +@@ -170,6 +171,194 @@ qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) + return regmap_update_bits(priv->regmap, reg, mask, write_val); + } + ++static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) ++{ ++ struct qca8k_mgmt_eth_data *mgmt_eth_data; ++ struct qca8k_priv *priv = ds->priv; ++ struct qca_mgmt_ethhdr *mgmt_ethhdr; ++ u8 len, cmd; ++ ++ mgmt_ethhdr = (struct qca_mgmt_ethhdr *)skb_mac_header(skb); ++ mgmt_eth_data = &priv->mgmt_eth_data; ++ ++ cmd = FIELD_GET(QCA_HDR_MGMT_CMD, mgmt_ethhdr->command); ++ len = FIELD_GET(QCA_HDR_MGMT_LENGTH, mgmt_ethhdr->command); ++ ++ /* Make sure the seq match the requested packet */ ++ if (mgmt_ethhdr->seq == mgmt_eth_data->seq) ++ mgmt_eth_data->ack = true; ++ ++ if (cmd == MDIO_READ) { ++ mgmt_eth_data->data[0] = mgmt_ethhdr->mdio_data; ++ ++ /* Get the rest of the 12 byte of data */ ++ if (len > QCA_HDR_MGMT_DATA1_LEN) ++ memcpy(mgmt_eth_data->data + 1, skb->data, ++ QCA_HDR_MGMT_DATA2_LEN); ++ } ++ ++ complete(&mgmt_eth_data->rw_done); ++} ++ ++static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *val, ++ int priority) ++{ ++ struct qca_mgmt_ethhdr *mgmt_ethhdr; ++ struct sk_buff *skb; ++ u16 hdr; ++ ++ skb = dev_alloc_skb(QCA_HDR_MGMT_PKT_LEN); ++ if (!skb) ++ return NULL; ++ ++ skb_reset_mac_header(skb); ++ skb_set_network_header(skb, skb->len); ++ ++ mgmt_ethhdr = skb_push(skb, QCA_HDR_MGMT_HEADER_LEN + QCA_HDR_LEN); ++ ++ hdr = FIELD_PREP(QCA_HDR_XMIT_VERSION, QCA_HDR_VERSION); ++ hdr |= FIELD_PREP(QCA_HDR_XMIT_PRIORITY, priority); ++ hdr |= QCA_HDR_XMIT_FROM_CPU; ++ hdr |= FIELD_PREP(QCA_HDR_XMIT_DP_BIT, BIT(0)); ++ hdr |= FIELD_PREP(QCA_HDR_XMIT_CONTROL, QCA_HDR_XMIT_TYPE_RW_REG); ++ ++ mgmt_ethhdr->command = FIELD_PREP(QCA_HDR_MGMT_ADDR, reg); ++ mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_LENGTH, 4); ++ mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CMD, cmd); ++ mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CHECK_CODE, ++ QCA_HDR_MGMT_CHECK_CODE_VAL); ++ ++ if (cmd == MDIO_WRITE) ++ mgmt_ethhdr->mdio_data = *val; ++ ++ mgmt_ethhdr->hdr = htons(hdr); ++ ++ skb_put_zero(skb, QCA_HDR_MGMT_DATA2_LEN + QCA_HDR_MGMT_PADDING_LEN); ++ ++ return skb; ++} ++ ++static void qca8k_mdio_header_fill_seq_num(struct sk_buff *skb, u32 seq_num) ++{ ++ struct qca_mgmt_ethhdr *mgmt_ethhdr; ++ ++ mgmt_ethhdr = (struct qca_mgmt_ethhdr *)skb->data; ++ mgmt_ethhdr->seq = FIELD_PREP(QCA_HDR_MGMT_SEQ_NUM, seq_num); ++} ++ ++static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) ++{ ++ struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data; ++ struct sk_buff *skb; ++ bool ack; ++ int ret; ++ ++ skb = qca8k_alloc_mdio_header(MDIO_READ, reg, NULL, ++ QCA8K_ETHERNET_MDIO_PRIORITY); ++ if (!skb) ++ return -ENOMEM; ++ ++ mutex_lock(&mgmt_eth_data->mutex); ++ ++ /* Check mgmt_master if is operational */ ++ if (!priv->mgmt_master) { ++ kfree_skb(skb); ++ mutex_unlock(&mgmt_eth_data->mutex); ++ return -EINVAL; ++ } ++ ++ skb->dev = priv->mgmt_master; ++ ++ reinit_completion(&mgmt_eth_data->rw_done); ++ ++ /* Increment seq_num and set it in the mdio pkt */ ++ mgmt_eth_data->seq++; ++ qca8k_mdio_header_fill_seq_num(skb, mgmt_eth_data->seq); ++ mgmt_eth_data->ack = false; ++ ++ dev_queue_xmit(skb); ++ ++ ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done, ++ msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT)); ++ ++ *val = mgmt_eth_data->data[0]; ++ ack = mgmt_eth_data->ack; ++ ++ mutex_unlock(&mgmt_eth_data->mutex); ++ ++ if (ret <= 0) ++ return -ETIMEDOUT; ++ ++ if (!ack) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 val) ++{ ++ struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data; ++ struct sk_buff *skb; ++ bool ack; ++ int ret; ++ ++ skb = qca8k_alloc_mdio_header(MDIO_WRITE, reg, &val, ++ QCA8K_ETHERNET_MDIO_PRIORITY); ++ if (!skb) ++ return -ENOMEM; ++ ++ mutex_lock(&mgmt_eth_data->mutex); ++ ++ /* Check mgmt_master if is operational */ ++ if (!priv->mgmt_master) { ++ kfree_skb(skb); ++ mutex_unlock(&mgmt_eth_data->mutex); ++ return -EINVAL; ++ } ++ ++ skb->dev = priv->mgmt_master; ++ ++ reinit_completion(&mgmt_eth_data->rw_done); ++ ++ /* Increment seq_num and set it in the mdio pkt */ ++ mgmt_eth_data->seq++; ++ qca8k_mdio_header_fill_seq_num(skb, mgmt_eth_data->seq); ++ mgmt_eth_data->ack = false; ++ ++ dev_queue_xmit(skb); ++ ++ ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done, ++ msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT)); ++ ++ ack = mgmt_eth_data->ack; ++ ++ mutex_unlock(&mgmt_eth_data->mutex); ++ ++ if (ret <= 0) ++ return -ETIMEDOUT; ++ ++ if (!ack) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int ++qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) ++{ ++ u32 val = 0; ++ int ret; ++ ++ ret = qca8k_read_eth(priv, reg, &val); ++ if (ret) ++ return ret; ++ ++ val &= ~mask; ++ val |= write_val; ++ ++ return qca8k_write_eth(priv, reg, val); ++} ++ + static int + qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + { +@@ -178,6 +367,9 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + u16 r1, r2, page; + int ret; + ++ if (!qca8k_read_eth(priv, reg, val)) ++ return 0; ++ + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -201,6 +393,9 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) + u16 r1, r2, page; + int ret; + ++ if (!qca8k_write_eth(priv, reg, val)) ++ return 0; ++ + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -225,6 +420,9 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ + u32 val; + int ret; + ++ if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) ++ return 0; ++ + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -2394,7 +2592,30 @@ qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, + if (dp->index != 0) + return; + ++ mutex_lock(&priv->mgmt_eth_data.mutex); ++ + priv->mgmt_master = operational ? (struct net_device *)master : NULL; ++ ++ mutex_unlock(&priv->mgmt_eth_data.mutex); ++} ++ ++static int qca8k_connect_tag_protocol(struct dsa_switch *ds, ++ enum dsa_tag_protocol proto) ++{ ++ struct qca_tagger_data *tagger_data; ++ ++ switch (proto) { ++ case DSA_TAG_PROTO_QCA: ++ tagger_data = ds->tagger_data; ++ ++ tagger_data->rw_reg_ack_handler = qca8k_rw_reg_ack_handler; ++ ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; + } + + static const struct dsa_switch_ops qca8k_switch_ops = { +@@ -2433,6 +2654,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + .port_lag_join = qca8k_port_lag_join, + .port_lag_leave = qca8k_port_lag_leave, + .master_state_change = qca8k_master_change, ++ .connect_tag_protocol = qca8k_connect_tag_protocol, + }; + + static int qca8k_read_switch_id(struct qca8k_priv *priv) +@@ -2512,6 +2734,9 @@ qca8k_sw_probe(struct mdio_device *mdiodev) + if (!priv->ds) + return -ENOMEM; + ++ mutex_init(&priv->mgmt_eth_data.mutex); ++ init_completion(&priv->mgmt_eth_data.rw_done); ++ + priv->ds->dev = &mdiodev->dev; + priv->ds->num_ports = QCA8K_NUM_PORTS; + priv->ds->priv = priv; +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index b81aad98a116..75c28689a652 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -11,6 +11,10 @@ + #include + #include + #include ++#include ++ ++#define QCA8K_ETHERNET_MDIO_PRIORITY 7 ++#define QCA8K_ETHERNET_TIMEOUT 100 + + #define QCA8K_NUM_PORTS 7 + #define QCA8K_NUM_CPU_PORTS 2 +@@ -328,6 +332,14 @@ enum { + QCA8K_CPU_PORT6, + }; + ++struct qca8k_mgmt_eth_data { ++ struct completion rw_done; ++ struct mutex mutex; /* Enforce one mdio read/write at time */ ++ bool ack; ++ u32 seq; ++ u32 data[4]; ++}; ++ + struct qca8k_ports_config { + bool sgmii_rx_clk_falling_edge; + bool sgmii_tx_clk_falling_edge; +@@ -354,6 +366,7 @@ struct qca8k_priv { + struct gpio_desc *reset_gpio; + unsigned int port_mtu[QCA8K_NUM_PORTS]; + struct net_device *mgmt_master; /* Track if mdio/mib Ethernet is available */ ++ struct qca8k_mgmt_eth_data mgmt_eth_data; + }; + + struct qca8k_mib_desc { +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch b/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch new file mode 100644 index 0000000000..69882e9c21 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch @@ -0,0 +1,233 @@ +From 5c957c7ca78cce5e4b96866722b0115bd758d945 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:30 +0100 +Subject: [PATCH 11/16] net: dsa: qca8k: add support for mib autocast in + Ethernet packet + +The switch can autocast MIB counter using Ethernet packet. +Add support for this and provide a handler for the tagger. +The switch will send packet with MIB counter for each port, the switch +will use completion API to wait for the correct packet to be received +and will complete the task only when each packet is received. +Although the handler will drop all the other packet, we still have to +consume each MIB packet to complete the request. This is done to prevent +mixed data with concurrent ethtool request. + +connect_tag_protocol() is used to add the handler to the tag_qca tagger, +master_state_change() use the MIB lock to make sure no MIB Ethernet is +in progress. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 106 +++++++++++++++++++++++++++++++++++++++- + drivers/net/dsa/qca8k.h | 17 ++++++- + 2 files changed, 121 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index e3a215f04559..199cf4f761c0 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -830,7 +830,10 @@ qca8k_mib_init(struct qca8k_priv *priv) + int ret; + + mutex_lock(&priv->reg_mutex); +- ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); ++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_MIB, ++ QCA8K_MIB_FUNC | QCA8K_MIB_BUSY, ++ FIELD_PREP(QCA8K_MIB_FUNC, QCA8K_MIB_FLUSH) | ++ QCA8K_MIB_BUSY); + if (ret) + goto exit; + +@@ -1901,6 +1904,97 @@ qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) + ETH_GSTRING_LEN); + } + ++static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *skb) ++{ ++ const struct qca8k_match_data *match_data; ++ struct qca8k_mib_eth_data *mib_eth_data; ++ struct qca8k_priv *priv = ds->priv; ++ const struct qca8k_mib_desc *mib; ++ struct mib_ethhdr *mib_ethhdr; ++ int i, mib_len, offset = 0; ++ u64 *data; ++ u8 port; ++ ++ mib_ethhdr = (struct mib_ethhdr *)skb_mac_header(skb); ++ mib_eth_data = &priv->mib_eth_data; ++ ++ /* The switch autocast every port. Ignore other packet and ++ * parse only the requested one. ++ */ ++ port = FIELD_GET(QCA_HDR_RECV_SOURCE_PORT, ntohs(mib_ethhdr->hdr)); ++ if (port != mib_eth_data->req_port) ++ goto exit; ++ ++ match_data = device_get_match_data(priv->dev); ++ data = mib_eth_data->data; ++ ++ for (i = 0; i < match_data->mib_count; i++) { ++ mib = &ar8327_mib[i]; ++ ++ /* First 3 mib are present in the skb head */ ++ if (i < 3) { ++ data[i] = mib_ethhdr->data[i]; ++ continue; ++ } ++ ++ mib_len = sizeof(uint32_t); ++ ++ /* Some mib are 64 bit wide */ ++ if (mib->size == 2) ++ mib_len = sizeof(uint64_t); ++ ++ /* Copy the mib value from packet to the */ ++ memcpy(data + i, skb->data + offset, mib_len); ++ ++ /* Set the offset for the next mib */ ++ offset += mib_len; ++ } ++ ++exit: ++ /* Complete on receiving all the mib packet */ ++ if (refcount_dec_and_test(&mib_eth_data->port_parsed)) ++ complete(&mib_eth_data->rw_done); ++} ++ ++static int ++qca8k_get_ethtool_stats_eth(struct dsa_switch *ds, int port, u64 *data) ++{ ++ struct dsa_port *dp = dsa_to_port(ds, port); ++ struct qca8k_mib_eth_data *mib_eth_data; ++ struct qca8k_priv *priv = ds->priv; ++ int ret; ++ ++ mib_eth_data = &priv->mib_eth_data; ++ ++ mutex_lock(&mib_eth_data->mutex); ++ ++ reinit_completion(&mib_eth_data->rw_done); ++ ++ mib_eth_data->req_port = dp->index; ++ mib_eth_data->data = data; ++ refcount_set(&mib_eth_data->port_parsed, QCA8K_NUM_PORTS); ++ ++ mutex_lock(&priv->reg_mutex); ++ ++ /* Send mib autocast request */ ++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_MIB, ++ QCA8K_MIB_FUNC | QCA8K_MIB_BUSY, ++ FIELD_PREP(QCA8K_MIB_FUNC, QCA8K_MIB_CAST) | ++ QCA8K_MIB_BUSY); ++ ++ mutex_unlock(&priv->reg_mutex); ++ ++ if (ret) ++ goto exit; ++ ++ ret = wait_for_completion_timeout(&mib_eth_data->rw_done, QCA8K_ETHERNET_TIMEOUT); ++ ++exit: ++ mutex_unlock(&mib_eth_data->mutex); ++ ++ return ret; ++} ++ + static void + qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *data) +@@ -1912,6 +2006,10 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, + u32 hi = 0; + int ret; + ++ if (priv->mgmt_master && ++ qca8k_get_ethtool_stats_eth(ds, port, data) > 0) ++ return; ++ + match_data = of_device_get_match_data(priv->dev); + + for (i = 0; i < match_data->mib_count; i++) { +@@ -2593,9 +2691,11 @@ qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, + return; + + mutex_lock(&priv->mgmt_eth_data.mutex); ++ mutex_lock(&priv->mib_eth_data.mutex); + + priv->mgmt_master = operational ? (struct net_device *)master : NULL; + ++ mutex_unlock(&priv->mib_eth_data.mutex); + mutex_unlock(&priv->mgmt_eth_data.mutex); + } + +@@ -2609,6 +2709,7 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds, + tagger_data = ds->tagger_data; + + tagger_data->rw_reg_ack_handler = qca8k_rw_reg_ack_handler; ++ tagger_data->mib_autocast_handler = qca8k_mib_autocast_handler; + + break; + default: +@@ -2737,6 +2838,9 @@ qca8k_sw_probe(struct mdio_device *mdiodev) + mutex_init(&priv->mgmt_eth_data.mutex); + init_completion(&priv->mgmt_eth_data.rw_done); + ++ mutex_init(&priv->mib_eth_data.mutex); ++ init_completion(&priv->mib_eth_data.rw_done); ++ + priv->ds->dev = &mdiodev->dev; + priv->ds->num_ports = QCA8K_NUM_PORTS; + priv->ds->priv = priv; +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 75c28689a652..2d7d084db089 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -67,7 +67,7 @@ + #define QCA8K_REG_MODULE_EN 0x030 + #define QCA8K_MODULE_EN_MIB BIT(0) + #define QCA8K_REG_MIB 0x034 +-#define QCA8K_MIB_FLUSH BIT(24) ++#define QCA8K_MIB_FUNC GENMASK(26, 24) + #define QCA8K_MIB_CPU_KEEP BIT(20) + #define QCA8K_MIB_BUSY BIT(17) + #define QCA8K_MDIO_MASTER_CTRL 0x3c +@@ -317,6 +317,12 @@ enum qca8k_vlan_cmd { + QCA8K_VLAN_READ = 6, + }; + ++enum qca8k_mid_cmd { ++ QCA8K_MIB_FLUSH = 1, ++ QCA8K_MIB_FLUSH_PORT = 2, ++ QCA8K_MIB_CAST = 3, ++}; ++ + struct ar8xxx_port_status { + int enabled; + }; +@@ -340,6 +346,14 @@ struct qca8k_mgmt_eth_data { + u32 data[4]; + }; + ++struct qca8k_mib_eth_data { ++ struct completion rw_done; ++ struct mutex mutex; /* Process one command at time */ ++ refcount_t port_parsed; /* Counter to track parsed port */ ++ u8 req_port; ++ u64 *data; /* pointer to ethtool data */ ++}; ++ + struct qca8k_ports_config { + bool sgmii_rx_clk_falling_edge; + bool sgmii_tx_clk_falling_edge; +@@ -367,6 +381,7 @@ struct qca8k_priv { + unsigned int port_mtu[QCA8K_NUM_PORTS]; + struct net_device *mgmt_master; /* Track if mdio/mib Ethernet is available */ + struct qca8k_mgmt_eth_data mgmt_eth_data; ++ struct qca8k_mib_eth_data mib_eth_data; + }; + + struct qca8k_mib_desc { +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch b/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch new file mode 100644 index 0000000000..5c65626e54 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch @@ -0,0 +1,294 @@ +From 2cd5485663847d468dc207b3ff85fb1fab44d97f Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:31 +0100 +Subject: [PATCH 12/16] net: dsa: qca8k: add support for phy read/write with + mgmt Ethernet + +Use mgmt Ethernet also for phy read/write if availabale. Use a different +seq number to make sure we receive the correct packet. +On any error, we fallback to the legacy mdio read/write. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 216 ++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/qca8k.h | 1 + + 2 files changed, 217 insertions(+) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 199cf4f761c0..0ce5b7ca0b7f 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -867,6 +867,199 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) + regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask); + } + ++static int ++qca8k_phy_eth_busy_wait(struct qca8k_mgmt_eth_data *mgmt_eth_data, ++ struct sk_buff *read_skb, u32 *val) ++{ ++ struct sk_buff *skb = skb_copy(read_skb, GFP_KERNEL); ++ bool ack; ++ int ret; ++ ++ reinit_completion(&mgmt_eth_data->rw_done); ++ ++ /* Increment seq_num and set it in the copy pkt */ ++ mgmt_eth_data->seq++; ++ qca8k_mdio_header_fill_seq_num(skb, mgmt_eth_data->seq); ++ mgmt_eth_data->ack = false; ++ ++ dev_queue_xmit(skb); ++ ++ ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done, ++ QCA8K_ETHERNET_TIMEOUT); ++ ++ ack = mgmt_eth_data->ack; ++ ++ if (ret <= 0) ++ return -ETIMEDOUT; ++ ++ if (!ack) ++ return -EINVAL; ++ ++ *val = mgmt_eth_data->data[0]; ++ ++ return 0; ++} ++ ++static int ++qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy, ++ int regnum, u16 data) ++{ ++ struct sk_buff *write_skb, *clear_skb, *read_skb; ++ struct qca8k_mgmt_eth_data *mgmt_eth_data; ++ u32 write_val, clear_val = 0, val; ++ struct net_device *mgmt_master; ++ int ret, ret1; ++ bool ack; ++ ++ if (regnum >= QCA8K_MDIO_MASTER_MAX_REG) ++ return -EINVAL; ++ ++ mgmt_eth_data = &priv->mgmt_eth_data; ++ ++ write_val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN | ++ QCA8K_MDIO_MASTER_PHY_ADDR(phy) | ++ QCA8K_MDIO_MASTER_REG_ADDR(regnum); ++ ++ if (read) { ++ write_val |= QCA8K_MDIO_MASTER_READ; ++ } else { ++ write_val |= QCA8K_MDIO_MASTER_WRITE; ++ write_val |= QCA8K_MDIO_MASTER_DATA(data); ++ } ++ ++ /* Prealloc all the needed skb before the lock */ ++ write_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, ++ &write_val, QCA8K_ETHERNET_PHY_PRIORITY); ++ if (!write_skb) ++ return -ENOMEM; ++ ++ clear_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, ++ &clear_val, QCA8K_ETHERNET_PHY_PRIORITY); ++ if (!write_skb) { ++ ret = -ENOMEM; ++ goto err_clear_skb; ++ } ++ ++ read_skb = qca8k_alloc_mdio_header(MDIO_READ, QCA8K_MDIO_MASTER_CTRL, ++ &clear_val, QCA8K_ETHERNET_PHY_PRIORITY); ++ if (!write_skb) { ++ ret = -ENOMEM; ++ goto err_read_skb; ++ } ++ ++ /* Actually start the request: ++ * 1. Send mdio master packet ++ * 2. Busy Wait for mdio master command ++ * 3. Get the data if we are reading ++ * 4. Reset the mdio master (even with error) ++ */ ++ mutex_lock(&mgmt_eth_data->mutex); ++ ++ /* Check if mgmt_master is operational */ ++ mgmt_master = priv->mgmt_master; ++ if (!mgmt_master) { ++ mutex_unlock(&mgmt_eth_data->mutex); ++ ret = -EINVAL; ++ goto err_mgmt_master; ++ } ++ ++ read_skb->dev = mgmt_master; ++ clear_skb->dev = mgmt_master; ++ write_skb->dev = mgmt_master; ++ ++ reinit_completion(&mgmt_eth_data->rw_done); ++ ++ /* Increment seq_num and set it in the write pkt */ ++ mgmt_eth_data->seq++; ++ qca8k_mdio_header_fill_seq_num(write_skb, mgmt_eth_data->seq); ++ mgmt_eth_data->ack = false; ++ ++ dev_queue_xmit(write_skb); ++ ++ ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done, ++ QCA8K_ETHERNET_TIMEOUT); ++ ++ ack = mgmt_eth_data->ack; ++ ++ if (ret <= 0) { ++ ret = -ETIMEDOUT; ++ kfree_skb(read_skb); ++ goto exit; ++ } ++ ++ if (!ack) { ++ ret = -EINVAL; ++ kfree_skb(read_skb); ++ goto exit; ++ } ++ ++ ret = read_poll_timeout(qca8k_phy_eth_busy_wait, ret1, ++ !(val & QCA8K_MDIO_MASTER_BUSY), 0, ++ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, ++ mgmt_eth_data, read_skb, &val); ++ ++ if (ret < 0 && ret1 < 0) { ++ ret = ret1; ++ goto exit; ++ } ++ ++ if (read) { ++ reinit_completion(&mgmt_eth_data->rw_done); ++ ++ /* Increment seq_num and set it in the read pkt */ ++ mgmt_eth_data->seq++; ++ qca8k_mdio_header_fill_seq_num(read_skb, mgmt_eth_data->seq); ++ mgmt_eth_data->ack = false; ++ ++ dev_queue_xmit(read_skb); ++ ++ ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done, ++ QCA8K_ETHERNET_TIMEOUT); ++ ++ ack = mgmt_eth_data->ack; ++ ++ if (ret <= 0) { ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++ ++ if (!ack) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ ret = mgmt_eth_data->data[0] & QCA8K_MDIO_MASTER_DATA_MASK; ++ } else { ++ kfree_skb(read_skb); ++ } ++exit: ++ reinit_completion(&mgmt_eth_data->rw_done); ++ ++ /* Increment seq_num and set it in the clear pkt */ ++ mgmt_eth_data->seq++; ++ qca8k_mdio_header_fill_seq_num(clear_skb, mgmt_eth_data->seq); ++ mgmt_eth_data->ack = false; ++ ++ dev_queue_xmit(clear_skb); ++ ++ wait_for_completion_timeout(&mgmt_eth_data->rw_done, ++ QCA8K_ETHERNET_TIMEOUT); ++ ++ mutex_unlock(&mgmt_eth_data->mutex); ++ ++ return ret; ++ ++ /* Error handling before lock */ ++err_mgmt_master: ++ kfree_skb(read_skb); ++err_read_skb: ++ kfree_skb(clear_skb); ++err_clear_skb: ++ kfree_skb(write_skb); ++ ++ return ret; ++} ++ + static u32 + qca8k_port_to_phy(int port) + { +@@ -989,6 +1182,12 @@ qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 da + { + struct qca8k_priv *priv = slave_bus->priv; + struct mii_bus *bus = priv->bus; ++ int ret; ++ ++ /* Use mdio Ethernet when available, fallback to legacy one on error */ ++ ret = qca8k_phy_eth_command(priv, false, phy, regnum, data); ++ if (!ret) ++ return 0; + + return qca8k_mdio_write(bus, phy, regnum, data); + } +@@ -998,6 +1197,12 @@ qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) + { + struct qca8k_priv *priv = slave_bus->priv; + struct mii_bus *bus = priv->bus; ++ int ret; ++ ++ /* Use mdio Ethernet when available, fallback to legacy one on error */ ++ ret = qca8k_phy_eth_command(priv, true, phy, regnum, 0); ++ if (ret >= 0) ++ return ret; + + return qca8k_mdio_read(bus, phy, regnum); + } +@@ -1006,6 +1211,7 @@ static int + qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) + { + struct qca8k_priv *priv = ds->priv; ++ int ret; + + /* Check if the legacy mapping should be used and the + * port is not correctly mapped to the right PHY in the +@@ -1014,6 +1220,11 @@ qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) + if (priv->legacy_phy_port_mapping) + port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; + ++ /* Use mdio Ethernet when available, fallback to legacy one on error */ ++ ret = qca8k_phy_eth_command(priv, false, port, regnum, 0); ++ if (!ret) ++ return ret; ++ + return qca8k_mdio_write(priv->bus, port, regnum, data); + } + +@@ -1030,6 +1241,11 @@ qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) + if (priv->legacy_phy_port_mapping) + port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; + ++ /* Use mdio Ethernet when available, fallback to legacy one on error */ ++ ret = qca8k_phy_eth_command(priv, true, port, regnum, 0); ++ if (ret >= 0) ++ return ret; ++ + ret = qca8k_mdio_read(priv->bus, port, regnum); + + if (ret < 0) +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 2d7d084db089..c6f6abd2108e 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -14,6 +14,7 @@ + #include + + #define QCA8K_ETHERNET_MDIO_PRIORITY 7 ++#define QCA8K_ETHERNET_PHY_PRIORITY 6 + #define QCA8K_ETHERNET_TIMEOUT 100 + + #define QCA8K_NUM_PORTS 7 +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch b/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch new file mode 100644 index 0000000000..d69b959e56 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch @@ -0,0 +1,215 @@ +From 4264350acb75430d5021a1d7de56a33faf69a097 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:32 +0100 +Subject: [PATCH 13/16] net: dsa: qca8k: move page cache to driver priv + +There can be multiple qca8k switch on the same system. Move the static +qca8k_current_page to qca8k_priv and make it specific for each switch. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 42 ++++++++++++++++++++--------------------- + drivers/net/dsa/qca8k.h | 9 +++++++++ + 2 files changed, 29 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 0ce5b7ca0b7f..86d3742b1038 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -75,12 +75,6 @@ static const struct qca8k_mib_desc ar8327_mib[] = { + MIB_DESC(1, 0xac, "TXUnicast"), + }; + +-/* The 32bit switch registers are accessed indirectly. To achieve this we need +- * to set the page of the register. Track the last page that was set to reduce +- * mdio writes +- */ +-static u16 qca8k_current_page = 0xffff; +- + static void + qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) + { +@@ -134,11 +128,13 @@ qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) + } + + static int +-qca8k_set_page(struct mii_bus *bus, u16 page) ++qca8k_set_page(struct qca8k_priv *priv, u16 page) + { ++ u16 *cached_page = &priv->mdio_cache.page; ++ struct mii_bus *bus = priv->bus; + int ret; + +- if (page == qca8k_current_page) ++ if (page == *cached_page) + return 0; + + ret = bus->write(bus, 0x18, 0, page); +@@ -148,7 +144,7 @@ qca8k_set_page(struct mii_bus *bus, u16 page) + return ret; + } + +- qca8k_current_page = page; ++ *cached_page = page; + usleep_range(1000, 2000); + return 0; + } +@@ -374,7 +370,7 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(bus, page); ++ ret = qca8k_set_page(priv, page); + if (ret < 0) + goto exit; + +@@ -400,7 +396,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(bus, page); ++ ret = qca8k_set_page(priv, page); + if (ret < 0) + goto exit; + +@@ -427,7 +423,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(bus, page); ++ ret = qca8k_set_page(priv, page); + if (ret < 0) + goto exit; + +@@ -1098,8 +1094,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) + } + + static int +-qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) ++qca8k_mdio_write(struct qca8k_priv *priv, int phy, int regnum, u16 data) + { ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; +@@ -1116,7 +1113,7 @@ qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(bus, page); ++ ret = qca8k_set_page(priv, page); + if (ret) + goto exit; + +@@ -1135,8 +1132,9 @@ qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) + } + + static int +-qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) ++qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) + { ++ struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; +@@ -1152,7 +1150,7 @@ qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- ret = qca8k_set_page(bus, page); ++ ret = qca8k_set_page(priv, page); + if (ret) + goto exit; + +@@ -1181,7 +1179,6 @@ static int + qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data) + { + struct qca8k_priv *priv = slave_bus->priv; +- struct mii_bus *bus = priv->bus; + int ret; + + /* Use mdio Ethernet when available, fallback to legacy one on error */ +@@ -1189,14 +1186,13 @@ qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 da + if (!ret) + return 0; + +- return qca8k_mdio_write(bus, phy, regnum, data); ++ return qca8k_mdio_write(priv, phy, regnum, data); + } + + static int + qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) + { + struct qca8k_priv *priv = slave_bus->priv; +- struct mii_bus *bus = priv->bus; + int ret; + + /* Use mdio Ethernet when available, fallback to legacy one on error */ +@@ -1204,7 +1200,7 @@ qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) + if (ret >= 0) + return ret; + +- return qca8k_mdio_read(bus, phy, regnum); ++ return qca8k_mdio_read(priv, phy, regnum); + } + + static int +@@ -1225,7 +1221,7 @@ qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) + if (!ret) + return ret; + +- return qca8k_mdio_write(priv->bus, port, regnum, data); ++ return qca8k_mdio_write(priv, port, regnum, data); + } + + static int +@@ -1246,7 +1242,7 @@ qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) + if (ret >= 0) + return ret; + +- ret = qca8k_mdio_read(priv->bus, port, regnum); ++ ret = qca8k_mdio_read(priv, port, regnum); + + if (ret < 0) + return 0xffff; +@@ -3042,6 +3038,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev) + return PTR_ERR(priv->regmap); + } + ++ priv->mdio_cache.page = 0xffff; ++ + /* Check the detected switch id */ + ret = qca8k_read_switch_id(priv); + if (ret) +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index c6f6abd2108e..57368acae41b 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -363,6 +363,14 @@ struct qca8k_ports_config { + u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */ + }; + ++struct qca8k_mdio_cache { ++/* The 32bit switch registers are accessed indirectly. To achieve this we need ++ * to set the page of the register. Track the last page that was set to reduce ++ * mdio writes ++ */ ++ u16 page; ++}; ++ + struct qca8k_priv { + u8 switch_id; + u8 switch_revision; +@@ -383,6 +391,7 @@ struct qca8k_priv { + struct net_device *mgmt_master; /* Track if mdio/mib Ethernet is available */ + struct qca8k_mgmt_eth_data mgmt_eth_data; + struct qca8k_mib_eth_data mib_eth_data; ++ struct qca8k_mdio_cache mdio_cache; + }; + + struct qca8k_mib_desc { +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch b/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch new file mode 100644 index 0000000000..72de25c9d8 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch @@ -0,0 +1,171 @@ +From 2481d206fae7884cd07014fd1318e63af35e99eb Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:33 +0100 +Subject: [PATCH 14/16] net: dsa: qca8k: cache lo and hi for mdio write + +From Documentation, we can cache lo and hi the same way we do with the +page. This massively reduce the mdio write as 3/4 of the time as we only +require to write the lo or hi part for a mdio write. + +Signed-off-by: Ansuel Smith +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 61 +++++++++++++++++++++++++++++++++-------- + drivers/net/dsa/qca8k.h | 5 ++++ + 2 files changed, 54 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 86d3742b1038..0cce3a6030af 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -88,6 +88,44 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) + *page = regaddr & 0x3ff; + } + ++static int ++qca8k_set_lo(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 lo) ++{ ++ u16 *cached_lo = &priv->mdio_cache.lo; ++ struct mii_bus *bus = priv->bus; ++ int ret; ++ ++ if (lo == *cached_lo) ++ return 0; ++ ++ ret = bus->write(bus, phy_id, regnum, lo); ++ if (ret < 0) ++ dev_err_ratelimited(&bus->dev, ++ "failed to write qca8k 32bit lo register\n"); ++ ++ *cached_lo = lo; ++ return 0; ++} ++ ++static int ++qca8k_set_hi(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 hi) ++{ ++ u16 *cached_hi = &priv->mdio_cache.hi; ++ struct mii_bus *bus = priv->bus; ++ int ret; ++ ++ if (hi == *cached_hi) ++ return 0; ++ ++ ret = bus->write(bus, phy_id, regnum, hi); ++ if (ret < 0) ++ dev_err_ratelimited(&bus->dev, ++ "failed to write qca8k 32bit hi register\n"); ++ ++ *cached_hi = hi; ++ return 0; ++} ++ + static int + qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + { +@@ -111,7 +149,7 @@ qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + } + + static void +-qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) ++qca8k_mii_write32(struct qca8k_priv *priv, int phy_id, u32 regnum, u32 val) + { + u16 lo, hi; + int ret; +@@ -119,12 +157,9 @@ qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) + lo = val & 0xffff; + hi = (u16)(val >> 16); + +- ret = bus->write(bus, phy_id, regnum, lo); ++ ret = qca8k_set_lo(priv, phy_id, regnum, lo); + if (ret >= 0) +- ret = bus->write(bus, phy_id, regnum + 1, hi); +- if (ret < 0) +- dev_err_ratelimited(&bus->dev, +- "failed to write qca8k 32bit register\n"); ++ ret = qca8k_set_hi(priv, phy_id, regnum + 1, hi); + } + + static int +@@ -400,7 +435,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) + if (ret < 0) + goto exit; + +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ qca8k_mii_write32(priv, 0x10 | r2, r1, val); + + exit: + mutex_unlock(&bus->mdio_lock); +@@ -433,7 +468,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ + + val &= ~mask; + val |= write_val; +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ qca8k_mii_write32(priv, 0x10 | r2, r1, val); + + exit: + mutex_unlock(&bus->mdio_lock); +@@ -1117,14 +1152,14 @@ qca8k_mdio_write(struct qca8k_priv *priv, int phy, int regnum, u16 data) + if (ret) + goto exit; + +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ qca8k_mii_write32(priv, 0x10 | r2, r1, val); + + ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); ++ qca8k_mii_write32(priv, 0x10 | r2, r1, 0); + + mutex_unlock(&bus->mdio_lock); + +@@ -1154,7 +1189,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) + if (ret) + goto exit; + +- qca8k_mii_write32(bus, 0x10 | r2, r1, val); ++ qca8k_mii_write32(priv, 0x10 | r2, r1, val); + + ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); +@@ -1165,7 +1200,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(bus, 0x10 | r2, r1, 0); ++ qca8k_mii_write32(priv, 0x10 | r2, r1, 0); + + mutex_unlock(&bus->mdio_lock); + +@@ -3039,6 +3074,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev) + } + + priv->mdio_cache.page = 0xffff; ++ priv->mdio_cache.lo = 0xffff; ++ priv->mdio_cache.hi = 0xffff; + + /* Check the detected switch id */ + ret = qca8k_read_switch_id(priv); +diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h +index 57368acae41b..c3d3c2269b1d 100644 +--- a/drivers/net/dsa/qca8k.h ++++ b/drivers/net/dsa/qca8k.h +@@ -369,6 +369,11 @@ struct qca8k_mdio_cache { + * mdio writes + */ + u16 page; ++/* lo and hi can also be cached and from Documentation we can skip one ++ * extra mdio write if lo or hi is didn't change. ++ */ ++ u16 lo; ++ u16 hi; + }; + + struct qca8k_priv { +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch b/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch new file mode 100644 index 0000000000..4b735224b6 --- /dev/null +++ b/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch @@ -0,0 +1,211 @@ +From 90386223f44e2a751d7e9e9ac8f78ea33358a891 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:34 +0100 +Subject: [PATCH 15/16] net: dsa: qca8k: add support for larger read/write size + with mgmt Ethernet + +mgmt Ethernet packet can read/write up to 16byte at times. The len reg +is limited to 15 (0xf). The switch actually sends and accepts data in 4 +different steps of len values. +Len steps: +- 0: nothing +- 1-4: first 4 byte +- 5-6: first 12 byte +- 7-15: all 16 byte + +In the alloc skb function we check if the len is 16 and we fix it to a +len of 15. It the read/write function interest to extract the real asked +data. The tagger handler will always copy the fully 16byte with a READ +command. This is useful for some big regs like the fdb reg that are +more than 4byte of data. This permits to introduce a bulk function that +will send and request the entire entry in one go. +Write function is changed and it does now require to pass the pointer to +val to also handle array val. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 61 +++++++++++++++++++++++++++-------------- + 1 file changed, 41 insertions(+), 20 deletions(-) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index 0cce3a6030af..a1b76dcd2eb6 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -222,7 +222,9 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) + if (cmd == MDIO_READ) { + mgmt_eth_data->data[0] = mgmt_ethhdr->mdio_data; + +- /* Get the rest of the 12 byte of data */ ++ /* Get the rest of the 12 byte of data. ++ * The read/write function will extract the requested data. ++ */ + if (len > QCA_HDR_MGMT_DATA1_LEN) + memcpy(mgmt_eth_data->data + 1, skb->data, + QCA_HDR_MGMT_DATA2_LEN); +@@ -232,16 +234,30 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) + } + + static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *val, +- int priority) ++ int priority, unsigned int len) + { + struct qca_mgmt_ethhdr *mgmt_ethhdr; ++ unsigned int real_len; + struct sk_buff *skb; ++ u32 *data2; + u16 hdr; + + skb = dev_alloc_skb(QCA_HDR_MGMT_PKT_LEN); + if (!skb) + return NULL; + ++ /* Max value for len reg is 15 (0xf) but the switch actually return 16 byte ++ * Actually for some reason the steps are: ++ * 0: nothing ++ * 1-4: first 4 byte ++ * 5-6: first 12 byte ++ * 7-15: all 16 byte ++ */ ++ if (len == 16) ++ real_len = 15; ++ else ++ real_len = len; ++ + skb_reset_mac_header(skb); + skb_set_network_header(skb, skb->len); + +@@ -254,7 +270,7 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 * + hdr |= FIELD_PREP(QCA_HDR_XMIT_CONTROL, QCA_HDR_XMIT_TYPE_RW_REG); + + mgmt_ethhdr->command = FIELD_PREP(QCA_HDR_MGMT_ADDR, reg); +- mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_LENGTH, 4); ++ mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_LENGTH, real_len); + mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CMD, cmd); + mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CHECK_CODE, + QCA_HDR_MGMT_CHECK_CODE_VAL); +@@ -264,7 +280,9 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 * + + mgmt_ethhdr->hdr = htons(hdr); + +- skb_put_zero(skb, QCA_HDR_MGMT_DATA2_LEN + QCA_HDR_MGMT_PADDING_LEN); ++ data2 = skb_put_zero(skb, QCA_HDR_MGMT_DATA2_LEN + QCA_HDR_MGMT_PADDING_LEN); ++ if (cmd == MDIO_WRITE && len > QCA_HDR_MGMT_DATA1_LEN) ++ memcpy(data2, val + 1, len - QCA_HDR_MGMT_DATA1_LEN); + + return skb; + } +@@ -277,7 +295,7 @@ static void qca8k_mdio_header_fill_seq_num(struct sk_buff *skb, u32 seq_num) + mgmt_ethhdr->seq = FIELD_PREP(QCA_HDR_MGMT_SEQ_NUM, seq_num); + } + +-static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) ++static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len) + { + struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data; + struct sk_buff *skb; +@@ -285,7 +303,7 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) + int ret; + + skb = qca8k_alloc_mdio_header(MDIO_READ, reg, NULL, +- QCA8K_ETHERNET_MDIO_PRIORITY); ++ QCA8K_ETHERNET_MDIO_PRIORITY, len); + if (!skb) + return -ENOMEM; + +@@ -313,6 +331,9 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) + msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT)); + + *val = mgmt_eth_data->data[0]; ++ if (len > QCA_HDR_MGMT_DATA1_LEN) ++ memcpy(val + 1, mgmt_eth_data->data + 1, len - QCA_HDR_MGMT_DATA1_LEN); ++ + ack = mgmt_eth_data->ack; + + mutex_unlock(&mgmt_eth_data->mutex); +@@ -326,15 +347,15 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) + return 0; + } + +-static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 val) ++static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len) + { + struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data; + struct sk_buff *skb; + bool ack; + int ret; + +- skb = qca8k_alloc_mdio_header(MDIO_WRITE, reg, &val, +- QCA8K_ETHERNET_MDIO_PRIORITY); ++ skb = qca8k_alloc_mdio_header(MDIO_WRITE, reg, val, ++ QCA8K_ETHERNET_MDIO_PRIORITY, len); + if (!skb) + return -ENOMEM; + +@@ -380,14 +401,14 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri + u32 val = 0; + int ret; + +- ret = qca8k_read_eth(priv, reg, &val); ++ ret = qca8k_read_eth(priv, reg, &val, sizeof(val)); + if (ret) + return ret; + + val &= ~mask; + val |= write_val; + +- return qca8k_write_eth(priv, reg, val); ++ return qca8k_write_eth(priv, reg, &val, sizeof(val)); + } + + static int +@@ -398,7 +419,7 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + u16 r1, r2, page; + int ret; + +- if (!qca8k_read_eth(priv, reg, val)) ++ if (!qca8k_read_eth(priv, reg, val, sizeof(val))) + return 0; + + qca8k_split_addr(reg, &r1, &r2, &page); +@@ -424,7 +445,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) + u16 r1, r2, page; + int ret; + +- if (!qca8k_write_eth(priv, reg, val)) ++ if (!qca8k_write_eth(priv, reg, &val, sizeof(val))) + return 0; + + qca8k_split_addr(reg, &r1, &r2, &page); +@@ -959,21 +980,21 @@ qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy, + } + + /* Prealloc all the needed skb before the lock */ +- write_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, +- &write_val, QCA8K_ETHERNET_PHY_PRIORITY); ++ write_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, &write_val, ++ QCA8K_ETHERNET_PHY_PRIORITY, sizeof(write_val)); + if (!write_skb) + return -ENOMEM; + +- clear_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, +- &clear_val, QCA8K_ETHERNET_PHY_PRIORITY); ++ clear_skb = qca8k_alloc_mdio_header(MDIO_WRITE, QCA8K_MDIO_MASTER_CTRL, &clear_val, ++ QCA8K_ETHERNET_PHY_PRIORITY, sizeof(clear_val)); + if (!write_skb) { + ret = -ENOMEM; + goto err_clear_skb; + } + +- read_skb = qca8k_alloc_mdio_header(MDIO_READ, QCA8K_MDIO_MASTER_CTRL, +- &clear_val, QCA8K_ETHERNET_PHY_PRIORITY); +- if (!write_skb) { ++ read_skb = qca8k_alloc_mdio_header(MDIO_READ, QCA8K_MDIO_MASTER_CTRL, &clear_val, ++ QCA8K_ETHERNET_PHY_PRIORITY, sizeof(clear_val)); ++ if (!read_skb) { + ret = -ENOMEM; + goto err_read_skb; + } +-- +2.34.1 + diff --git a/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch b/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch new file mode 100644 index 0000000000..ebd08845bc --- /dev/null +++ b/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch @@ -0,0 +1,109 @@ +From 4f3701fc599820568ba4395070d34e4248800fc0 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Wed, 2 Feb 2022 01:03:35 +0100 +Subject: [PATCH 16/16] net: dsa: qca8k: introduce qca8k_bulk_read/write + function + +Introduce qca8k_bulk_read/write() function to use mgmt Ethernet way to +read/write packet in bulk. Make use of this new function in the fdb +function and while at it reduce the reg for fdb_read from 4 to 3 as the +max bit for the ARL(fdb) table is 83 bits. + +Signed-off-by: Ansuel Smith +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca8k.c | 55 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 43 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c +index a1b76dcd2eb6..52ec2800dd89 100644 +--- a/drivers/net/dsa/qca8k.c ++++ b/drivers/net/dsa/qca8k.c +@@ -411,6 +411,43 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri + return qca8k_write_eth(priv, reg, &val, sizeof(val)); + } + ++static int ++qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len) ++{ ++ int i, count = len / sizeof(u32), ret; ++ ++ if (priv->mgmt_master && !qca8k_read_eth(priv, reg, val, len)) ++ return 0; ++ ++ for (i = 0; i < count; i++) { ++ ret = regmap_read(priv->regmap, reg + (i * 4), val + i); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len) ++{ ++ int i, count = len / sizeof(u32), ret; ++ u32 tmp; ++ ++ if (priv->mgmt_master && !qca8k_write_eth(priv, reg, val, len)) ++ return 0; ++ ++ for (i = 0; i < count; i++) { ++ tmp = val[i]; ++ ++ ret = regmap_write(priv->regmap, reg + (i * 4), tmp); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int + qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) + { +@@ -546,17 +583,13 @@ qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + static int + qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) + { +- u32 reg[4], val; +- int i, ret; ++ u32 reg[3]; ++ int ret; + + /* load the ARL table into an array */ +- for (i = 0; i < 4; i++) { +- ret = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4), &val); +- if (ret < 0) +- return ret; +- +- reg[i] = val; +- } ++ ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); ++ if (ret) ++ return ret; + + /* vid - 83:72 */ + fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]); +@@ -580,7 +613,6 @@ qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, + u8 aging) + { + u32 reg[3] = { 0 }; +- int i; + + /* vid - 83:72 */ + reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); +@@ -597,8 +629,7 @@ qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, + reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); + + /* load the array into the ARL table */ +- for (i = 0; i < 3; i++) +- qca8k_write(priv, QCA8K_REG_ATU_DATA0 + (i * 4), reg[i]); ++ qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); + } + + static int +-- +2.34.1 + From 49d9d2b2105d3b547dd4ae35a691ed6eec6b4845 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Tue, 1 Mar 2022 16:47:11 +0100 Subject: [PATCH 19/26] generic: fix compilation warning for ar8xxx swconfig There are 2 warning for ar8xxx swconfig. - Fix not used dev variable when ETHERNET_PACKET_MANGLE is not selected - Convert fallthrough comment to compilation macro Signed-off-by: Ansuel Smith --- target/linux/generic/files/drivers/net/phy/ar8216.c | 2 ++ target/linux/generic/files/drivers/net/phy/ar8327.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 3e6494aebb..bf98fd599e 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -2433,7 +2433,9 @@ static int ar8xxx_phy_config_init(struct phy_device *phydev) { struct ar8xxx_priv *priv = phydev->priv; +#ifdef CONFIG_ETHERNET_PACKET_MANGLE struct net_device *dev = phydev->attached_dev; +#endif int ret; if (WARN_ON(!priv)) diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.c b/target/linux/generic/files/drivers/net/phy/ar8327.c index dce52ce0e4..3313149559 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.c +++ b/target/linux/generic/files/drivers/net/phy/ar8327.c @@ -183,7 +183,7 @@ ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy) case 2: ar8xxx_phy_mmd_write(priv, phy, 0x7, 0x3c, 0x0); - /* fallthrough */ + fallthrough; case 4: ar8xxx_phy_mmd_write(priv, phy, 0x3, 0x800d, 0x803f); ar8xxx_phy_dbg_write(priv, phy, 0x3d, 0x6860); From 39a7c8d809e7b8f7c4e554a221776b824277989f Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 21 Mar 2022 15:21:24 +0100 Subject: [PATCH 20/26] generic: 5.15: refresh backport patch Use 'make target/linux/refresh' to refresh backport patches. Signed-off-by: Ansuel Smith --- .../011-kbuild-export-SUBARCH.patch | 4 +- ...0-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch | 6 +-- ...to-define-reg_update_bits-for-no-bus.patch | 6 +-- ...or-setting-affinity-if-no-IRQ-parent.patch | 6 +-- ...ow_offload-handle-netdevice-events-f.patch | 4 +- ...uce-tagger-owned-storage-for-private.patch | 41 +++++++---------- ...ocols-connect-to-individual-switches.patch | 29 ++++-------- ...dd-support-for-qca-8327-internal-phy.patch | 4 +- ...3-Include-all-ports-in-enabled_ports.patch | 24 +++++----- ...-BCM5301x-workaround-for-a-wrong-CPU.patch | 2 +- ...prove-flow-control-setup-on-BCM5301x.patch | 2 +- ...t-dsa-b53-Drop-unused-cpu_port-field.patch | 44 +++++++++---------- ...x-add-support-for-qca-8327-A-variant.patch | 10 ++--- ...dd-resume-suspend-function-to-qca83x.patch | 6 +-- ...ix-spacing-and-improve-name-for-83xx.patch | 2 +- ...hy-at803x-fix-resume-for-QCA8327-phy.patch | 8 ++-- ...x-add-DAC-amplitude-fix-for-8327-phy.patch | 10 ++--- ...nable-prefer-master-for-83xx-interna.patch | 2 +- ...hy-at803x-better-describe-debug-regs.patch | 16 +++---- ...et-dsa-qca8k-add-support-for-QCA8328.patch | 4 +- ...ernal-delay-applied-to-the-wrong-PAD.patch | 6 +-- ...16-net-dsa-qca8k-fix-MTU-calculation.patch | 2 - ...redundant-check-in-parse_port_config.patch | 7 +-- ...vert-to-GENMASK_FIELD_PREP_FIELD_GET.patch | 33 ++++++-------- ...move-extra-mutex_init-in-qca8k_setup.patch | 5 --- ...move-regmap-init-in-probe-and-set-it.patch | 7 +-- ...k-initial-conversion-to-regmap-heper.patch | 17 +++---- ...ca8k-add-additional-MIB-counter-and-.patch | 17 +++---- ...ca8k-add-support-for-port-fast-aging.patch | 11 +---- ...sa-qca8k-add-set_ageing_time-support.patch | 19 +++----- ...sa-qca8k-add-support-for-mdb_add-del.patch | 23 ++++------ ...sa-qca8k-add-support-for-mirror-mode.patch | 17 +++---- ...t-next-net-dsa-qca8k-add-LAG-support.patch | 13 ++---- ...dsa-qca8k-fix-warning-in-LAG-feature.patch | 9 +--- ...PHY-initialization-with-MTU-setup-in.patch | 15 +++---- ...nl_lock-sections-in-dsa_slave_create.patch | 7 +-- ...op-updating-master-MTU-from-master.c.patch | 11 ++--- ...l_mutex-when-calling-dsa_master_-set.patch | 15 ++----- ...t-up-shared-ports-then-non-shared-po.patch | 13 ++---- ...xt-net-dsa-setup-master-before-ports.patch | 15 +++---- ...switch-operations-for-tracking-the-m.patch | 39 ++++++---------- ...aster-state-events-in-dsa_tree_-setu.patch | 9 +--- ...t-dsa-tag_qca-convert-to-FIELD-macro.patch | 16 +++---- ...qca-move-define-to-include-linux-dsa.patch | 8 ---- ...ag_qca-enable-promisc_on_master-flag.patch | 7 +-- ...add-define-for-handling-mgmt-Etherne.patch | 11 +---- ...a-add-define-for-handling-MIB-packet.patch | 9 +--- ...add-support-for-handling-mgmt-and-MI.patch | 15 ++----- ...8k-add-tracking-state-of-master-port.patch | 11 +---- ...d-support-for-mgmt-read-write-in-Eth.patch | 21 +++------ ...d-support-for-mib-autocast-in-Ethern.patch | 17 +++---- ...d-support-for-phy-read-write-with-mg.patch | 17 +++---- ...qca8k-move-page-cache-to-driver-priv.patch | 37 +++++++--------- ...qca8k-cache-lo-and-hi-for-mdio-write.patch | 31 +++++-------- ...d-support-for-larger-read-write-size.patch | 29 +++++------- ...troduce-qca8k_bulk_read-write-functi.patch | 19 +++----- ...N-filtering-syncing-out-of-dsa_switc.patch | 8 +--- ...cross-chip-syncing-of-VLAN-filtering.patch | 8 +--- ...-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch | 6 +-- ...PCI-aardvark-Clear-all-MSIs-at-setup.patch | 8 ++-- ...ment-actions-in-driver-remove-method.patch | 2 +- ...able-bus-mastering-when-unbinding-dr.patch | 4 +- ...k-all-interrupts-when-unbinding-driv.patch | 2 +- ...ark-Fix-memory-leak-in-driver-unbind.patch | 2 +- ...k-Assert-PERST-when-unbinding-driver.patch | 2 +- ...able-link-training-when-unbinding-dr.patch | 2 +- ...able-common-PHY-when-unbinding-drive.patch | 2 +- ...PS-ath79-drop-_machine_restart-again.patch | 2 +- 68 files changed, 293 insertions(+), 543 deletions(-) diff --git a/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch b/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch index bb99e4ddbf..0aedad4bfd 100644 --- a/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/backport-5.15/011-kbuild-export-SUBARCH.patch @@ -10,12 +10,12 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -507,7 +507,7 @@ KBUILD_LDFLAGS_MODULE := +@@ -523,7 +523,7 @@ KBUILD_LDFLAGS_MODULE := KBUILD_LDFLAGS := CLANG_FLAGS := -export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC +export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL - export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX + export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD diff --git a/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch b/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch index 10685c5f3c..00b3536b6d 100644 --- a/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch +++ b/target/linux/generic/backport-5.15/050-v5.16-05-mips-bpf-Enable-eBPF-JITs.patch @@ -14,7 +14,7 @@ Signed-off-by: Johan Almbladh --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -3294,6 +3294,7 @@ S: Supported +@@ -3428,6 +3428,7 @@ S: Supported F: arch/arm64/net/ BPF JIT for MIPS (32-BIT AND 64-BIT) @@ -24,7 +24,7 @@ Signed-off-by: Johan Almbladh L: bpf@vger.kernel.org --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -49,7 +49,6 @@ config MIPS +@@ -57,7 +57,6 @@ config MIPS select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES select HAVE_ASM_MODVERSIONS @@ -32,7 +32,7 @@ Signed-off-by: Johan Almbladh select HAVE_CONTEXT_TRACKING select HAVE_TIF_NOHZ select HAVE_C_RECORDMCOUNT -@@ -57,7 +56,10 @@ config MIPS +@@ -65,7 +64,10 @@ config MIPS select HAVE_DEBUG_STACKOVERFLOW select HAVE_DMA_CONTIGUOUS select HAVE_DYNAMIC_FTRACE diff --git a/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch b/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch index 6e274acb1f..e4c0833ae7 100644 --- a/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch +++ b/target/linux/generic/backport-5.15/081-net-next-regmap-allow-to-define-reg_update_bits-for-no-bus.patch @@ -19,7 +19,7 @@ Signed-off-by: Mark Brown --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c -@@ -842,6 +842,7 @@ struct regmap *__regmap_init(struct devi +@@ -877,6 +877,7 @@ struct regmap *__regmap_init(struct devi if (!bus) { map->reg_read = config->reg_read; map->reg_write = config->reg_write; @@ -29,7 +29,7 @@ Signed-off-by: Mark Brown goto skip_format_initialization; --- a/include/linux/regmap.h +++ b/include/linux/regmap.h -@@ -289,6 +289,11 @@ typedef void (*regmap_unlock)(void *); +@@ -290,6 +290,11 @@ typedef void (*regmap_unlock)(void *); * read operation on a bus such as SPI, I2C, etc. Most of the * devices do not need this. * @reg_write: Same as above for writing. @@ -41,7 +41,7 @@ Signed-off-by: Mark Brown * @fast_io: Register IO is fast. Use a spinlock instead of a mutex * to perform locking. This field is ignored if custom lock/unlock * functions are used (see fields lock/unlock of struct regmap_config). -@@ -366,6 +371,8 @@ struct regmap_config { +@@ -372,6 +377,8 @@ struct regmap_config { int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); diff --git a/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch b/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch index 796ca74b4d..18a8752a18 100644 --- a/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch +++ b/target/linux/generic/backport-5.15/300-v5.18-pinctrl-qcom-Return--EINVAL-for-setting-affinity-if-no-IRQ-parent.patch @@ -26,11 +26,9 @@ Signed-off-by: Manivannan Sadhasivam drivers/pinctrl/qcom/pinctrl-msm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c -index 8476a8ac4451..a42ff4b22a04 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c -@@ -1157,7 +1157,7 @@ static int msm_gpio_irq_set_affinity(struct irq_data *d, +@@ -1157,7 +1157,7 @@ static int msm_gpio_irq_set_affinity(str if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs)) return irq_chip_set_affinity_parent(d, dest, force); @@ -39,7 +37,7 @@ index 8476a8ac4451..a42ff4b22a04 100644 } static int msm_gpio_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) -@@ -1168,7 +1168,7 @@ static int msm_gpio_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) +@@ -1168,7 +1168,7 @@ static int msm_gpio_irq_set_vcpu_affinit if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs)) return irq_chip_set_vcpu_affinity_parent(d, vcpu_info); diff --git a/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index d300af3342..9a6b802fd1 100644 --- a/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -10,7 +10,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c -@@ -576,13 +576,41 @@ void nf_flow_table_free(struct nf_flowta +@@ -646,13 +646,41 @@ void nf_flow_table_free(struct nf_flowta } EXPORT_SYMBOL_GPL(nf_flow_table_free); @@ -55,7 +55,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c -@@ -237,47 +237,14 @@ static struct nft_expr_type nft_flow_off +@@ -438,47 +438,14 @@ static struct nft_expr_type nft_flow_off .owner = THIS_MODULE, }; diff --git a/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch b/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch index 019d0d5ee8..fe47c175a4 100644 --- a/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch +++ b/target/linux/generic/backport-5.15/700-net-next-net-dsa-introduce-tagger-owned-storage-for-private.patch @@ -67,11 +67,9 @@ Signed-off-by: David S. Miller net/dsa/switch.c | 14 +++++++++++ 4 files changed, 96 insertions(+), 4 deletions(-) -diff --git a/include/net/dsa.h b/include/net/dsa.h -index bdf308a5c55ee..8b496c7e62ef8 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h -@@ -82,12 +82,15 @@ enum dsa_tag_protocol { +@@ -80,12 +80,15 @@ enum dsa_tag_protocol { }; struct dsa_switch; @@ -87,7 +85,7 @@ index bdf308a5c55ee..8b496c7e62ef8 100644 unsigned int needed_headroom; unsigned int needed_tailroom; const char *name; -@@ -337,6 +340,8 @@ struct dsa_switch { +@@ -329,6 +332,8 @@ struct dsa_switch { */ void *priv; @@ -96,7 +94,7 @@ index bdf308a5c55ee..8b496c7e62ef8 100644 /* * Configuration data for this switch. */ -@@ -689,6 +694,13 @@ struct dsa_switch_ops { +@@ -584,6 +589,13 @@ struct dsa_switch_ops { enum dsa_tag_protocol mprot); int (*change_tag_protocol)(struct dsa_switch *ds, int port, enum dsa_tag_protocol proto); @@ -110,11 +108,9 @@ index bdf308a5c55ee..8b496c7e62ef8 100644 /* Optional switch-wide initialization and destruction methods */ int (*setup)(struct dsa_switch *ds); -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index 8814fa0e44c84..cf65661686209 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c -@@ -248,8 +248,12 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index) +@@ -230,8 +230,12 @@ static struct dsa_switch_tree *dsa_tree_ static void dsa_tree_free(struct dsa_switch_tree *dst) { @@ -128,16 +124,16 @@ index 8814fa0e44c84..cf65661686209 100644 list_del(&dst->list); kfree(dst); } -@@ -822,7 +826,7 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) - int err; +@@ -805,7 +809,7 @@ static int dsa_switch_setup_tag_protocol + int port, err; if (tag_ops->proto == dst->default_proto) - return 0; + goto connect; - dsa_switch_for_each_cpu_port(cpu_dp, ds) { - rtnl_lock(); -@@ -836,6 +840,17 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) + for (port = 0; port < ds->num_ports; port++) { + if (!dsa_is_cpu_port(ds, port)) +@@ -821,6 +825,17 @@ static int dsa_switch_setup_tag_protocol } } @@ -155,7 +151,7 @@ index 8814fa0e44c84..cf65661686209 100644 return 0; } -@@ -1136,6 +1151,46 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) +@@ -1132,6 +1147,46 @@ static void dsa_tree_teardown(struct dsa dst->setup = false; } @@ -202,7 +198,7 @@ index 8814fa0e44c84..cf65661686209 100644 /* Since the dsa/tagging sysfs device attribute is per master, the assumption * is that all DSA switches within a tree share the same tagger, otherwise * they would have formed disjoint trees (different "dsa,member" values). -@@ -1168,12 +1223,15 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, +@@ -1164,12 +1219,15 @@ int dsa_tree_change_tag_proto(struct dsa goto out_unlock; } @@ -220,7 +216,7 @@ index 8814fa0e44c84..cf65661686209 100644 rtnl_unlock(); -@@ -1260,6 +1318,7 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, +@@ -1257,6 +1315,7 @@ static int dsa_port_parse_cpu(struct dsa struct dsa_switch_tree *dst = ds->dst; const struct dsa_device_ops *tag_ops; enum dsa_tag_protocol default_proto; @@ -228,7 +224,7 @@ index 8814fa0e44c84..cf65661686209 100644 /* Find out which protocol the switch would prefer. */ default_proto = dsa_get_tag_protocol(dp, master); -@@ -1307,6 +1366,12 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, +@@ -1304,6 +1363,12 @@ static int dsa_port_parse_cpu(struct dsa */ dsa_tag_driver_put(tag_ops); } else { @@ -241,8 +237,6 @@ index 8814fa0e44c84..cf65661686209 100644 dst->tag_ops = tag_ops; } -diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h -index 38ce5129a33dc..0db2b26b0c83c 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -37,6 +37,7 @@ enum { @@ -253,11 +247,9 @@ index 38ce5129a33dc..0db2b26b0c83c 100644 DSA_NOTIFIER_MRP_ADD, DSA_NOTIFIER_MRP_DEL, DSA_NOTIFIER_MRP_ADD_RING_ROLE, -diff --git a/net/dsa/switch.c b/net/dsa/switch.c -index 9c92edd969612..06948f5368296 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -647,6 +647,17 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds, +@@ -616,6 +616,17 @@ static int dsa_switch_change_tag_proto(s return 0; } @@ -275,7 +267,7 @@ index 9c92edd969612..06948f5368296 100644 static int dsa_switch_mrp_add(struct dsa_switch *ds, struct dsa_notifier_mrp_info *info) { -@@ -766,6 +777,9 @@ static int dsa_switch_event(struct notifier_block *nb, +@@ -735,6 +746,9 @@ static int dsa_switch_event(struct notif case DSA_NOTIFIER_TAG_PROTO: err = dsa_switch_change_tag_proto(ds, info); break; @@ -285,6 +277,3 @@ index 9c92edd969612..06948f5368296 100644 case DSA_NOTIFIER_MRP_ADD: err = dsa_switch_mrp_add(ds, info); break; --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch b/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch index fa3752ac34..f682260699 100644 --- a/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch +++ b/target/linux/generic/backport-5.15/701-net-dsa-make-tagging-protocols-connect-to-individual-switches.patch @@ -65,11 +65,9 @@ Signed-off-by: David S. Miller net/dsa/tag_sja1105.c | 67 ++++++++++++++++------------------------------ 6 files changed, 109 insertions(+), 113 deletions(-) -diff --git a/include/net/dsa.h b/include/net/dsa.h -index 64d71968aa91a..f16959444ae12 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h -@@ -82,15 +82,14 @@ enum dsa_tag_protocol { +@@ -80,15 +80,14 @@ enum dsa_tag_protocol { }; struct dsa_switch; @@ -87,11 +85,9 @@ index 64d71968aa91a..f16959444ae12 100644 unsigned int needed_headroom; unsigned int needed_tailroom; const char *name; -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index cf65661686209..c18b22c0bf55e 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c -@@ -248,12 +248,8 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index) +@@ -230,12 +230,8 @@ static struct dsa_switch_tree *dsa_tree_ static void dsa_tree_free(struct dsa_switch_tree *dst) { @@ -105,7 +101,7 @@ index cf65661686209..c18b22c0bf55e 100644 list_del(&dst->list); kfree(dst); } -@@ -841,17 +837,29 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) +@@ -826,17 +822,29 @@ static int dsa_switch_setup_tag_protocol } connect: @@ -136,7 +132,7 @@ index cf65661686209..c18b22c0bf55e 100644 } static int dsa_switch_setup(struct dsa_switch *ds) -@@ -1160,13 +1168,6 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, +@@ -1156,13 +1164,6 @@ static int dsa_tree_bind_tag_proto(struc dst->tag_ops = tag_ops; @@ -150,7 +146,7 @@ index cf65661686209..c18b22c0bf55e 100644 /* Notify the switches from this tree about the connection * to the new tagger */ -@@ -1176,16 +1177,14 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, +@@ -1172,16 +1173,14 @@ static int dsa_tree_bind_tag_proto(struc goto out_disconnect; /* Notify the old tagger about the disconnection from this tree */ @@ -171,7 +167,7 @@ index cf65661686209..c18b22c0bf55e 100644 dst->tag_ops = old_tag_ops; return err; -@@ -1318,7 +1317,6 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, +@@ -1315,7 +1314,6 @@ static int dsa_port_parse_cpu(struct dsa struct dsa_switch_tree *dst = ds->dst; const struct dsa_device_ops *tag_ops; enum dsa_tag_protocol default_proto; @@ -179,7 +175,7 @@ index cf65661686209..c18b22c0bf55e 100644 /* Find out which protocol the switch would prefer. */ default_proto = dsa_get_tag_protocol(dp, master); -@@ -1366,12 +1364,6 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master, +@@ -1363,12 +1361,6 @@ static int dsa_port_parse_cpu(struct dsa */ dsa_tag_driver_put(tag_ops); } else { @@ -192,8 +188,6 @@ index cf65661686209..c18b22c0bf55e 100644 dst->tag_ops = tag_ops; } -diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h -index 0db2b26b0c83c..edfaae7b59672 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -38,6 +38,7 @@ enum { @@ -204,11 +198,9 @@ index 0db2b26b0c83c..edfaae7b59672 100644 DSA_NOTIFIER_MRP_ADD, DSA_NOTIFIER_MRP_DEL, DSA_NOTIFIER_MRP_ADD_RING_ROLE, -diff --git a/net/dsa/switch.c b/net/dsa/switch.c -index 06948f5368296..393f2d8a860a9 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -647,15 +647,58 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds, +@@ -616,15 +616,58 @@ static int dsa_switch_change_tag_proto(s return 0; } @@ -270,7 +262,7 @@ index 06948f5368296..393f2d8a860a9 100644 } static int dsa_switch_mrp_add(struct dsa_switch *ds, -@@ -780,6 +823,9 @@ static int dsa_switch_event(struct notifier_block *nb, +@@ -749,6 +792,9 @@ static int dsa_switch_event(struct notif case DSA_NOTIFIER_TAG_PROTO_CONNECT: err = dsa_switch_connect_tag_proto(ds, info); break; @@ -280,6 +272,3 @@ index 06948f5368296..393f2d8a860a9 100644 case DSA_NOTIFIER_MRP_ADD: err = dsa_switch_mrp_add(ds, info); break; --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch b/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch index 16aa0711ad..e4bead892c 100644 --- a/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch +++ b/target/linux/generic/backport-5.15/742-v5.16-net-phy-at803x-add-support-for-qca-8327-internal-phy.patch @@ -17,7 +17,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c -@@ -1328,6 +1328,19 @@ static struct phy_driver at803x_driver[] +@@ -1420,6 +1420,19 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, @@ -37,7 +37,7 @@ Signed-off-by: David S. Miller }, }; module_phy_driver(at803x_driver); -@@ -1338,6 +1351,8 @@ static struct mdio_device_id __maybe_unu +@@ -1430,6 +1443,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, diff --git a/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch b/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch index d80b5db714..eb84b45b5c 100644 --- a/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch +++ b/target/linux/generic/backport-5.15/743-v5.16-0001-net-dsa-b53-Include-all-ports-in-enabled_ports.patch @@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c -@@ -2288,7 +2288,7 @@ static const struct b53_chip_data b53_sw +@@ -2302,7 +2302,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM5325_DEVICE_ID, .dev_name = "BCM5325", .vlans = 16, @@ -31,7 +31,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 2, .arl_buckets = 1024, .imp_port = 5, -@@ -2299,7 +2299,7 @@ static const struct b53_chip_data b53_sw +@@ -2313,7 +2313,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM5365_DEVICE_ID, .dev_name = "BCM5365", .vlans = 256, @@ -40,7 +40,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 2, .arl_buckets = 1024, .imp_port = 5, -@@ -2310,7 +2310,7 @@ static const struct b53_chip_data b53_sw +@@ -2324,7 +2324,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM5389_DEVICE_ID, .dev_name = "BCM5389", .vlans = 4096, @@ -49,7 +49,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2324,7 +2324,7 @@ static const struct b53_chip_data b53_sw +@@ -2338,7 +2338,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM5395_DEVICE_ID, .dev_name = "BCM5395", .vlans = 4096, @@ -58,7 +58,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2338,7 +2338,7 @@ static const struct b53_chip_data b53_sw +@@ -2352,7 +2352,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM5397_DEVICE_ID, .dev_name = "BCM5397", .vlans = 4096, @@ -67,7 +67,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2352,7 +2352,7 @@ static const struct b53_chip_data b53_sw +@@ -2366,7 +2366,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM5398_DEVICE_ID, .dev_name = "BCM5398", .vlans = 4096, @@ -76,7 +76,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2366,7 +2366,7 @@ static const struct b53_chip_data b53_sw +@@ -2380,7 +2380,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM53115_DEVICE_ID, .dev_name = "BCM53115", .vlans = 4096, @@ -85,7 +85,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .vta_regs = B53_VTA_REGS, -@@ -2380,7 +2380,7 @@ static const struct b53_chip_data b53_sw +@@ -2394,7 +2394,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM53125_DEVICE_ID, .dev_name = "BCM53125", .vlans = 4096, @@ -94,7 +94,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2422,7 +2422,7 @@ static const struct b53_chip_data b53_sw +@@ -2436,7 +2436,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM53010_DEVICE_ID, .dev_name = "BCM53010", .vlans = 4096, @@ -103,7 +103,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2464,7 +2464,7 @@ static const struct b53_chip_data b53_sw +@@ -2478,7 +2478,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM53018_DEVICE_ID, .dev_name = "BCM53018", .vlans = 4096, @@ -112,7 +112,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2478,7 +2478,7 @@ static const struct b53_chip_data b53_sw +@@ -2492,7 +2492,7 @@ static const struct b53_chip_data b53_sw .chip_id = BCM53019_DEVICE_ID, .dev_name = "BCM53019", .vlans = 4096, @@ -121,7 +121,7 @@ Signed-off-by: Jakub Kicinski .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, -@@ -2605,7 +2605,6 @@ static int b53_switch_init(struct b53_de +@@ -2634,7 +2634,6 @@ static int b53_switch_init(struct b53_de dev->cpu_port = 5; } diff --git a/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch b/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch index 4a4f8e940d..23805a9027 100644 --- a/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch +++ b/target/linux/generic/backport-5.15/743-v5.16-0002-net-dsa-b53-Drop-BCM5301x-workaround-for-a-wrong-CPU.patch @@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c -@@ -1256,12 +1256,6 @@ static void b53_adjust_link(struct dsa_s +@@ -1291,12 +1291,6 @@ static void b53_adjust_link(struct dsa_s return; } } diff --git a/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch b/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch index 3954ee4aac..941fa23eb4 100644 --- a/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch +++ b/target/linux/generic/backport-5.15/743-v5.16-0003-net-dsa-b53-Improve-flow-control-setup-on-BCM5301x.patch @@ -21,7 +21,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c -@@ -1187,7 +1187,7 @@ static void b53_adjust_link(struct dsa_s +@@ -1222,7 +1222,7 @@ static void b53_adjust_link(struct dsa_s return; /* Enable flow control on BCM5301x's CPU port */ diff --git a/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch b/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch index 9e687b1488..746a1e3978 100644 --- a/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch +++ b/target/linux/generic/backport-5.15/743-v5.16-0004-net-dsa-b53-Drop-unused-cpu_port-field.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c -@@ -2286,7 +2286,6 @@ static const struct b53_chip_data b53_sw +@@ -2300,7 +2300,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 2, .arl_buckets = 1024, .imp_port = 5, @@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski .duplex_reg = B53_DUPLEX_STAT_FE, }, { -@@ -2297,7 +2296,6 @@ static const struct b53_chip_data b53_sw +@@ -2311,7 +2310,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 2, .arl_buckets = 1024, .imp_port = 5, @@ -35,7 +35,7 @@ Signed-off-by: Jakub Kicinski .duplex_reg = B53_DUPLEX_STAT_FE, }, { -@@ -2308,7 +2306,6 @@ static const struct b53_chip_data b53_sw +@@ -2322,7 +2320,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -43,7 +43,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2322,7 +2319,6 @@ static const struct b53_chip_data b53_sw +@@ -2336,7 +2333,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -51,7 +51,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2336,7 +2332,6 @@ static const struct b53_chip_data b53_sw +@@ -2350,7 +2346,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -59,7 +59,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS_9798, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2350,7 +2345,6 @@ static const struct b53_chip_data b53_sw +@@ -2364,7 +2359,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -67,7 +67,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS_9798, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2365,7 +2359,6 @@ static const struct b53_chip_data b53_sw +@@ -2379,7 +2373,6 @@ static const struct b53_chip_data b53_sw .arl_buckets = 1024, .vta_regs = B53_VTA_REGS, .imp_port = 8, @@ -75,7 +75,7 @@ Signed-off-by: Jakub Kicinski .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -@@ -2378,7 +2371,6 @@ static const struct b53_chip_data b53_sw +@@ -2392,7 +2385,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -83,7 +83,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2392,7 +2384,6 @@ static const struct b53_chip_data b53_sw +@@ -2406,7 +2398,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -91,7 +91,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2406,7 +2397,6 @@ static const struct b53_chip_data b53_sw +@@ -2420,7 +2411,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -99,7 +99,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS_63XX, .duplex_reg = B53_DUPLEX_STAT_63XX, .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, -@@ -2420,7 +2410,6 @@ static const struct b53_chip_data b53_sw +@@ -2434,7 +2424,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2434,7 +2423,6 @@ static const struct b53_chip_data b53_sw +@@ -2448,7 +2437,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -115,7 +115,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2448,7 +2436,6 @@ static const struct b53_chip_data b53_sw +@@ -2462,7 +2450,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -123,7 +123,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2462,7 +2449,6 @@ static const struct b53_chip_data b53_sw +@@ -2476,7 +2463,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -131,7 +131,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2476,7 +2462,6 @@ static const struct b53_chip_data b53_sw +@@ -2490,7 +2476,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -139,7 +139,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2490,7 +2475,6 @@ static const struct b53_chip_data b53_sw +@@ -2504,7 +2489,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -147,7 +147,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2504,7 +2488,6 @@ static const struct b53_chip_data b53_sw +@@ -2518,7 +2502,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -155,7 +155,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2518,7 +2501,6 @@ static const struct b53_chip_data b53_sw +@@ -2547,7 +2530,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 1024, .imp_port = 8, @@ -163,7 +163,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2532,7 +2514,6 @@ static const struct b53_chip_data b53_sw +@@ -2561,7 +2543,6 @@ static const struct b53_chip_data b53_sw .arl_bins = 4, .arl_buckets = 256, .imp_port = 8, @@ -171,7 +171,7 @@ Signed-off-by: Jakub Kicinski .vta_regs = B53_VTA_REGS, .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -@@ -2558,7 +2539,6 @@ static int b53_switch_init(struct b53_de +@@ -2587,7 +2568,6 @@ static int b53_switch_init(struct b53_de dev->vta_regs[2] = chip->vta_regs[2]; dev->jumbo_pm_reg = chip->jumbo_pm_reg; dev->imp_port = chip->imp_port; @@ -179,7 +179,7 @@ Signed-off-by: Jakub Kicinski dev->num_vlans = chip->vlans; dev->num_arl_bins = chip->arl_bins; dev->num_arl_buckets = chip->arl_buckets; -@@ -2590,13 +2570,6 @@ static int b53_switch_init(struct b53_de +@@ -2619,13 +2599,6 @@ static int b53_switch_init(struct b53_de break; #endif } @@ -195,7 +195,7 @@ Signed-off-by: Jakub Kicinski dev->num_ports = fls(dev->enabled_ports); --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h -@@ -123,7 +123,6 @@ struct b53_device { +@@ -124,7 +124,6 @@ struct b53_device { /* used ports mask */ u16 enabled_ports; unsigned int imp_port; diff --git a/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch b/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch index c82bf913a0..07428364aa 100644 --- a/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch +++ b/target/linux/generic/backport-5.15/745-v5.16-01-net-phy-at803x-add-support-for-qca-8327-A-variant.patch @@ -16,9 +16,9 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c -@@ -148,7 +148,8 @@ - #define AT803X_PAGE_FIBER 0 - #define AT803X_PAGE_COPPER 1 +@@ -150,7 +150,8 @@ + #define ATH8035_PHY_ID 0x004dd072 + #define AT8030_PHY_ID_MASK 0xffffffef -#define QCA8327_PHY_ID 0x004dd034 +#define QCA8327_A_PHY_ID 0x004dd033 @@ -26,7 +26,7 @@ Signed-off-by: David S. Miller #define QCA8337_PHY_ID 0x004dd036 #define QCA8K_PHY_ID_MASK 0xffffffff -@@ -1329,10 +1330,23 @@ static struct phy_driver at803x_driver[] +@@ -1421,10 +1422,23 @@ static struct phy_driver at803x_driver[] .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, }, { @@ -53,7 +53,7 @@ Signed-off-by: David S. Miller /* PHY_GBIT_FEATURES */ .probe = at803x_probe, .flags = PHY_IS_INTERNAL, -@@ -1352,7 +1366,8 @@ static struct mdio_device_id __maybe_unu +@@ -1444,7 +1458,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, diff --git a/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch b/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch index be24fd5cf7..a572a318c8 100644 --- a/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch +++ b/target/linux/generic/backport-5.15/745-v5.16-02-net-phy-at803x-add-resume-suspend-function-to-qca83x.patch @@ -16,7 +16,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c -@@ -1329,6 +1329,8 @@ static struct phy_driver at803x_driver[] +@@ -1421,6 +1421,8 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, @@ -25,7 +25,7 @@ Signed-off-by: David S. Miller }, { /* QCA8327-A from switch QCA8327-AL1A */ .phy_id = QCA8327_A_PHY_ID, -@@ -1342,6 +1344,8 @@ static struct phy_driver at803x_driver[] +@@ -1434,6 +1436,8 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, @@ -34,7 +34,7 @@ Signed-off-by: David S. Miller }, { /* QCA8327-B from switch QCA8327-BL1A */ .phy_id = QCA8327_B_PHY_ID, -@@ -1355,6 +1359,8 @@ static struct phy_driver at803x_driver[] +@@ -1447,6 +1451,8 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, diff --git a/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch b/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch index 23f574c76f..45c1ff27dc 100644 --- a/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch +++ b/target/linux/generic/backport-5.15/745-v5.16-03-net-phy-at803x-fix-spacing-and-improve-name-for-83xx.patch @@ -15,7 +15,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c -@@ -1318,47 +1318,47 @@ static struct phy_driver at803x_driver[] +@@ -1410,47 +1410,47 @@ static struct phy_driver at803x_driver[] .config_aneg = at803x_config_aneg, }, { /* QCA8337 */ diff --git a/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch b/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch index 5dfe27dd24..7f9182ab19 100644 --- a/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch +++ b/target/linux/generic/backport-5.15/746-v5.16-01-net-phy-at803x-fix-resume-for-QCA8327-phy.patch @@ -37,7 +37,7 @@ Signed-off-by: David S. Miller #define AT803X_DEBUG_REG_1F 0x1F #define AT803X_DEBUG_PLL_ON BIT(2) -@@ -1220,6 +1225,58 @@ static int qca83xx_config_init(struct ph +@@ -1312,6 +1317,58 @@ static int qca83xx_config_init(struct ph return 0; } @@ -96,7 +96,7 @@ Signed-off-by: David S. Miller static struct phy_driver at803x_driver[] = { { /* Qualcomm Atheros AR8035 */ -@@ -1329,8 +1386,8 @@ static struct phy_driver at803x_driver[] +@@ -1421,8 +1478,8 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, @@ -107,7 +107,7 @@ Signed-off-by: David S. Miller }, { /* QCA8327-A from switch QCA8327-AL1A */ .phy_id = QCA8327_A_PHY_ID, -@@ -1344,8 +1401,8 @@ static struct phy_driver at803x_driver[] +@@ -1436,8 +1493,8 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, @@ -118,7 +118,7 @@ Signed-off-by: David S. Miller }, { /* QCA8327-B from switch QCA8327-BL1A */ .phy_id = QCA8327_B_PHY_ID, -@@ -1359,8 +1416,8 @@ static struct phy_driver at803x_driver[] +@@ -1451,8 +1508,8 @@ static struct phy_driver at803x_driver[] .get_sset_count = at803x_get_sset_count, .get_strings = at803x_get_strings, .get_stats = at803x_get_stats, diff --git a/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch b/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch index aeb43e2f67..cfdfe2c47f 100644 --- a/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch +++ b/target/linux/generic/backport-5.15/746-v5.16-02-net-phy-at803x-add-DAC-amplitude-fix-for-8327-phy.patch @@ -19,7 +19,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -87,6 +87,8 @@ - #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 #define AT803X_DEBUG_REG_0 0x00 +#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) @@ -27,7 +27,7 @@ Signed-off-by: David S. Miller #define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) #define AT803X_DEBUG_REG_5 0x05 -@@ -1222,9 +1224,37 @@ static int qca83xx_config_init(struct ph +@@ -1314,9 +1316,37 @@ static int qca83xx_config_init(struct ph break; } @@ -65,7 +65,7 @@ Signed-off-by: David S. Miller static int qca83xx_resume(struct phy_device *phydev) { int ret, val; -@@ -1379,6 +1409,7 @@ static struct phy_driver at803x_driver[] +@@ -1471,6 +1501,7 @@ static struct phy_driver at803x_driver[] .phy_id_mask = QCA8K_PHY_ID_MASK, .name = "Qualcomm Atheros 8337 internal PHY", /* PHY_GBIT_FEATURES */ @@ -73,7 +73,7 @@ Signed-off-by: David S. Miller .probe = at803x_probe, .flags = PHY_IS_INTERNAL, .config_init = qca83xx_config_init, -@@ -1394,6 +1425,7 @@ static struct phy_driver at803x_driver[] +@@ -1486,6 +1517,7 @@ static struct phy_driver at803x_driver[] .phy_id_mask = QCA8K_PHY_ID_MASK, .name = "Qualcomm Atheros 8327-A internal PHY", /* PHY_GBIT_FEATURES */ @@ -81,7 +81,7 @@ Signed-off-by: David S. Miller .probe = at803x_probe, .flags = PHY_IS_INTERNAL, .config_init = qca83xx_config_init, -@@ -1409,6 +1441,7 @@ static struct phy_driver at803x_driver[] +@@ -1501,6 +1533,7 @@ static struct phy_driver at803x_driver[] .phy_id_mask = QCA8K_PHY_ID_MASK, .name = "Qualcomm Atheros 8327-B internal PHY", /* PHY_GBIT_FEATURES */ diff --git a/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch b/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch index 2352fa0e44..71c1e60fac 100644 --- a/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch +++ b/target/linux/generic/backport-5.15/746-v5.16-03-net-phy-at803x-enable-prefer-master-for-83xx-interna.patch @@ -15,7 +15,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c -@@ -1233,6 +1233,9 @@ static int qca83xx_config_init(struct ph +@@ -1325,6 +1325,9 @@ static int qca83xx_config_init(struct ph at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, QCA8327_DEBUG_MANU_CTRL_EN, 0); diff --git a/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch b/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch index 9c28a893f1..64163bfb41 100644 --- a/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch +++ b/target/linux/generic/backport-5.15/746-v5.16-04-net-phy-at803x-better-describe-debug-regs.patch @@ -16,8 +16,8 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -86,12 +86,12 @@ - #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ - #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 -#define AT803X_DEBUG_REG_0 0x00 +#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 @@ -39,7 +39,7 @@ Signed-off-by: David S. Miller #define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) #define AT803X_DEBUG_REG_1F 0x1F -@@ -274,25 +274,25 @@ static int at803x_read_page(struct phy_d +@@ -284,25 +284,25 @@ static int at803x_read_page(struct phy_d static int at803x_enable_rx_delay(struct phy_device *phydev) { @@ -69,7 +69,7 @@ Signed-off-by: David S. Miller AT803X_DEBUG_TX_CLK_DLY_EN, 0); } -@@ -1208,9 +1208,9 @@ static int qca83xx_config_init(struct ph +@@ -1300,9 +1300,9 @@ static int qca83xx_config_init(struct ph switch (switch_revision) { case 1: /* For 100M waveform */ @@ -81,7 +81,7 @@ Signed-off-by: David S. Miller break; case 2: -@@ -1218,8 +1218,8 @@ static int qca83xx_config_init(struct ph +@@ -1310,8 +1310,8 @@ static int qca83xx_config_init(struct ph fallthrough; case 4: phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); @@ -92,7 +92,7 @@ Signed-off-by: David S. Miller at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); break; } -@@ -1230,7 +1230,7 @@ static int qca83xx_config_init(struct ph +@@ -1322,7 +1322,7 @@ static int qca83xx_config_init(struct ph */ if (phydev->drv->phy_id == QCA8327_A_PHY_ID || phydev->drv->phy_id == QCA8327_B_PHY_ID) @@ -101,7 +101,7 @@ Signed-off-by: David S. Miller QCA8327_DEBUG_MANU_CTRL_EN, 0); /* Following original QCA sourcecode set port to prefer master */ -@@ -1248,12 +1248,12 @@ static void qca83xx_link_change_notify(s +@@ -1340,12 +1340,12 @@ static void qca83xx_link_change_notify(s /* Set DAC Amplitude adjustment to +6% for 100m on link running */ if (phydev->state == PHY_RUNNING) { if (phydev->speed == SPEED_100) @@ -116,7 +116,7 @@ Signed-off-by: David S. Miller QCA8327_DEBUG_MANU_CTRL_EN, 0); } } -@@ -1300,7 +1300,7 @@ static int qca83xx_suspend(struct phy_de +@@ -1392,7 +1392,7 @@ static int qca83xx_suspend(struct phy_de phy_modify(phydev, MII_BMCR, mask, 0); } diff --git a/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch b/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch index 6e118f5a14..70f227fb69 100644 --- a/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch +++ b/target/linux/generic/backport-5.15/747-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch @@ -42,7 +42,7 @@ Signed-off-by: David S. Miller if (ret) return ret; } -@@ -2098,7 +2105,12 @@ static int qca8k_resume(struct device *d +@@ -2105,7 +2112,12 @@ static int qca8k_resume(struct device *d static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, qca8k_suspend, qca8k_resume); @@ -56,7 +56,7 @@ Signed-off-by: David S. Miller .id = QCA8K_ID_QCA8327, }; -@@ -2107,7 +2119,8 @@ static const struct qca8k_match_data qca +@@ -2114,7 +2126,8 @@ static const struct qca8k_match_data qca }; static const struct of_device_id qca8k_of_match[] = { diff --git a/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch b/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch index 430329e23b..df9518d86c 100644 --- a/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch +++ b/target/linux/generic/backport-5.15/751-v5.16-net-dsa-qca8k-fix-internal-delay-applied-to-the-wrong-PAD.patch @@ -18,11 +18,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index a429c9750add1b..d7bcecbc1c5300 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1433,6 +1433,12 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, +@@ -1433,6 +1433,12 @@ qca8k_phylink_mac_config(struct dsa_swit qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val); @@ -35,7 +33,7 @@ index a429c9750add1b..d7bcecbc1c5300 100644 /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and * falling edge is set writing in the PORT0 PAD reg */ -@@ -1455,12 +1461,6 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, +@@ -1455,12 +1461,6 @@ qca8k_phylink_mac_config(struct dsa_swit QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE, val); diff --git a/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch b/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch index 721a59108b..7348d93ec4 100644 --- a/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch +++ b/target/linux/generic/backport-5.15/752-v5.16-net-dsa-qca8k-fix-MTU-calculation.patch @@ -28,8 +28,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index d7bcecbc1c5300..147ca39531a3bb 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1256,8 +1256,12 @@ qca8k_setup(struct dsa_switch *ds) diff --git a/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch b/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch index d86f6156a5..f477b1b929 100644 --- a/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch +++ b/target/linux/generic/backport-5.15/753-net-next-net-dsa-qca8k-remove-redundant-check-in-parse_port_config.patch @@ -16,11 +16,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index a429c9750add1..bfffc1fb7016d 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -983,7 +983,7 @@ qca8k_parse_port_config(struct qca8k_priv *priv) +@@ -983,7 +983,7 @@ qca8k_parse_port_config(struct qca8k_pri u32 delay; /* We have 2 CPU port. Check them */ @@ -29,6 +27,3 @@ index a429c9750add1..bfffc1fb7016d 100644 /* Skip every other port */ if (port != 0 && port != 6) continue; --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch b/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch index a37ab8b848..408a59df85 100644 --- a/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch +++ b/target/linux/generic/backport-5.15/754-net-next-net-dsa-qca8k-convert-to-GENMASK_FIELD_PREP_FIELD_GET.patch @@ -14,8 +14,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 153 ++++++++++++++++++++++++++---------------------- 2 files changed, 130 insertions(+), 121 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index bfffc1fb7016d..0eceb9cba2dc8 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -9,6 +9,7 @@ @@ -26,7 +24,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 #include #include #include -@@ -319,18 +320,18 @@ qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) +@@ -319,18 +320,18 @@ qca8k_fdb_read(struct qca8k_priv *priv, } /* vid - 83:72 */ @@ -54,7 +52,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 return 0; } -@@ -343,18 +344,18 @@ qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, +@@ -343,18 +344,18 @@ qca8k_fdb_write(struct qca8k_priv *priv, int i; /* vid - 83:72 */ @@ -82,7 +80,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 /* load the array into the ARL table */ for (i = 0; i < 3; i++) -@@ -372,7 +373,7 @@ qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port) +@@ -372,7 +373,7 @@ qca8k_fdb_access(struct qca8k_priv *priv reg |= cmd; if (port >= 0) { reg |= QCA8K_ATU_FUNC_PORT_EN; @@ -91,7 +89,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 } /* Write the function register triggering the table access */ -@@ -454,7 +455,7 @@ qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) +@@ -454,7 +455,7 @@ qca8k_vlan_access(struct qca8k_priv *pri /* Set the command and VLAN index */ reg = QCA8K_VTU_FUNC1_BUSY; reg |= cmd; @@ -100,7 +98,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 /* Write the function register triggering the table access */ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg); -@@ -500,13 +501,11 @@ qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, bool untagged) +@@ -500,13 +501,11 @@ qca8k_vlan_add(struct qca8k_priv *priv, if (ret < 0) goto out; reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN; @@ -117,7 +115,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg); if (ret) -@@ -534,15 +533,13 @@ qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid) +@@ -534,15 +533,13 @@ qca8k_vlan_del(struct qca8k_priv *priv, ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®); if (ret < 0) goto out; @@ -136,7 +134,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 if ((reg & mask) != mask) { del = false; -@@ -1014,7 +1011,7 @@ qca8k_parse_port_config(struct qca8k_priv *priv) +@@ -1014,7 +1011,7 @@ qca8k_parse_port_config(struct qca8k_pri mode == PHY_INTERFACE_MODE_RGMII_TXID) delay = 1; @@ -145,7 +143,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value"); delay = 3; } -@@ -1030,7 +1027,7 @@ qca8k_parse_port_config(struct qca8k_priv *priv) +@@ -1030,7 +1027,7 @@ qca8k_parse_port_config(struct qca8k_pri mode == PHY_INTERFACE_MODE_RGMII_RXID) delay = 2; @@ -209,7 +207,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | QCA8K_PORT_HOL_CTRL1_WRED_EN, -@@ -1265,8 +1260,8 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1269,8 +1264,8 @@ qca8k_setup(struct dsa_switch *ds) mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496); qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH, @@ -220,7 +218,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 mask); } -@@ -1912,11 +1907,11 @@ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, +@@ -1916,11 +1911,11 @@ qca8k_port_vlan_filtering(struct dsa_swi if (vlan_filtering) { ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), @@ -234,7 +232,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 QCA8K_PORT_LOOKUP_VLAN_MODE_NONE); } -@@ -1940,10 +1935,9 @@ qca8k_port_vlan_add(struct dsa_switch *ds, int port, +@@ -1944,10 +1939,9 @@ qca8k_port_vlan_add(struct dsa_switch *d } if (pvid) { @@ -247,7 +245,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 if (ret) return ret; -@@ -2037,7 +2031,7 @@ static int qca8k_read_switch_id(struct qca8k_priv *priv) +@@ -2041,7 +2035,7 @@ static int qca8k_read_switch_id(struct q if (ret < 0) return -ENODEV; @@ -256,7 +254,7 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 if (id != data->id) { dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id); return -ENODEV; -@@ -2046,7 +2040,7 @@ static int qca8k_read_switch_id(struct qca8k_priv *priv) +@@ -2050,7 +2044,7 @@ static int qca8k_read_switch_id(struct q priv->switch_id = id; /* Save revision to communicate to the internal PHY driver */ @@ -265,8 +263,6 @@ index bfffc1fb7016d..0eceb9cba2dc8 100644 return 0; } -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 128b8cf85e080..085885275398b 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -30,9 +30,9 @@ @@ -509,6 +505,3 @@ index 128b8cf85e080..085885275398b 100644 #define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2))) /* L3 registers */ --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch b/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch index e5f3edfa51..8c39b8ea29 100644 --- a/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch +++ b/target/linux/generic/backport-5.15/755-net-next-net-dsa-qca8k-remove-extra-mutex_init-in-qca8k_setup.patch @@ -12,8 +12,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 2 -- 1 file changed, 2 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 0eceb9cba2dc8..ae02043a52079 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1086,8 +1086,6 @@ qca8k_setup(struct dsa_switch *ds) @@ -25,6 +23,3 @@ index 0eceb9cba2dc8..ae02043a52079 100644 /* Start by setting up the register mapping */ priv->regmap = devm_regmap_init(ds->dev, NULL, priv, &qca8k_regmap_config); --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch b/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch index f67abf901b..f873b70d0f 100644 --- a/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch +++ b/target/linux/generic/backport-5.15/756-net-next-net-dsa-qca8k-move-regmap-init-in-probe-and-set-it.patch @@ -14,8 +14,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index ae02043a52079..f63a432916360 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -1086,12 +1086,6 @@ qca8k_setup(struct dsa_switch *ds) @@ -31,7 +29,7 @@ index ae02043a52079..f63a432916360 100644 ret = qca8k_setup_mdio_bus(priv); if (ret) return ret; -@@ -2073,6 +2067,14 @@ qca8k_sw_probe(struct mdio_device *mdiodev) +@@ -2077,6 +2071,14 @@ qca8k_sw_probe(struct mdio_device *mdiod gpiod_set_value_cansleep(priv->reset_gpio, 0); } @@ -46,6 +44,3 @@ index ae02043a52079..f63a432916360 100644 /* Check the detected switch id */ ret = qca8k_read_switch_id(priv); if (ret) --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch b/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch index e0a9c809d8..4ca9c8ba41 100644 --- a/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch +++ b/target/linux/generic/backport-5.15/757-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch @@ -23,8 +23,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 107 +++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 60 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index f63a432916360..d64a9af186beb 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -10,6 +10,7 @@ @@ -35,7 +33,7 @@ index f63a432916360..d64a9af186beb 100644 #include #include #include -@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 page) +@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 static int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) { @@ -118,7 +116,7 @@ index f63a432916360..d64a9af186beb 100644 static const struct regmap_range qca8k_readable_ranges[] = { regmap_reg_range(0x0000, 0x00e4), /* Global control */ regmap_reg_range(0x0100, 0x0168), /* EEE control */ -@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap_config = { +@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap .max_register = 0x16ac, /* end MIB - Port6 range */ .reg_read = qca8k_regmap_read, .reg_write = qca8k_regmap_write, @@ -168,7 +166,7 @@ index f63a432916360..d64a9af186beb 100644 if (ret) goto exit; -@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) +@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv mask |= QCA8K_PORT_STATUS_LINK_AUTO; if (enable) @@ -180,7 +178,7 @@ index f63a432916360..d64a9af186beb 100644 } static u32 -@@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv) +@@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv * * a dt-overlay and driver reload changed the configuration */ @@ -223,7 +221,7 @@ index f63a432916360..d64a9af186beb 100644 if (ret) return ret; -@@ -1741,9 +1728,9 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) +@@ -1745,9 +1732,9 @@ qca8k_port_bridge_join(struct dsa_switch /* Add this port to the portvlan mask of the other ports * in the bridge */ @@ -236,7 +234,7 @@ index f63a432916360..d64a9af186beb 100644 if (ret) return ret; if (i != port) -@@ -1773,9 +1760,9 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) +@@ -1777,9 +1764,9 @@ qca8k_port_bridge_leave(struct dsa_switc /* Remove this port to the portvlan mask of the other ports * in the bridge */ @@ -249,6 +247,3 @@ index f63a432916360..d64a9af186beb 100644 } /* Set the cpu port to be the only one in the portvlan mask of --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch b/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch index e889a7f5b2..1465d1f35d 100644 --- a/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch +++ b/target/linux/generic/backport-5.15/758-net-next-net-dsa-qca8k-add-additional-MIB-counter-and-.patch @@ -17,11 +17,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 4 ++++ 2 files changed, 24 insertions(+), 3 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index d64a9af186beb..bedaaa6b9a1df 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -70,6 +70,8 @@ static const struct qca8k_mib_desc ar8327_mib[] = { +@@ -70,6 +70,8 @@ static const struct qca8k_mib_desc ar832 MIB_DESC(1, 0x9c, "TxExcDefer"), MIB_DESC(1, 0xa0, "TxDefer"), MIB_DESC(1, 0xa4, "TxLateCol"), @@ -30,7 +28,7 @@ index d64a9af186beb..bedaaa6b9a1df 100644 }; /* The 32bit switch registers are accessed indirectly. To achieve this we need -@@ -1601,12 +1603,16 @@ qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, +@@ -1605,12 +1607,16 @@ qca8k_phylink_mac_link_up(struct dsa_swi static void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) { @@ -48,7 +46,7 @@ index d64a9af186beb..bedaaa6b9a1df 100644 strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name, ETH_GSTRING_LEN); } -@@ -1616,12 +1622,15 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, +@@ -1620,12 +1626,15 @@ qca8k_get_ethtool_stats(struct dsa_switc uint64_t *data) { struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; @@ -65,7 +63,7 @@ index d64a9af186beb..bedaaa6b9a1df 100644 mib = &ar8327_mib[i]; reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset; -@@ -1644,10 +1653,15 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, +@@ -1648,10 +1657,15 @@ qca8k_get_ethtool_stats(struct dsa_switc static int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset) { @@ -82,7 +80,7 @@ index d64a9af186beb..bedaaa6b9a1df 100644 } static int -@@ -2150,14 +2164,17 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, +@@ -2154,14 +2168,17 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, static const struct qca8k_match_data qca8327 = { .id = QCA8K_ID_QCA8327, .reduced_package = true, @@ -100,8 +98,6 @@ index d64a9af186beb..bedaaa6b9a1df 100644 }; static const struct of_device_id qca8k_of_match[] = { -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 085885275398b..91c94dfc9789d 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -21,6 +21,9 @@ @@ -122,6 +118,3 @@ index 085885275398b..91c94dfc9789d 100644 }; enum { --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch b/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch index 877223b5d2..973446ec57 100644 --- a/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch +++ b/target/linux/generic/backport-5.15/759-net-next-net-dsa-qca8k-add-support-for-port-fast-aging.patch @@ -14,11 +14,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 1 + 2 files changed, 12 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index bedaaa6b9a1df..d988df913ae02 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1786,6 +1786,16 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) +@@ -1790,6 +1790,16 @@ qca8k_port_bridge_leave(struct dsa_switc QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); } @@ -35,7 +33,7 @@ index bedaaa6b9a1df..d988df913ae02 100644 static int qca8k_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) -@@ -1994,6 +2004,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { +@@ -1998,6 +2008,7 @@ static const struct dsa_switch_ops qca8k .port_stp_state_set = qca8k_port_stp_state_set, .port_bridge_join = qca8k_port_bridge_join, .port_bridge_leave = qca8k_port_bridge_leave, @@ -43,8 +41,6 @@ index bedaaa6b9a1df..d988df913ae02 100644 .port_fdb_add = qca8k_port_fdb_add, .port_fdb_del = qca8k_port_fdb_del, .port_fdb_dump = qca8k_port_fdb_dump, -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 91c94dfc9789d..a533b8cf143be 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -262,6 +262,7 @@ enum qca8k_fdb_cmd { @@ -55,6 +51,3 @@ index 91c94dfc9789d..a533b8cf143be 100644 QCA8K_FDB_NEXT = 6, QCA8K_FDB_SEARCH = 7, }; --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch b/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch index b851c9598b..29530065a1 100644 --- a/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch +++ b/target/linux/generic/backport-5.15/760-net-next-net-dsa-qca8k-add-set_ageing_time-support.patch @@ -16,11 +16,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 3 +++ 2 files changed, 28 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index d988df913ae02..45e769b9166b8 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1257,6 +1257,10 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1261,6 +1261,10 @@ qca8k_setup(struct dsa_switch *ds) /* We don't have interrupts for link changes, so we need to poll */ ds->pcs_poll = true; @@ -31,11 +29,10 @@ index d988df913ae02..45e769b9166b8 100644 return 0; } -@@ -1796,6 +1800,26 @@ qca8k_port_fast_age(struct dsa_switch *ds, int port) - mutex_unlock(&priv->reg_mutex); +@@ -1801,6 +1805,26 @@ qca8k_port_fast_age(struct dsa_switch *d } -+static int + static int +qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) +{ + struct qca8k_priv *priv = ds->priv; @@ -55,10 +52,11 @@ index d988df913ae02..45e769b9166b8 100644 + QCA8K_ATU_AGE_TIME(val)); +} + - static int ++static int qca8k_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) -@@ -1995,6 +2019,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + { +@@ -1999,6 +2023,7 @@ static const struct dsa_switch_ops qca8k .get_strings = qca8k_get_strings, .get_ethtool_stats = qca8k_get_ethtool_stats, .get_sset_count = qca8k_get_sset_count, @@ -66,8 +64,6 @@ index d988df913ae02..45e769b9166b8 100644 .get_mac_eee = qca8k_get_mac_eee, .set_mac_eee = qca8k_set_mac_eee, .port_enable = qca8k_port_enable, -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index a533b8cf143be..40ec8012622f7 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -175,6 +175,9 @@ @@ -80,6 +76,3 @@ index a533b8cf143be..40ec8012622f7 100644 #define QCA8K_REG_GLOBAL_FW_CTRL0 0x620 #define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10) #define QCA8K_REG_GLOBAL_FW_CTRL1 0x624 --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch b/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch index a71d7480da..fa022d7ae6 100644 --- a/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch +++ b/target/linux/generic/backport-5.15/761-net-next-net-dsa-qca8k-add-support-for-mdb_add-del.patch @@ -18,15 +18,12 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 45e769b9166b8..67742fbd80409 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -435,6 +435,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv) - mutex_unlock(&priv->reg_mutex); +@@ -436,6 +436,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv) } -+static int + static int +qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask, + const u8 *mac, u16 vid) +{ @@ -101,14 +98,14 @@ index 45e769b9166b8..67742fbd80409 100644 + return ret; +} + - static int ++static int qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid) { -@@ -1925,6 +2000,28 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port, - return 0; + u32 reg; +@@ -1930,6 +2005,28 @@ qca8k_port_fdb_dump(struct dsa_switch *d } -+static int + static int +qca8k_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) +{ @@ -130,10 +127,11 @@ index 45e769b9166b8..67742fbd80409 100644 + return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid); +} + - static int ++static int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, struct netlink_ext_ack *extack) -@@ -2033,6 +2130,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + { +@@ -2037,6 +2134,8 @@ static const struct dsa_switch_ops qca8k .port_fdb_add = qca8k_port_fdb_add, .port_fdb_del = qca8k_port_fdb_del, .port_fdb_dump = qca8k_port_fdb_dump, @@ -142,6 +140,3 @@ index 45e769b9166b8..67742fbd80409 100644 .port_vlan_filtering = qca8k_port_vlan_filtering, .port_vlan_add = qca8k_port_vlan_add, .port_vlan_del = qca8k_port_vlan_del, --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch b/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch index 4ebdfda651..69e9b381c2 100644 --- a/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch +++ b/target/linux/generic/backport-5.15/762-net-next-net-dsa-qca8k-add-support-for-mirror-mode.patch @@ -15,15 +15,12 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 4 +++ 2 files changed, 99 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 67742fbd80409..bd9d756f40011 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -2022,6 +2022,99 @@ qca8k_port_mdb_del(struct dsa_switch *ds, int port, - return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid); +@@ -2027,6 +2027,99 @@ qca8k_port_mdb_del(struct dsa_switch *ds } -+static int + static int +qca8k_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) @@ -116,10 +113,11 @@ index 67742fbd80409..bd9d756f40011 100644 + dev_err(priv->dev, "Failed to del mirror port from %d", port); +} + - static int ++static int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, struct netlink_ext_ack *extack) -@@ -2132,6 +2225,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { + { +@@ -2136,6 +2229,8 @@ static const struct dsa_switch_ops qca8k .port_fdb_dump = qca8k_port_fdb_dump, .port_mdb_add = qca8k_port_mdb_add, .port_mdb_del = qca8k_port_mdb_del, @@ -128,8 +126,6 @@ index 67742fbd80409..bd9d756f40011 100644 .port_vlan_filtering = qca8k_port_vlan_filtering, .port_vlan_add = qca8k_port_vlan_add, .port_vlan_del = qca8k_port_vlan_del, -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 40ec8012622f7..7c87a968c0104 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -180,6 +180,7 @@ @@ -157,6 +153,3 @@ index 40ec8012622f7..7c87a968c0104 100644 bool legacy_phy_port_mapping; struct qca8k_ports_config ports_config; struct regmap *regmap; --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch b/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch index 9967211828..bfc77db184 100644 --- a/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch +++ b/target/linux/generic/backport-5.15/763-net-next-net-dsa-qca8k-add-LAG-support.patch @@ -23,11 +23,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 33 +++++++++ 2 files changed, 210 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index bd9d756f40011..6516df08a5d5f 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -1336,6 +1336,9 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1340,6 +1340,9 @@ qca8k_setup(struct dsa_switch *ds) ds->ageing_time_min = 7000; ds->ageing_time_max = 458745000; @@ -37,7 +35,7 @@ index bd9d756f40011..6516df08a5d5f 100644 return 0; } -@@ -2203,6 +2206,178 @@ qca8k_get_tag_protocol(struct dsa_switch *ds, int port, +@@ -2207,6 +2210,178 @@ qca8k_get_tag_protocol(struct dsa_switch return DSA_TAG_PROTO_QCA; } @@ -216,7 +214,7 @@ index bd9d756f40011..6516df08a5d5f 100644 static const struct dsa_switch_ops qca8k_switch_ops = { .get_tag_protocol = qca8k_get_tag_protocol, .setup = qca8k_setup, -@@ -2236,6 +2411,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = { +@@ -2240,6 +2415,8 @@ static const struct dsa_switch_ops qca8k .phylink_mac_link_down = qca8k_phylink_mac_link_down, .phylink_mac_link_up = qca8k_phylink_mac_link_up, .get_phy_flags = qca8k_get_phy_flags, @@ -225,8 +223,6 @@ index bd9d756f40011..6516df08a5d5f 100644 }; static int qca8k_read_switch_id(struct qca8k_priv *priv) -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 7c87a968c0104..ab4a417b25a9c 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -15,6 +15,8 @@ @@ -290,6 +286,3 @@ index 7c87a968c0104..ab4a417b25a9c 100644 bool legacy_phy_port_mapping; struct qca8k_ports_config ports_config; struct regmap *regmap; --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch b/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch index 2bde440093..8c0a990b0d 100644 --- a/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch +++ b/target/linux/generic/backport-5.15/764-net-next-net-dsa-qca8k-fix-warning-in-LAG-feature.patch @@ -17,11 +17,9 @@ Signed-off-by: Jakub Kicinski drivers/net/dsa/qca8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 6516df08a5d5f..d04b25eca2503 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -2228,7 +2228,7 @@ qca8k_lag_can_offload(struct dsa_switch *ds, +@@ -2232,7 +2232,7 @@ qca8k_lag_can_offload(struct dsa_switch if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) return false; @@ -30,7 +28,7 @@ index 6516df08a5d5f..d04b25eca2503 100644 info->hash_type != NETDEV_LAG_HASH_L23) return false; -@@ -2242,8 +2242,8 @@ qca8k_lag_setup_hash(struct dsa_switch *ds, +@@ -2246,8 +2246,8 @@ qca8k_lag_setup_hash(struct dsa_switch * { struct qca8k_priv *priv = ds->priv; bool unique_lag = true; @@ -40,6 +38,3 @@ index 6516df08a5d5f..d04b25eca2503 100644 id = dsa_lag_id(ds->dst, lag); --- -cgit 1.2.3-1.el7 - diff --git a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch index 25c6ac2e8f..1786bf0345 100644 --- a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch +++ b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch @@ -20,11 +20,9 @@ Signed-off-by: David S. Miller net/dsa/slave.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index 88f7b8686dac..88bcdba92fa7 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2011,13 +2011,6 @@ int dsa_slave_create(struct dsa_port *port) +@@ -1986,13 +1986,6 @@ int dsa_slave_create(struct dsa_port *po port->slave = slave_dev; dsa_slave_setup_tagger(slave_dev); @@ -38,20 +36,17 @@ index 88f7b8686dac..88bcdba92fa7 100644 netif_carrier_off(slave_dev); ret = dsa_slave_phy_setup(slave_dev); -@@ -2028,6 +2021,13 @@ int dsa_slave_create(struct dsa_port *port) - goto out_gcells; +@@ -2004,6 +1997,13 @@ int dsa_slave_create(struct dsa_port *po } -+ rtnl_lock(); + rtnl_lock(); + ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN); + rtnl_unlock(); + if (ret && ret != -EOPNOTSUPP) + dev_warn(ds->dev, "nonfatal error %d setting MTU to %d on port %d\n", + ret, ETH_DATA_LEN, port->index); + - rtnl_lock(); ++ rtnl_lock(); ret = register_netdevice(slave_dev); --- -2.34.1 - + if (ret) { diff --git a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch index c383bd93fb..c2493a08fd 100644 --- a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch +++ b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch @@ -14,11 +14,9 @@ Signed-off-by: David S. Miller net/dsa/slave.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index 88bcdba92fa7..22241afcac81 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2022,14 +2022,12 @@ int dsa_slave_create(struct dsa_port *port) +@@ -1997,14 +1997,12 @@ int dsa_slave_create(struct dsa_port *po } rtnl_lock(); @@ -34,6 +32,3 @@ index 88bcdba92fa7..22241afcac81 100644 ret = register_netdevice(slave_dev); if (ret) { netdev_err(master, "error %d registering interface %s\n", --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch b/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch index c81bedaaf8..d1126de5dd 100644 --- a/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch +++ b/target/linux/generic/backport-5.15/765-3-net-next-net-dsa-stop-updating-master-MTU-from-master.c.patch @@ -35,11 +35,9 @@ Signed-off-by: David S. Miller net/dsa/master.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) -diff --git a/net/dsa/master.c b/net/dsa/master.c -index e8e19857621b..f4efb244f91d 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c -@@ -330,28 +330,13 @@ static const struct attribute_group dsa_group = { +@@ -330,28 +330,13 @@ static const struct attribute_group dsa_ .attrs = dsa_slave_attrs, }; @@ -69,7 +67,7 @@ index e8e19857621b..f4efb244f91d 100644 /* The DSA master must use SET_NETDEV_DEV for this to work. */ consumer_link = device_link_add(ds->dev, dev->dev.parent, -@@ -361,13 +346,6 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) +@@ -361,13 +346,6 @@ int dsa_master_setup(struct net_device * "Failed to create a device link to DSA switch %s\n", dev_name(ds->dev)); @@ -83,7 +81,7 @@ index e8e19857621b..f4efb244f91d 100644 /* If we use a tagging format that doesn't have an ethertype * field, make sure that all packets from this point on get * sent to the tag format's receive function. -@@ -405,7 +383,6 @@ void dsa_master_teardown(struct net_device *dev) +@@ -405,7 +383,6 @@ void dsa_master_teardown(struct net_devi sysfs_remove_group(&dev->dev.kobj, &dsa_group); dsa_netdev_ops_set(dev, NULL); dsa_master_ethtool_teardown(dev); @@ -91,6 +89,3 @@ index e8e19857621b..f4efb244f91d 100644 dsa_master_set_promiscuity(dev, -1); dev->dsa_ptr = NULL; --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch b/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch index cbbe52b0cc..67d434006b 100644 --- a/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch +++ b/target/linux/generic/backport-5.15/765-4-net-next-net-dsa-hold-rtnl_mutex-when-calling-dsa_master_-set.patch @@ -28,11 +28,9 @@ Signed-off-by: David S. Miller net/dsa/master.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index a0d84f9f864f..52fb1958b535 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c -@@ -1038,6 +1038,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) +@@ -1034,6 +1034,8 @@ static int dsa_tree_setup_master(struct struct dsa_port *dp; int err; @@ -41,7 +39,7 @@ index a0d84f9f864f..52fb1958b535 100644 list_for_each_entry(dp, &dst->ports, list) { if (dsa_port_is_cpu(dp)) { err = dsa_master_setup(dp->master, dp); -@@ -1046,6 +1048,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) +@@ -1042,6 +1044,8 @@ static int dsa_tree_setup_master(struct } } @@ -50,7 +48,7 @@ index a0d84f9f864f..52fb1958b535 100644 return 0; } -@@ -1053,9 +1057,13 @@ static void dsa_tree_teardown_master(struct dsa_switch_tree *dst) +@@ -1049,9 +1053,13 @@ static void dsa_tree_teardown_master(str { struct dsa_port *dp; @@ -64,11 +62,9 @@ index a0d84f9f864f..52fb1958b535 100644 } static int dsa_tree_setup_lags(struct dsa_switch_tree *dst) -diff --git a/net/dsa/master.c b/net/dsa/master.c -index f4efb244f91d..2199104ca7df 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c -@@ -267,9 +267,9 @@ static void dsa_master_set_promiscuity(struct net_device *dev, int inc) +@@ -267,9 +267,9 @@ static void dsa_master_set_promiscuity(s if (!ops->promisc_on_master) return; @@ -80,6 +76,3 @@ index f4efb244f91d..2199104ca7df 100644 } static ssize_t tagging_show(struct device *d, struct device_attribute *attr, --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch b/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch index fbd63a5743..e6472c61da 100644 --- a/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch +++ b/target/linux/generic/backport-5.15/765-5-net-next-net-dsa-first-set-up-shared-ports-then-non-shared-po.patch @@ -25,11 +25,9 @@ Signed-off-by: David S. Miller net/dsa/dsa2.c | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index 52fb1958b535..ea0f02a24b8b 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c -@@ -1003,23 +1003,28 @@ static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst) +@@ -999,23 +999,28 @@ static void dsa_tree_teardown_switches(s dsa_switch_teardown(dp->ds); } @@ -68,7 +66,7 @@ index 52fb1958b535..ea0f02a24b8b 100644 } } -@@ -1028,7 +1033,21 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) +@@ -1024,7 +1029,21 @@ static int dsa_tree_setup_switches(struc teardown: dsa_tree_teardown_ports(dst); @@ -91,7 +89,7 @@ index 52fb1958b535..ea0f02a24b8b 100644 return err; } -@@ -1115,10 +1134,14 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) +@@ -1111,10 +1130,14 @@ static int dsa_tree_setup(struct dsa_swi if (err) goto teardown_cpu_ports; @@ -107,7 +105,7 @@ index 52fb1958b535..ea0f02a24b8b 100644 err = dsa_tree_setup_lags(dst); if (err) goto teardown_master; -@@ -1131,8 +1154,9 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) +@@ -1127,8 +1150,9 @@ static int dsa_tree_setup(struct dsa_swi teardown_master: dsa_tree_teardown_master(dst); @@ -118,6 +116,3 @@ index 52fb1958b535..ea0f02a24b8b 100644 dsa_tree_teardown_switches(dst); teardown_cpu_ports: dsa_tree_teardown_cpu_ports(dst); --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch b/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch index 3f5b71945b..93cad0c98a 100644 --- a/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch +++ b/target/linux/generic/backport-5.15/765-6-net-next-net-dsa-setup-master-before-ports.patch @@ -41,11 +41,9 @@ Signed-off-by: David S. Miller net/dsa/dsa2.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index ea0f02a24b8b..3d21521453fe 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c -@@ -561,6 +561,7 @@ static void dsa_port_teardown(struct dsa_port *dp) +@@ -545,6 +545,7 @@ static void dsa_port_teardown(struct dsa struct devlink_port *dlp = &dp->devlink_port; struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a, *tmp; @@ -53,7 +51,7 @@ index ea0f02a24b8b..3d21521453fe 100644 if (!dp->setup) return; -@@ -582,9 +583,11 @@ static void dsa_port_teardown(struct dsa_port *dp) +@@ -566,9 +567,11 @@ static void dsa_port_teardown(struct dsa dsa_port_link_unregister_of(dp); break; case DSA_PORT_TYPE_USER: @@ -67,7 +65,7 @@ index ea0f02a24b8b..3d21521453fe 100644 } break; } -@@ -1134,17 +1137,17 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) +@@ -1130,17 +1133,17 @@ static int dsa_tree_setup(struct dsa_swi if (err) goto teardown_cpu_ports; @@ -89,7 +87,7 @@ index ea0f02a24b8b..3d21521453fe 100644 dst->setup = true; -@@ -1152,10 +1155,10 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) +@@ -1148,10 +1151,10 @@ static int dsa_tree_setup(struct dsa_swi return 0; @@ -102,7 +100,7 @@ index ea0f02a24b8b..3d21521453fe 100644 teardown_switches: dsa_tree_teardown_switches(dst); teardown_cpu_ports: -@@ -1173,10 +1176,10 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) +@@ -1169,10 +1172,10 @@ static void dsa_tree_teardown(struct dsa dsa_tree_teardown_lags(dst); @@ -115,6 +113,3 @@ index ea0f02a24b8b..3d21521453fe 100644 dsa_tree_teardown_switches(dst); dsa_tree_teardown_cpu_ports(dst); --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch index 2cfb488aee..d73b745586 100644 --- a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch +++ b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch @@ -42,11 +42,9 @@ Signed-off-by: David S. Miller net/dsa/switch.c | 15 +++++++++++++++ 5 files changed, 123 insertions(+) -diff --git a/include/net/dsa.h b/include/net/dsa.h -index 57b3e4e7413b..43c4153ef53a 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h -@@ -278,6 +278,10 @@ struct dsa_port { +@@ -291,6 +291,10 @@ struct dsa_port { struct list_head mdbs; bool setup; @@ -57,7 +55,7 @@ index 57b3e4e7413b..43c4153ef53a 100644 }; /* TODO: ideally DSA ports would have a single dp->link_dp member, -@@ -478,6 +482,12 @@ static inline bool dsa_port_is_unused(struct dsa_port *dp) +@@ -456,6 +460,12 @@ static inline bool dsa_port_is_unused(st return dp->type == DSA_PORT_TYPE_UNUSED; } @@ -70,7 +68,7 @@ index 57b3e4e7413b..43c4153ef53a 100644 static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p) { return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED; -@@ -1036,6 +1046,13 @@ struct dsa_switch_ops { +@@ -916,6 +926,13 @@ struct dsa_switch_ops { int (*tag_8021q_vlan_add)(struct dsa_switch *ds, int port, u16 vid, u16 flags); int (*tag_8021q_vlan_del)(struct dsa_switch *ds, int port, u16 vid); @@ -84,11 +82,9 @@ index 57b3e4e7413b..43c4153ef53a 100644 }; #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \ -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index 3d21521453fe..ff998c0ede02 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c -@@ -1279,6 +1279,52 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, +@@ -1275,6 +1275,52 @@ out_unlock: return err; } @@ -141,19 +137,17 @@ index 3d21521453fe..ff998c0ede02 100644 static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index) { struct dsa_switch_tree *dst = ds->dst; -diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h -index 760306f0012f..2bbfa9efe9f8 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h -@@ -40,6 +40,7 @@ enum { - DSA_NOTIFIER_TAG_PROTO_DISCONNECT, +@@ -45,6 +45,7 @@ enum { + DSA_NOTIFIER_MRP_DEL_RING_ROLE, DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, + DSA_NOTIFIER_MASTER_STATE_CHANGE, }; /* DSA_NOTIFIER_AGEING_TIME */ -@@ -109,6 +110,12 @@ struct dsa_notifier_tag_8021q_vlan_info { +@@ -127,6 +128,12 @@ struct dsa_notifier_tag_8021q_vlan_info u16 vid; }; @@ -166,7 +160,7 @@ index 760306f0012f..2bbfa9efe9f8 100644 struct dsa_switchdev_event_work { struct dsa_switch *ds; int port; -@@ -482,6 +489,12 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, +@@ -548,6 +555,12 @@ int dsa_tree_change_tag_proto(struct dsa struct net_device *master, const struct dsa_device_ops *tag_ops, const struct dsa_device_ops *old_tag_ops); @@ -179,11 +173,9 @@ index 760306f0012f..2bbfa9efe9f8 100644 int dsa_bridge_num_get(const struct net_device *bridge_dev, int max); void dsa_bridge_num_put(const struct net_device *bridge_dev, int bridge_num); -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index 22241afcac81..2b5b0f294233 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2346,6 +2346,36 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, +@@ -2320,6 +2320,36 @@ static int dsa_slave_netdevice_event(str err = dsa_port_lag_change(dp, info->lower_state_info); return notifier_from_errno(err); } @@ -220,20 +212,18 @@ index 22241afcac81..2b5b0f294233 100644 case NETDEV_GOING_DOWN: { struct dsa_port *dp, *cpu_dp; struct dsa_switch_tree *dst; -@@ -2357,6 +2387,8 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, +@@ -2331,6 +2361,8 @@ static int dsa_slave_netdevice_event(str cpu_dp = dev->dsa_ptr; dst = cpu_dp->ds->dst; + dsa_tree_master_admin_state_change(dst, dev, false); + list_for_each_entry(dp, &dst->ports, list) { - if (!dsa_port_is_user(dp)) + if (!dsa_is_user_port(dp->ds, dp->index)) continue; -diff --git a/net/dsa/switch.c b/net/dsa/switch.c -index 517cc83d13cc..4866b58649e4 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -697,6 +697,18 @@ dsa_switch_disconnect_tag_proto(struct dsa_switch *ds, +@@ -722,6 +722,18 @@ dsa_switch_mrp_del_ring_role(struct dsa_ return 0; } @@ -252,7 +242,7 @@ index 517cc83d13cc..4866b58649e4 100644 static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { -@@ -770,6 +782,9 @@ static int dsa_switch_event(struct notifier_block *nb, +@@ -813,6 +825,9 @@ static int dsa_switch_event(struct notif case DSA_NOTIFIER_TAG_8021Q_VLAN_DEL: err = dsa_switch_tag_8021q_vlan_del(ds, info); break; @@ -262,6 +252,3 @@ index 517cc83d13cc..4866b58649e4 100644 default: err = -EOPNOTSUPP; break; --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch b/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch index d9356c3b7d..6478d580c0 100644 --- a/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch +++ b/target/linux/generic/backport-5.15/766-02-net-dsa-replay-master-state-events-in-dsa_tree_-setu.patch @@ -34,8 +34,6 @@ Signed-off-by: David S. Miller net/dsa/dsa2.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) -diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c -index ff998c0ede02..909b045c9b11 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -15,6 +15,7 @@ @@ -46,7 +44,7 @@ index ff998c0ede02..909b045c9b11 100644 #include "dsa_priv.h" -@@ -1064,9 +1065,18 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) +@@ -1060,9 +1061,18 @@ static int dsa_tree_setup_master(struct list_for_each_entry(dp, &dst->ports, list) { if (dsa_port_is_cpu(dp)) { @@ -66,7 +64,7 @@ index ff998c0ede02..909b045c9b11 100644 } } -@@ -1081,9 +1091,19 @@ static void dsa_tree_teardown_master(struct dsa_switch_tree *dst) +@@ -1077,9 +1087,19 @@ static void dsa_tree_teardown_master(str rtnl_lock(); @@ -89,6 +87,3 @@ index ff998c0ede02..909b045c9b11 100644 rtnl_unlock(); } --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch b/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch index 84fd918cb3..82c94b385b 100644 --- a/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch +++ b/target/linux/generic/backport-5.15/766-03-net-dsa-tag_qca-convert-to-FIELD-macro.patch @@ -13,8 +13,6 @@ Signed-off-by: David S. Miller net/dsa/tag_qca.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) -diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c -index 1ea9401b8ace..55fa6b96b4eb 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c @@ -4,29 +4,24 @@ @@ -39,15 +37,14 @@ index 1ea9401b8ace..55fa6b96b4eb 100644 +#define QCA_HDR_RECV_TYPE GENMASK(10, 6) #define QCA_HDR_RECV_FRAME_IS_TAGGED BIT(3) -#define QCA_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) -- ++#define QCA_HDR_RECV_SOURCE_PORT GENMASK(2, 0) + -#define QCA_HDR_XMIT_VERSION_MASK GENMASK(15, 14) -#define QCA_HDR_XMIT_VERSION_S 14 -#define QCA_HDR_XMIT_PRIORITY_MASK GENMASK(13, 11) -#define QCA_HDR_XMIT_PRIORITY_S 11 -#define QCA_HDR_XMIT_CONTROL_MASK GENMASK(10, 8) -#define QCA_HDR_XMIT_CONTROL_S 8 -+#define QCA_HDR_RECV_SOURCE_PORT GENMASK(2, 0) -+ +#define QCA_HDR_XMIT_VERSION GENMASK(15, 14) +#define QCA_HDR_XMIT_PRIORITY GENMASK(13, 11) +#define QCA_HDR_XMIT_CONTROL GENMASK(10, 8) @@ -57,7 +54,7 @@ index 1ea9401b8ace..55fa6b96b4eb 100644 static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) { -@@ -40,8 +35,9 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) +@@ -40,8 +35,9 @@ static struct sk_buff *qca_tag_xmit(stru phdr = dsa_etype_header_pos_tx(skb); /* Set the version field, and set destination port information */ @@ -69,7 +66,7 @@ index 1ea9401b8ace..55fa6b96b4eb 100644 *phdr = htons(hdr); -@@ -62,7 +58,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -62,7 +58,7 @@ static struct sk_buff *qca_tag_rcv(struc hdr = ntohs(*phdr); /* Make sure the version is correct */ @@ -78,7 +75,7 @@ index 1ea9401b8ace..55fa6b96b4eb 100644 if (unlikely(ver != QCA_HDR_VERSION)) return NULL; -@@ -71,7 +67,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -71,7 +67,7 @@ static struct sk_buff *qca_tag_rcv(struc dsa_strip_etype_header(skb, QCA_HDR_LEN); /* Get source port information */ @@ -87,6 +84,3 @@ index 1ea9401b8ace..55fa6b96b4eb 100644 skb->dev = dsa_master_find_slave(dev, 0, port); if (!skb->dev) --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch b/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch index 21221dbbef..c1e74ceeeb 100644 --- a/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch +++ b/target/linux/generic/backport-5.15/766-04-net-dsa-tag_qca-move-define-to-include-linux-dsa.patch @@ -17,9 +17,6 @@ Signed-off-by: David S. Miller 2 files changed, 22 insertions(+), 15 deletions(-) create mode 100644 include/linux/dsa/tag_qca.h -diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h -new file mode 100644 -index 000000000000..c02d2d39ff4a --- /dev/null +++ b/include/linux/dsa/tag_qca.h @@ -0,0 +1,21 @@ @@ -44,8 +41,6 @@ index 000000000000..c02d2d39ff4a +#define QCA_HDR_XMIT_DP_BIT GENMASK(6, 0) + +#endif /* __TAG_QCA_H */ -diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c -index 55fa6b96b4eb..34e565e00ece 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c @@ -5,24 +5,10 @@ @@ -74,6 +69,3 @@ index 55fa6b96b4eb..34e565e00ece 100644 static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) { struct dsa_port *dp = dsa_slave_to_port(dev); --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch b/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch index d0dd4513f3..9394a0dabb 100644 --- a/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch +++ b/target/linux/generic/backport-5.15/766-05-net-dsa-tag_qca-enable-promisc_on_master-flag.patch @@ -15,11 +15,9 @@ Signed-off-by: David S. Miller net/dsa/tag_qca.c | 1 + 1 file changed, 1 insertion(+) -diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c -index 34e565e00ece..f8df49d5956f 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c -@@ -68,6 +68,7 @@ static const struct dsa_device_ops qca_netdev_ops = { +@@ -68,6 +68,7 @@ static const struct dsa_device_ops qca_n .xmit = qca_tag_xmit, .rcv = qca_tag_rcv, .needed_headroom = QCA_HDR_LEN, @@ -27,6 +25,3 @@ index 34e565e00ece..f8df49d5956f 100644 }; MODULE_LICENSE("GPL"); --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch b/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch index 6981e7b187..459454e03b 100644 --- a/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch +++ b/target/linux/generic/backport-5.15/766-06-net-dsa-tag_qca-add-define-for-handling-mgmt-Etherne.patch @@ -19,8 +19,6 @@ Signed-off-by: David S. Miller net/dsa/tag_qca.c | 15 ++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) -diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h -index c02d2d39ff4a..f366422ab7a0 100644 --- a/include/linux/dsa/tag_qca.h +++ b/include/linux/dsa/tag_qca.h @@ -12,10 +12,54 @@ @@ -78,11 +76,9 @@ index c02d2d39ff4a..f366422ab7a0 100644 +} __packed; + #endif /* __TAG_QCA_H */ -diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c -index f8df49d5956f..f17ed5be20c2 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c -@@ -32,10 +32,12 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) +@@ -32,10 +32,12 @@ static struct sk_buff *qca_tag_xmit(stru static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) { @@ -98,7 +94,7 @@ index f8df49d5956f..f17ed5be20c2 100644 if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) return NULL; -@@ -48,6 +50,13 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -48,6 +50,13 @@ static struct sk_buff *qca_tag_rcv(struc if (unlikely(ver != QCA_HDR_VERSION)) return NULL; @@ -112,6 +108,3 @@ index f8df49d5956f..f17ed5be20c2 100644 /* Remove QCA tag and recalculate checksum */ skb_pull_rcsum(skb, QCA_HDR_LEN); dsa_strip_etype_header(skb, QCA_HDR_LEN); --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch b/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch index 497518097e..7e5dc65730 100644 --- a/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch +++ b/target/linux/generic/backport-5.15/766-07-net-dsa-tag_qca-add-define-for-handling-MIB-packet.patch @@ -13,8 +13,6 @@ Signed-off-by: David S. Miller net/dsa/tag_qca.c | 4 ++++ 2 files changed, 14 insertions(+) -diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h -index f366422ab7a0..1fff57f2937b 100644 --- a/include/linux/dsa/tag_qca.h +++ b/include/linux/dsa/tag_qca.h @@ -62,4 +62,14 @@ struct qca_mgmt_ethhdr { @@ -32,11 +30,9 @@ index f366422ab7a0..1fff57f2937b 100644 +} __packed; + #endif /* __TAG_QCA_H */ -diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c -index f17ed5be20c2..be792cf687d9 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c -@@ -57,6 +57,10 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -57,6 +57,10 @@ static struct sk_buff *qca_tag_rcv(struc if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) return NULL; @@ -47,6 +43,3 @@ index f17ed5be20c2..be792cf687d9 100644 /* Remove QCA tag and recalculate checksum */ skb_pull_rcsum(skb, QCA_HDR_LEN); dsa_strip_etype_header(skb, QCA_HDR_LEN); --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch b/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch index 4375cd08b8..ad25da30e6 100644 --- a/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch +++ b/target/linux/generic/backport-5.15/766-08-net-dsa-tag_qca-add-support-for-handling-mgmt-and-MI.patch @@ -17,8 +17,6 @@ Signed-off-by: David S. Miller net/dsa/tag_qca.c | 39 ++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) -diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h -index 1fff57f2937b..4359fb0221cf 100644 --- a/include/linux/dsa/tag_qca.h +++ b/include/linux/dsa/tag_qca.h @@ -72,4 +72,11 @@ struct mib_ethhdr { @@ -33,8 +31,6 @@ index 1fff57f2937b..4359fb0221cf 100644 +}; + #endif /* __TAG_QCA_H */ -diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c -index be792cf687d9..57d2e00f1e5d 100644 --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c @@ -5,6 +5,7 @@ @@ -45,7 +41,7 @@ index be792cf687d9..57d2e00f1e5d 100644 #include #include "dsa_priv.h" -@@ -32,6 +33,9 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) +@@ -32,6 +33,9 @@ static struct sk_buff *qca_tag_xmit(stru static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) { @@ -55,7 +51,7 @@ index be792cf687d9..57d2e00f1e5d 100644 u8 ver, pk_type; __be16 *phdr; int port; -@@ -39,6 +43,8 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -39,6 +43,8 @@ static struct sk_buff *qca_tag_rcv(struc BUILD_BUG_ON(sizeof(struct qca_mgmt_ethhdr) != QCA_HDR_MGMT_HEADER_LEN + QCA_HDR_LEN); @@ -64,7 +60,7 @@ index be792cf687d9..57d2e00f1e5d 100644 if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) return NULL; -@@ -53,13 +59,19 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -53,13 +59,19 @@ static struct sk_buff *qca_tag_rcv(struc /* Get pk type */ pk_type = FIELD_GET(QCA_HDR_RECV_TYPE, hdr); @@ -87,7 +83,7 @@ index be792cf687d9..57d2e00f1e5d 100644 /* Remove QCA tag and recalculate checksum */ skb_pull_rcsum(skb, QCA_HDR_LEN); -@@ -75,9 +87,30 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev) +@@ -75,9 +87,30 @@ static struct sk_buff *qca_tag_rcv(struc return skb; } @@ -118,6 +114,3 @@ index be792cf687d9..57d2e00f1e5d 100644 .xmit = qca_tag_xmit, .rcv = qca_tag_rcv, .needed_headroom = QCA_HDR_LEN, --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch b/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch index d2799f9e7a..ff8fdca512 100644 --- a/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch +++ b/target/linux/generic/backport-5.15/766-09-net-dsa-qca8k-add-tracking-state-of-master-port.patch @@ -24,11 +24,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 1 + 2 files changed, 16 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 039694518788..ec062b9a918d 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -2383,6 +2383,20 @@ qca8k_port_lag_leave(struct dsa_switch *ds, int port, +@@ -2382,6 +2382,20 @@ qca8k_port_lag_leave(struct dsa_switch * return qca8k_lag_refresh_portmap(ds, port, lag, true); } @@ -49,7 +47,7 @@ index 039694518788..ec062b9a918d 100644 static const struct dsa_switch_ops qca8k_switch_ops = { .get_tag_protocol = qca8k_get_tag_protocol, .setup = qca8k_setup, -@@ -2418,6 +2432,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { +@@ -2417,6 +2431,7 @@ static const struct dsa_switch_ops qca8k .get_phy_flags = qca8k_get_phy_flags, .port_lag_join = qca8k_port_lag_join, .port_lag_leave = qca8k_port_lag_leave, @@ -57,8 +55,6 @@ index 039694518788..ec062b9a918d 100644 }; static int qca8k_read_switch_id(struct qca8k_priv *priv) -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index ab4a417b25a9..b81aad98a116 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -353,6 +353,7 @@ struct qca8k_priv { @@ -69,6 +65,3 @@ index ab4a417b25a9..b81aad98a116 100644 }; struct qca8k_mib_desc { --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch b/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch index dedffbc074..43656ad79d 100644 --- a/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch +++ b/target/linux/generic/backport-5.15/766-10-net-dsa-qca8k-add-support-for-mgmt-read-write-in-Eth.patch @@ -41,8 +41,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 13 +++ 2 files changed, 238 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index ec062b9a918d..e3a215f04559 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -20,6 +20,7 @@ @@ -53,7 +51,7 @@ index ec062b9a918d..e3a215f04559 100644 #include "qca8k.h" -@@ -170,6 +171,194 @@ qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) +@@ -170,6 +171,194 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r return regmap_update_bits(priv->regmap, reg, mask, write_val); } @@ -248,7 +246,7 @@ index ec062b9a918d..e3a215f04559 100644 static int qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) { -@@ -178,6 +367,9 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +@@ -178,6 +367,9 @@ qca8k_regmap_read(void *ctx, uint32_t re u16 r1, r2, page; int ret; @@ -258,7 +256,7 @@ index ec062b9a918d..e3a215f04559 100644 qca8k_split_addr(reg, &r1, &r2, &page); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -201,6 +393,9 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) +@@ -201,6 +393,9 @@ qca8k_regmap_write(void *ctx, uint32_t r u16 r1, r2, page; int ret; @@ -268,7 +266,7 @@ index ec062b9a918d..e3a215f04559 100644 qca8k_split_addr(reg, &r1, &r2, &page); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -225,6 +420,9 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ +@@ -225,6 +420,9 @@ qca8k_regmap_update_bits(void *ctx, uint u32 val; int ret; @@ -278,7 +276,7 @@ index ec062b9a918d..e3a215f04559 100644 qca8k_split_addr(reg, &r1, &r2, &page); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -@@ -2394,7 +2592,30 @@ qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, +@@ -2393,7 +2591,30 @@ qca8k_master_change(struct dsa_switch *d if (dp->index != 0) return; @@ -309,7 +307,7 @@ index ec062b9a918d..e3a215f04559 100644 } static const struct dsa_switch_ops qca8k_switch_ops = { -@@ -2433,6 +2654,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = { +@@ -2432,6 +2653,7 @@ static const struct dsa_switch_ops qca8k .port_lag_join = qca8k_port_lag_join, .port_lag_leave = qca8k_port_lag_leave, .master_state_change = qca8k_master_change, @@ -317,7 +315,7 @@ index ec062b9a918d..e3a215f04559 100644 }; static int qca8k_read_switch_id(struct qca8k_priv *priv) -@@ -2512,6 +2734,9 @@ qca8k_sw_probe(struct mdio_device *mdiodev) +@@ -2511,6 +2733,9 @@ qca8k_sw_probe(struct mdio_device *mdiod if (!priv->ds) return -ENOMEM; @@ -327,8 +325,6 @@ index ec062b9a918d..e3a215f04559 100644 priv->ds->dev = &mdiodev->dev; priv->ds->num_ports = QCA8K_NUM_PORTS; priv->ds->priv = priv; -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index b81aad98a116..75c28689a652 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -11,6 +11,10 @@ @@ -365,6 +361,3 @@ index b81aad98a116..75c28689a652 100644 }; struct qca8k_mib_desc { --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch b/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch index 69882e9c21..c4bc2b3646 100644 --- a/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch +++ b/target/linux/generic/backport-5.15/766-11-net-dsa-qca8k-add-support-for-mib-autocast-in-Ethern.patch @@ -24,8 +24,6 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 17 ++++++- 2 files changed, 121 insertions(+), 2 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index e3a215f04559..199cf4f761c0 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -830,7 +830,10 @@ qca8k_mib_init(struct qca8k_priv *priv) @@ -40,7 +38,7 @@ index e3a215f04559..199cf4f761c0 100644 if (ret) goto exit; -@@ -1901,6 +1904,97 @@ qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) +@@ -1901,6 +1904,97 @@ qca8k_get_strings(struct dsa_switch *ds, ETH_GSTRING_LEN); } @@ -138,7 +136,7 @@ index e3a215f04559..199cf4f761c0 100644 static void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) -@@ -1912,6 +2006,10 @@ qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, +@@ -1912,6 +2006,10 @@ qca8k_get_ethtool_stats(struct dsa_switc u32 hi = 0; int ret; @@ -149,7 +147,7 @@ index e3a215f04559..199cf4f761c0 100644 match_data = of_device_get_match_data(priv->dev); for (i = 0; i < match_data->mib_count; i++) { -@@ -2593,9 +2691,11 @@ qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, +@@ -2592,9 +2690,11 @@ qca8k_master_change(struct dsa_switch *d return; mutex_lock(&priv->mgmt_eth_data.mutex); @@ -161,7 +159,7 @@ index e3a215f04559..199cf4f761c0 100644 mutex_unlock(&priv->mgmt_eth_data.mutex); } -@@ -2609,6 +2709,7 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds, +@@ -2608,6 +2708,7 @@ static int qca8k_connect_tag_protocol(st tagger_data = ds->tagger_data; tagger_data->rw_reg_ack_handler = qca8k_rw_reg_ack_handler; @@ -169,7 +167,7 @@ index e3a215f04559..199cf4f761c0 100644 break; default: -@@ -2737,6 +2838,9 @@ qca8k_sw_probe(struct mdio_device *mdiodev) +@@ -2736,6 +2837,9 @@ qca8k_sw_probe(struct mdio_device *mdiod mutex_init(&priv->mgmt_eth_data.mutex); init_completion(&priv->mgmt_eth_data.rw_done); @@ -179,8 +177,6 @@ index e3a215f04559..199cf4f761c0 100644 priv->ds->dev = &mdiodev->dev; priv->ds->num_ports = QCA8K_NUM_PORTS; priv->ds->priv = priv; -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 75c28689a652..2d7d084db089 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -67,7 +67,7 @@ @@ -228,6 +224,3 @@ index 75c28689a652..2d7d084db089 100644 }; struct qca8k_mib_desc { --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch b/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch index 5c65626e54..f5899eb590 100644 --- a/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch +++ b/target/linux/generic/backport-5.15/766-12-net-dsa-qca8k-add-support-for-phy-read-write-with-mg.patch @@ -15,11 +15,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 1 + 2 files changed, 217 insertions(+) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 199cf4f761c0..0ce5b7ca0b7f 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -867,6 +867,199 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) +@@ -867,6 +867,199 @@ qca8k_port_set_status(struct qca8k_priv regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask); } @@ -219,7 +217,7 @@ index 199cf4f761c0..0ce5b7ca0b7f 100644 static u32 qca8k_port_to_phy(int port) { -@@ -989,6 +1182,12 @@ qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 da +@@ -989,6 +1182,12 @@ qca8k_internal_mdio_write(struct mii_bus { struct qca8k_priv *priv = slave_bus->priv; struct mii_bus *bus = priv->bus; @@ -232,7 +230,7 @@ index 199cf4f761c0..0ce5b7ca0b7f 100644 return qca8k_mdio_write(bus, phy, regnum, data); } -@@ -998,6 +1197,12 @@ qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) +@@ -998,6 +1197,12 @@ qca8k_internal_mdio_read(struct mii_bus { struct qca8k_priv *priv = slave_bus->priv; struct mii_bus *bus = priv->bus; @@ -253,7 +251,7 @@ index 199cf4f761c0..0ce5b7ca0b7f 100644 /* Check if the legacy mapping should be used and the * port is not correctly mapped to the right PHY in the -@@ -1014,6 +1220,11 @@ qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) +@@ -1014,6 +1220,11 @@ qca8k_phy_write(struct dsa_switch *ds, i if (priv->legacy_phy_port_mapping) port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; @@ -265,7 +263,7 @@ index 199cf4f761c0..0ce5b7ca0b7f 100644 return qca8k_mdio_write(priv->bus, port, regnum, data); } -@@ -1030,6 +1241,11 @@ qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) +@@ -1030,6 +1241,11 @@ qca8k_phy_read(struct dsa_switch *ds, in if (priv->legacy_phy_port_mapping) port = qca8k_port_to_phy(port) % PHY_MAX_ADDR; @@ -277,8 +275,6 @@ index 199cf4f761c0..0ce5b7ca0b7f 100644 ret = qca8k_mdio_read(priv->bus, port, regnum); if (ret < 0) -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 2d7d084db089..c6f6abd2108e 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -14,6 +14,7 @@ @@ -289,6 +285,3 @@ index 2d7d084db089..c6f6abd2108e 100644 #define QCA8K_ETHERNET_TIMEOUT 100 #define QCA8K_NUM_PORTS 7 --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch b/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch index d69b959e56..dc8160966c 100644 --- a/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch +++ b/target/linux/generic/backport-5.15/766-13-net-dsa-qca8k-move-page-cache-to-driver-priv.patch @@ -14,11 +14,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 9 +++++++++ 2 files changed, 29 insertions(+), 22 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 0ce5b7ca0b7f..86d3742b1038 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -75,12 +75,6 @@ static const struct qca8k_mib_desc ar8327_mib[] = { +@@ -75,12 +75,6 @@ static const struct qca8k_mib_desc ar832 MIB_DESC(1, 0xac, "TXUnicast"), }; @@ -31,7 +29,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 static void qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) { -@@ -134,11 +128,13 @@ qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) +@@ -134,11 +128,13 @@ qca8k_mii_write32(struct mii_bus *bus, i } static int @@ -47,7 +45,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 return 0; ret = bus->write(bus, 0x18, 0, page); -@@ -148,7 +144,7 @@ qca8k_set_page(struct mii_bus *bus, u16 page) +@@ -148,7 +144,7 @@ qca8k_set_page(struct mii_bus *bus, u16 return ret; } @@ -56,7 +54,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 usleep_range(1000, 2000); return 0; } -@@ -374,7 +370,7 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +@@ -374,7 +370,7 @@ qca8k_regmap_read(void *ctx, uint32_t re mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); @@ -65,7 +63,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 if (ret < 0) goto exit; -@@ -400,7 +396,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) +@@ -400,7 +396,7 @@ qca8k_regmap_write(void *ctx, uint32_t r mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); @@ -74,7 +72,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 if (ret < 0) goto exit; -@@ -427,7 +423,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ +@@ -427,7 +423,7 @@ qca8k_regmap_update_bits(void *ctx, uint mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); @@ -83,7 +81,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 if (ret < 0) goto exit; -@@ -1098,8 +1094,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask) +@@ -1098,8 +1094,9 @@ qca8k_mdio_busy_wait(struct mii_bus *bus } static int @@ -94,7 +92,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 u16 r1, r2, page; u32 val; int ret; -@@ -1116,7 +1113,7 @@ qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) +@@ -1116,7 +1113,7 @@ qca8k_mdio_write(struct mii_bus *bus, in mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); @@ -103,7 +101,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 if (ret) goto exit; -@@ -1135,8 +1132,9 @@ qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data) +@@ -1135,8 +1132,9 @@ exit: } static int @@ -114,7 +112,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 u16 r1, r2, page; u32 val; int ret; -@@ -1152,7 +1150,7 @@ qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum) +@@ -1152,7 +1150,7 @@ qca8k_mdio_read(struct mii_bus *bus, int mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); @@ -131,7 +129,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 int ret; /* Use mdio Ethernet when available, fallback to legacy one on error */ -@@ -1189,14 +1186,13 @@ qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 da +@@ -1189,14 +1186,13 @@ qca8k_internal_mdio_write(struct mii_bus if (!ret) return 0; @@ -147,7 +145,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 int ret; /* Use mdio Ethernet when available, fallback to legacy one on error */ -@@ -1204,7 +1200,7 @@ qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum) +@@ -1204,7 +1200,7 @@ qca8k_internal_mdio_read(struct mii_bus if (ret >= 0) return ret; @@ -156,7 +154,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 } static int -@@ -1225,7 +1221,7 @@ qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data) +@@ -1225,7 +1221,7 @@ qca8k_phy_write(struct dsa_switch *ds, i if (!ret) return ret; @@ -165,7 +163,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 } static int -@@ -1246,7 +1242,7 @@ qca8k_phy_read(struct dsa_switch *ds, int port, int regnum) +@@ -1246,7 +1242,7 @@ qca8k_phy_read(struct dsa_switch *ds, in if (ret >= 0) return ret; @@ -174,7 +172,7 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 if (ret < 0) return 0xffff; -@@ -3042,6 +3038,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev) +@@ -3041,6 +3037,8 @@ qca8k_sw_probe(struct mdio_device *mdiod return PTR_ERR(priv->regmap); } @@ -183,8 +181,6 @@ index 0ce5b7ca0b7f..86d3742b1038 100644 /* Check the detected switch id */ ret = qca8k_read_switch_id(priv); if (ret) -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index c6f6abd2108e..57368acae41b 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -363,6 +363,14 @@ struct qca8k_ports_config { @@ -210,6 +206,3 @@ index c6f6abd2108e..57368acae41b 100644 }; struct qca8k_mib_desc { --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch b/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch index 72de25c9d8..2d483730c9 100644 --- a/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch +++ b/target/linux/generic/backport-5.15/766-14-net-dsa-qca8k-cache-lo-and-hi-for-mdio-write.patch @@ -15,15 +15,12 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.h | 5 ++++ 2 files changed, 54 insertions(+), 12 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 86d3742b1038..0cce3a6030af 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -88,6 +88,44 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) - *page = regaddr & 0x3ff; +@@ -89,6 +89,44 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u } -+static int + static int +qca8k_set_lo(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 lo) +{ + u16 *cached_lo = &priv->mdio_cache.lo; @@ -61,10 +58,11 @@ index 86d3742b1038..0cce3a6030af 100644 + return 0; +} + - static int ++static int qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) { -@@ -111,7 +149,7 @@ qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + int ret; +@@ -111,7 +149,7 @@ qca8k_mii_read32(struct mii_bus *bus, in } static void @@ -73,7 +71,7 @@ index 86d3742b1038..0cce3a6030af 100644 { u16 lo, hi; int ret; -@@ -119,12 +157,9 @@ qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) +@@ -119,12 +157,9 @@ qca8k_mii_write32(struct mii_bus *bus, i lo = val & 0xffff; hi = (u16)(val >> 16); @@ -88,7 +86,7 @@ index 86d3742b1038..0cce3a6030af 100644 } static int -@@ -400,7 +435,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) +@@ -400,7 +435,7 @@ qca8k_regmap_write(void *ctx, uint32_t r if (ret < 0) goto exit; @@ -97,7 +95,7 @@ index 86d3742b1038..0cce3a6030af 100644 exit: mutex_unlock(&bus->mdio_lock); -@@ -433,7 +468,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ +@@ -433,7 +468,7 @@ qca8k_regmap_update_bits(void *ctx, uint val &= ~mask; val |= write_val; @@ -106,7 +104,7 @@ index 86d3742b1038..0cce3a6030af 100644 exit: mutex_unlock(&bus->mdio_lock); -@@ -1117,14 +1152,14 @@ qca8k_mdio_write(struct qca8k_priv *priv, int phy, int regnum, u16 data) +@@ -1117,14 +1152,14 @@ qca8k_mdio_write(struct qca8k_priv *priv if (ret) goto exit; @@ -123,7 +121,7 @@ index 86d3742b1038..0cce3a6030af 100644 mutex_unlock(&bus->mdio_lock); -@@ -1154,7 +1189,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) +@@ -1154,7 +1189,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, if (ret) goto exit; @@ -132,7 +130,7 @@ index 86d3742b1038..0cce3a6030af 100644 ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, QCA8K_MDIO_MASTER_BUSY); -@@ -1165,7 +1200,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) +@@ -1165,7 +1200,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, exit: /* even if the busy_wait timeouts try to clear the MASTER_EN */ @@ -141,7 +139,7 @@ index 86d3742b1038..0cce3a6030af 100644 mutex_unlock(&bus->mdio_lock); -@@ -3039,6 +3074,8 @@ qca8k_sw_probe(struct mdio_device *mdiodev) +@@ -3038,6 +3073,8 @@ qca8k_sw_probe(struct mdio_device *mdiod } priv->mdio_cache.page = 0xffff; @@ -150,8 +148,6 @@ index 86d3742b1038..0cce3a6030af 100644 /* Check the detected switch id */ ret = qca8k_read_switch_id(priv); -diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h -index 57368acae41b..c3d3c2269b1d 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -369,6 +369,11 @@ struct qca8k_mdio_cache { @@ -166,6 +162,3 @@ index 57368acae41b..c3d3c2269b1d 100644 }; struct qca8k_priv { --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch b/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch index 4b735224b6..5acd13dbad 100644 --- a/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch +++ b/target/linux/generic/backport-5.15/766-15-net-dsa-qca8k-add-support-for-larger-read-write-size.patch @@ -28,11 +28,9 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 61 +++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 20 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index 0cce3a6030af..a1b76dcd2eb6 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -222,7 +222,9 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) +@@ -222,7 +222,9 @@ static void qca8k_rw_reg_ack_handler(str if (cmd == MDIO_READ) { mgmt_eth_data->data[0] = mgmt_ethhdr->mdio_data; @@ -43,7 +41,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 if (len > QCA_HDR_MGMT_DATA1_LEN) memcpy(mgmt_eth_data->data + 1, skb->data, QCA_HDR_MGMT_DATA2_LEN); -@@ -232,16 +234,30 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) +@@ -232,16 +234,30 @@ static void qca8k_rw_reg_ack_handler(str } static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 *val, @@ -75,7 +73,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 skb_reset_mac_header(skb); skb_set_network_header(skb, skb->len); -@@ -254,7 +270,7 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 * +@@ -254,7 +270,7 @@ static struct sk_buff *qca8k_alloc_mdio_ hdr |= FIELD_PREP(QCA_HDR_XMIT_CONTROL, QCA_HDR_XMIT_TYPE_RW_REG); mgmt_ethhdr->command = FIELD_PREP(QCA_HDR_MGMT_ADDR, reg); @@ -84,7 +82,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CMD, cmd); mgmt_ethhdr->command |= FIELD_PREP(QCA_HDR_MGMT_CHECK_CODE, QCA_HDR_MGMT_CHECK_CODE_VAL); -@@ -264,7 +280,9 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 * +@@ -264,7 +280,9 @@ static struct sk_buff *qca8k_alloc_mdio_ mgmt_ethhdr->hdr = htons(hdr); @@ -95,7 +93,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 return skb; } -@@ -277,7 +295,7 @@ static void qca8k_mdio_header_fill_seq_num(struct sk_buff *skb, u32 seq_num) +@@ -277,7 +295,7 @@ static void qca8k_mdio_header_fill_seq_n mgmt_ethhdr->seq = FIELD_PREP(QCA_HDR_MGMT_SEQ_NUM, seq_num); } @@ -104,7 +102,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 { struct qca8k_mgmt_eth_data *mgmt_eth_data = &priv->mgmt_eth_data; struct sk_buff *skb; -@@ -285,7 +303,7 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) +@@ -285,7 +303,7 @@ static int qca8k_read_eth(struct qca8k_p int ret; skb = qca8k_alloc_mdio_header(MDIO_READ, reg, NULL, @@ -113,7 +111,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 if (!skb) return -ENOMEM; -@@ -313,6 +331,9 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) +@@ -313,6 +331,9 @@ static int qca8k_read_eth(struct qca8k_p msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT)); *val = mgmt_eth_data->data[0]; @@ -123,7 +121,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 ack = mgmt_eth_data->ack; mutex_unlock(&mgmt_eth_data->mutex); -@@ -326,15 +347,15 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val) +@@ -326,15 +347,15 @@ static int qca8k_read_eth(struct qca8k_p return 0; } @@ -142,7 +140,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 if (!skb) return -ENOMEM; -@@ -380,14 +401,14 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri +@@ -380,14 +401,14 @@ qca8k_regmap_update_bits_eth(struct qca8 u32 val = 0; int ret; @@ -159,7 +157,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 } static int -@@ -398,7 +419,7 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +@@ -398,7 +419,7 @@ qca8k_regmap_read(void *ctx, uint32_t re u16 r1, r2, page; int ret; @@ -168,7 +166,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 return 0; qca8k_split_addr(reg, &r1, &r2, &page); -@@ -424,7 +445,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) +@@ -424,7 +445,7 @@ qca8k_regmap_write(void *ctx, uint32_t r u16 r1, r2, page; int ret; @@ -177,7 +175,7 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 return 0; qca8k_split_addr(reg, &r1, &r2, &page); -@@ -959,21 +980,21 @@ qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy, +@@ -959,21 +980,21 @@ qca8k_phy_eth_command(struct qca8k_priv } /* Prealloc all the needed skb before the lock */ @@ -206,6 +204,3 @@ index 0cce3a6030af..a1b76dcd2eb6 100644 ret = -ENOMEM; goto err_read_skb; } --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch b/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch index ebd08845bc..f26c6b91ac 100644 --- a/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch +++ b/target/linux/generic/backport-5.15/766-16-net-dsa-qca8k-introduce-qca8k_bulk_read-write-functi.patch @@ -15,15 +15,12 @@ Signed-off-by: David S. Miller drivers/net/dsa/qca8k.c | 55 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 12 deletions(-) -diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c -index a1b76dcd2eb6..52ec2800dd89 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c -@@ -411,6 +411,43 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri - return qca8k_write_eth(priv, reg, &val, sizeof(val)); +@@ -412,6 +412,43 @@ qca8k_regmap_update_bits_eth(struct qca8 } -+static int + static int +qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len) +{ + int i, count = len / sizeof(u32), ret; @@ -60,10 +57,11 @@ index a1b76dcd2eb6..52ec2800dd89 100644 + return 0; +} + - static int ++static int qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) { -@@ -546,17 +583,13 @@ qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + struct qca8k_priv *priv = (struct qca8k_priv *)ctx; +@@ -546,17 +583,13 @@ qca8k_busy_wait(struct qca8k_priv *priv, static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) { @@ -86,7 +84,7 @@ index a1b76dcd2eb6..52ec2800dd89 100644 /* vid - 83:72 */ fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]); -@@ -580,7 +613,6 @@ qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, +@@ -580,7 +613,6 @@ qca8k_fdb_write(struct qca8k_priv *priv, u8 aging) { u32 reg[3] = { 0 }; @@ -94,7 +92,7 @@ index a1b76dcd2eb6..52ec2800dd89 100644 /* vid - 83:72 */ reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); -@@ -597,8 +629,7 @@ qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac, +@@ -597,8 +629,7 @@ qca8k_fdb_write(struct qca8k_priv *priv, reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); /* load the array into the ARL table */ @@ -104,6 +102,3 @@ index a1b76dcd2eb6..52ec2800dd89 100644 } static int --- -2.34.1 - diff --git a/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch b/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch index c36b9e6a90..44093eab95 100644 --- a/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch +++ b/target/linux/generic/backport-5.15/773-v5.18-1-net-dsa-Move-VLAN-filtering-syncing-out-of-dsa_switc.patch @@ -15,11 +15,9 @@ Signed-off-by: David S. Miller net/dsa/switch.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) -diff --git a/net/dsa/switch.c b/net/dsa/switch.c -index e3c7d2627a619..9f9b70d6070a3 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -113,25 +113,14 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds, +@@ -113,25 +113,14 @@ static int dsa_switch_bridge_join(struct return dsa_tag_8021q_bridge_join(ds, info); } @@ -47,7 +45,7 @@ index e3c7d2627a619..9f9b70d6070a3 100644 if (ds->needs_standalone_vlan_filtering && !br_vlan_enabled(info->br)) { change_vlan_filtering = true; vlan_filtering = true; -@@ -172,6 +161,29 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, +@@ -172,6 +161,29 @@ static int dsa_switch_bridge_leave(struc return err; } @@ -77,5 +75,3 @@ index e3c7d2627a619..9f9b70d6070a3 100644 return dsa_tag_8021q_bridge_leave(ds, info); } --- -cgit diff --git a/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch b/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch index 079ac7eb63..cdddbcf14e 100644 --- a/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch +++ b/target/linux/generic/backport-5.15/773-v5.18-2-net-dsa-Avoid-cross-chip-syncing-of-VLAN-filtering.patch @@ -33,13 +33,11 @@ Signed-off-by: David S. Miller net/dsa/switch.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) -diff --git a/net/dsa/switch.c b/net/dsa/switch.c -index 9f9b70d6070a3..517cc83d13cc8 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c -@@ -180,9 +180,11 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, +@@ -180,9 +180,11 @@ static int dsa_switch_bridge_leave(struc info->sw_index, info->port, - info->bridge); + info->br); - err = dsa_switch_sync_vlan_filtering(ds, info); - if (err) @@ -52,5 +50,3 @@ index 9f9b70d6070a3..517cc83d13cc8 100644 return dsa_tag_8021q_bridge_leave(ds, info); } --- -cgit diff --git a/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch b/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch index ce38719009..b84eb442ad 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0003-PCI-aardvark-Add-support-for-DEVCAP2-DEVCTL2-LNKCAP2.patch @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -881,8 +881,13 @@ advk_pci_bridge_emul_pcie_conf_read(stru +@@ -874,8 +874,13 @@ advk_pci_bridge_emul_pcie_conf_read(stru case PCI_EXP_DEVCAP: case PCI_EXP_DEVCTL: @@ -35,7 +35,7 @@ Signed-off-by: Lorenzo Pieralisi default: return PCI_BRIDGE_EMUL_NOT_HANDLED; } -@@ -896,10 +901,6 @@ advk_pci_bridge_emul_pcie_conf_write(str +@@ -889,10 +894,6 @@ advk_pci_bridge_emul_pcie_conf_write(str struct advk_pcie *pcie = bridge->data; switch (reg) { @@ -46,7 +46,7 @@ Signed-off-by: Lorenzo Pieralisi case PCI_EXP_LNKCTL: advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); if (new & PCI_EXP_LNKCTL_RL) -@@ -921,6 +922,12 @@ advk_pci_bridge_emul_pcie_conf_write(str +@@ -914,6 +915,12 @@ advk_pci_bridge_emul_pcie_conf_write(str advk_writel(pcie, new, PCIE_ISR0_REG); break; diff --git a/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch b/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch index 66c7e60202..a22aacf170 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0004-PCI-aardvark-Clear-all-MSIs-at-setup.patch @@ -23,7 +23,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -114,6 +114,7 @@ +@@ -115,6 +115,7 @@ #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) @@ -31,7 +31,7 @@ Signed-off-by: Lorenzo Pieralisi #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) #define PCIE_MSI_DATA_MASK GENMASK(15, 0) -@@ -577,6 +578,7 @@ static void advk_pcie_setup_hw(struct ad +@@ -570,6 +571,7 @@ static void advk_pcie_setup_hw(struct ad advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); /* Clear all interrupts */ @@ -39,7 +39,7 @@ Signed-off-by: Lorenzo Pieralisi advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG); advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); -@@ -589,7 +591,7 @@ static void advk_pcie_setup_hw(struct ad +@@ -582,7 +584,7 @@ static void advk_pcie_setup_hw(struct ad advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); /* Unmask all MSIs */ @@ -48,7 +48,7 @@ Signed-off-by: Lorenzo Pieralisi /* Enable summary interrupt for GIC SPI source */ reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); -@@ -1399,7 +1401,7 @@ static void advk_pcie_handle_msi(struct +@@ -1392,7 +1394,7 @@ static void advk_pcie_handle_msi(struct msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG); msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch b/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch index 8870e47b40..16e09bc1f9 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0005-PCI-aardvark-Comment-actions-in-driver-remove-method.patch @@ -18,7 +18,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1698,11 +1698,13 @@ static int advk_pcie_remove(struct platf +@@ -1688,11 +1688,13 @@ static int advk_pcie_remove(struct platf struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); int i; diff --git a/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch b/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch index f1c3f3bb13..6c48b3bc2b 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0006-PCI-aardvark-Disable-bus-mastering-when-unbinding-dr.patch @@ -19,7 +19,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1696,6 +1696,7 @@ static int advk_pcie_remove(struct platf +@@ -1686,6 +1686,7 @@ static int advk_pcie_remove(struct platf { struct advk_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -27,7 +27,7 @@ Signed-off-by: Lorenzo Pieralisi int i; /* Remove PCI bus with all devices */ -@@ -1704,6 +1705,11 @@ static int advk_pcie_remove(struct platf +@@ -1694,6 +1695,11 @@ static int advk_pcie_remove(struct platf pci_remove_root_bus(bridge->bus); pci_unlock_rescan_remove(); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch b/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch index 7add045cab..3cc5ba667c 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch @@ -18,7 +18,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1710,6 +1710,27 @@ static int advk_pcie_remove(struct platf +@@ -1700,6 +1700,27 @@ static int advk_pcie_remove(struct platf val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch b/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch index f86d2bd61f..fdd049b978 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1735,6 +1735,9 @@ static int advk_pcie_remove(struct platf +@@ -1725,6 +1725,9 @@ static int advk_pcie_remove(struct platf advk_pcie_remove_msi_irq_domain(pcie); advk_pcie_remove_irq_domain(pcie); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch b/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch index 1e9e74136c..2e95d26ce9 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch @@ -20,7 +20,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1738,6 +1738,10 @@ static int advk_pcie_remove(struct platf +@@ -1728,6 +1728,10 @@ static int advk_pcie_remove(struct platf /* Free config space for emulated root bridge */ pci_bridge_emul_cleanup(&pcie->bridge); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch b/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch index 3b531deae0..826f10a35f 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch @@ -20,7 +20,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1742,6 +1742,11 @@ static int advk_pcie_remove(struct platf +@@ -1732,6 +1732,11 @@ static int advk_pcie_remove(struct platf if (pcie->reset_gpio) gpiod_set_value_cansleep(pcie->reset_gpio, 1); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch b/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch index 6caa6eb362..c01377a887 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch @@ -18,7 +18,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1751,6 +1751,9 @@ static int advk_pcie_remove(struct platf +@@ -1741,6 +1741,9 @@ static int advk_pcie_remove(struct platf for (i = 0; i < OB_WIN_COUNT; i++) advk_pcie_disable_ob_win(pcie, i); diff --git a/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch b/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch index 971562a8f7..e9d692b651 100644 --- a/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch +++ b/target/linux/generic/backport-5.15/860-v5.17-MIPS-ath79-drop-_machine_restart-again.patch @@ -39,7 +39,7 @@ Signed-off-by: Thomas Bogendoerfer static void ath79_halt(void) { while (1) -@@ -233,7 +224,6 @@ void __init plat_mem_setup(void) +@@ -234,7 +225,6 @@ void __init plat_mem_setup(void) detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); From 49cb5e501a8d6eb8ff5cad63f13282de7b84e7ef Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 21 Mar 2022 15:21:45 +0100 Subject: [PATCH 21/26] generic: 5.15: refresh hack patch Use 'make target/linux/refresh' to refresh hack patches. Signed-off-by: Ansuel Smith --- .../generic/hack-5.15/204-module_strip.patch | 38 +++++++------- .../generic/hack-5.15/205-kconfig-exit.patch | 2 +- .../hack-5.15/212-tools_portability.patch | 2 +- .../hack-5.15/214-spidev_h_portability.patch | 2 +- .../hack-5.15/220-arm-gc_sections.patch | 12 ++--- .../hack-5.15/221-module_exports.patch | 8 +-- .../hack-5.15/230-openwrt_lzma_options.patch | 2 +- .../hack-5.15/250-netfilter_depends.patch | 4 +- .../linux/generic/hack-5.15/251-kconfig.patch | 2 +- .../generic/hack-5.15/253-ksmbd-config.patch | 2 +- .../hack-5.15/259-regmap_dynamic.patch | 5 +- .../260-crypto_test_dependencies.patch | 2 +- .../generic/hack-5.15/280-rfkill-stubs.patch | 4 +- ...cache-use-more-efficient-cache-blast.patch | 2 +- .../301-mips_image_cmdline_hack.patch | 2 +- ...rans-call-add-disks-after-mtd-device.patch | 2 +- .../410-block-fit-partition-parser.patch | 22 ++++---- .../420-mtd-set-rootfs-to-be-root-dev.patch | 2 +- .../hack-5.15/430-mtk-bmt-support.patch | 6 +-- .../hack-5.15/600-bridge_offload.patch | 50 +++++++++---------- ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 14 +++--- .../hack-5.15/651-wireless_mesh_header.patch | 2 +- .../hack-5.15/660-fq_codel_defaults.patch | 2 +- .../710-net-dsa-mv88e6xxx-default-VID-1.patch | 4 +- ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 6 +-- .../hack-5.15/720-net-phy-add-aqr-phys.patch | 12 ++--- .../721-net-add-packet-mangeling.patch | 34 ++++++------- ...hy-aquantia-enable-AQR112-and-AQR412.patch | 8 +-- ...aquantia-fix-system-side-protocol-mi.patch | 2 +- ...y-aquantia-Add-AQR113-driver-support.patch | 4 +- ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 4 +- ...-r8152-add-LED-configuration-from-OF.patch | 10 ++-- .../hack-5.15/773-bgmac-add-srab-switch.patch | 6 +-- .../780-usb-net-MeigLink_modem_support.patch | 2 +- .../800-GPIO-add-named-gpio-exports.patch | 12 ++--- .../hack-5.15/901-debloat_sock_diag.patch | 10 ++-- .../generic/hack-5.15/902-debloat_proc.patch | 28 +++++------ .../hack-5.15/904-debloat_dma_buf.patch | 10 ++-- .../hack-5.15/920-device_tree_cmdline.patch | 2 +- 39 files changed, 171 insertions(+), 172 deletions(-) diff --git a/target/linux/generic/hack-5.15/204-module_strip.patch b/target/linux/generic/hack-5.15/204-module_strip.patch index 645074821f..0968d6a135 100644 --- a/target/linux/generic/hack-5.15/204-module_strip.patch +++ b/target/linux/generic/hack-5.15/204-module_strip.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/module.h +++ b/include/linux/module.h -@@ -161,6 +161,7 @@ extern void cleanup_module(void); +@@ -164,6 +164,7 @@ extern void cleanup_module(void); /* Generic info of form tag = "info" */ #define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info) @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau /* For userspace: you can also call me... */ #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) -@@ -230,12 +231,12 @@ extern void cleanup_module(void); +@@ -233,12 +234,12 @@ extern void cleanup_module(void); * Author(s), use "Name " or just "Name", for multiple * authors use multiple MODULE_AUTHOR() statements/lines. */ @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau /* Creates an alias so file2alias.c can find device table. */ #define MODULE_DEVICE_TABLE(type, name) \ extern typeof(name) __mod_##type##__##name##_device_table \ -@@ -262,7 +263,9 @@ extern typeof(name) __mod_##type##__##na +@@ -265,7 +266,9 @@ extern typeof(name) __mod_##type##__##na */ #if defined(MODULE) || !defined(CONFIG_SYSFS) @@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau #else #define MODULE_VERSION(_version) \ MODULE_INFO(version, _version); \ -@@ -285,7 +288,7 @@ extern typeof(name) __mod_##type##__##na +@@ -288,7 +291,7 @@ extern typeof(name) __mod_##type##__##na /* Optional firmware file (or files) needed by the module * format is simply firmware file name. Multiple firmware * files require multiple MODULE_FIRMWARE() specifiers */ @@ -75,9 +75,9 @@ Signed-off-by: Felix Fietkau +#endif + #define __MODULE_INFO(tag, name, info) \ - static const char __UNIQUE_ID(name)[] \ - __used __section(".modinfo") __attribute__((unused, aligned(1))) \ -@@ -31,7 +41,7 @@ static const char __UNIQUE_ID(name)[] + static const char __UNIQUE_ID(name)[] \ + __used __section(".modinfo") __aligned(1) \ +@@ -31,7 +41,7 @@ /* One for each parameter, describing how to use it. Some files do multiple of these per line, so can't just use MODULE_INFO. */ #define MODULE_PARM_DESC(_parm, desc) \ @@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau config MODULES_TREE_LOOKUP --- a/kernel/module.c +++ b/kernel/module.c -@@ -1285,6 +1285,7 @@ static struct module_attribute *modinfo_ +@@ -1218,6 +1218,7 @@ static struct module_attribute *modinfo_ static const char vermagic[] = VERMAGIC_STRING; @@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau static int try_to_force_load(struct module *mod, const char *reason) { #ifdef CONFIG_MODULE_FORCE_LOAD -@@ -1296,6 +1297,7 @@ static int try_to_force_load(struct modu +@@ -1229,6 +1230,7 @@ static int try_to_force_load(struct modu return -ENOEXEC; #endif } @@ -120,7 +120,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_MODVERSIONS -@@ -3247,9 +3249,11 @@ static int setup_load_info(struct load_i +@@ -3227,9 +3229,11 @@ static int setup_load_info(struct load_i static int check_modinfo(struct module *mod, struct load_info *info, int flags) { @@ -133,7 +133,7 @@ Signed-off-by: Felix Fietkau if (flags & MODULE_INIT_IGNORE_VERMAGIC) modmagic = NULL; -@@ -3270,6 +3274,7 @@ static int check_modinfo(struct module * +@@ -3250,6 +3254,7 @@ static int check_modinfo(struct module * mod->name); add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); } @@ -143,7 +143,7 @@ Signed-off-by: Felix Fietkau --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c -@@ -2037,7 +2037,9 @@ static void read_symbols(const char *mod +@@ -2033,7 +2033,9 @@ static void read_symbols(const char *mod symname = remove_dot(info.strtab + sym->st_name); handle_symbol(mod, &info, sym, symname); @@ -153,9 +153,9 @@ Signed-off-by: Felix Fietkau } for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { -@@ -2250,8 +2252,10 @@ static void add_header(struct buffer *b, - buf_printf(b, "\n"); +@@ -2212,8 +2214,10 @@ static void add_header(struct buffer *b, buf_printf(b, "BUILD_SALT;\n"); + buf_printf(b, "BUILD_LTO_INFO;\n"); buf_printf(b, "\n"); +#ifndef CONFIG_MODULE_STRIPPED buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); @@ -164,7 +164,7 @@ Signed-off-by: Felix Fietkau buf_printf(b, "\n"); buf_printf(b, "__visible struct module __this_module\n"); buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n"); -@@ -2268,8 +2272,10 @@ static void add_header(struct buffer *b, +@@ -2230,8 +2234,10 @@ static void add_header(struct buffer *b, static void add_intree_flag(struct buffer *b, int is_intree) { @@ -175,7 +175,7 @@ Signed-off-by: Felix Fietkau } /* Cannot check for assembler */ -@@ -2282,8 +2288,10 @@ static void add_retpoline(struct buffer +@@ -2244,8 +2250,10 @@ static void add_retpoline(struct buffer static void add_staging_flag(struct buffer *b, const char *name) { @@ -186,7 +186,7 @@ Signed-off-by: Felix Fietkau } /** -@@ -2367,11 +2375,13 @@ static void add_depends(struct buffer *b +@@ -2325,11 +2333,13 @@ static void add_depends(struct buffer *b static void add_srcversion(struct buffer *b, struct module *mod) { @@ -200,9 +200,9 @@ Signed-off-by: Felix Fietkau } static void write_buf(struct buffer *b, const char *fname) -@@ -2630,7 +2640,9 @@ int main(int argc, char **argv) +@@ -2578,7 +2588,9 @@ int main(int argc, char **argv) add_staging_flag(&buf, mod->name); - err |= add_versions(&buf, mod); + add_versions(&buf, mod); add_depends(&buf, mod); +#ifndef CONFIG_MODULE_STRIPPED add_moddevtable(&buf, mod); diff --git a/target/linux/generic/hack-5.15/205-kconfig-exit.patch b/target/linux/generic/hack-5.15/205-kconfig-exit.patch index c3fb7a1f99..e61c3ffdd9 100644 --- a/target/linux/generic/hack-5.15/205-kconfig-exit.patch +++ b/target/linux/generic/hack-5.15/205-kconfig-exit.patch @@ -1,6 +1,6 @@ --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c -@@ -215,6 +215,8 @@ static int conf_sym(struct menu *menu) +@@ -435,6 +435,8 @@ static int conf_sym(struct menu *menu) break; continue; case 0: diff --git a/target/linux/generic/hack-5.15/212-tools_portability.patch b/target/linux/generic/hack-5.15/212-tools_portability.patch index 54ac048417..b488155f94 100644 --- a/target/linux/generic/hack-5.15/212-tools_portability.patch +++ b/target/linux/generic/hack-5.15/212-tools_portability.patch @@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau +#endif --- a/tools/include/linux/types.h +++ b/tools/include/linux/types.h -@@ -7,8 +7,12 @@ +@@ -10,8 +10,12 @@ #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ #endif diff --git a/target/linux/generic/hack-5.15/214-spidev_h_portability.patch b/target/linux/generic/hack-5.15/214-spidev_h_portability.patch index 506d50ad4d..db754a2903 100644 --- a/target/linux/generic/hack-5.15/214-spidev_h_portability.patch +++ b/target/linux/generic/hack-5.15/214-spidev_h_portability.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/include/uapi/linux/spi/spidev.h +++ b/include/uapi/linux/spi/spidev.h -@@ -121,7 +121,7 @@ struct spi_ioc_transfer { +@@ -93,7 +93,7 @@ struct spi_ioc_transfer { /* not all platforms use or _IOC_TYPECHECK() ... */ #define SPI_MSGSIZE(N) \ diff --git a/target/linux/generic/hack-5.15/220-arm-gc_sections.patch b/target/linux/generic/hack-5.15/220-arm-gc_sections.patch index 331368b9fb..0aa3eb840c 100644 --- a/target/linux/generic/hack-5.15/220-arm-gc_sections.patch +++ b/target/linux/generic/hack-5.15/220-arm-gc_sections.patch @@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos --- --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -113,6 +113,7 @@ config ARM +@@ -117,6 +117,7 @@ config ARM select HAVE_UID16 select HAVE_VIRT_CPU_ACCOUNTING_GEN select IRQ_FORCED_THREADING @@ -22,14 +22,14 @@ Signed-off-by: Gabor Juhos select OF_EARLY_FLATTREE if OF --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile -@@ -98,6 +98,7 @@ $(foreach o, $(libfdt_objs) atags_to_fdt - ifdef building_out_of_srctree - $(shell rm -f $(addprefix $(obj)/, fdt_rw.c fdt_ro.c fdt_wip.c fdt.c)) +@@ -92,6 +92,7 @@ endif + ifeq ($(CONFIG_USE_OF),y) + OBJS += $(libfdt_objs) fdt_check_mem_start.o endif +KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL)) - targets := vmlinux vmlinux.lds piggy_data piggy.o \ - lib1funcs.o ashldi3.o bswapsdi2.o \ + # -fstack-protector-strong triggers protection checks in this code, + # but it is being used too early to link to meaningful stack_chk logic. --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -75,7 +75,7 @@ SECTIONS diff --git a/target/linux/generic/hack-5.15/221-module_exports.patch b/target/linux/generic/hack-5.15/221-module_exports.patch index cd38125f28..65cee1a541 100644 --- a/target/linux/generic/hack-5.15/221-module_exports.patch +++ b/target/linux/generic/hack-5.15/221-module_exports.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau /* Align . to a 8 byte boundary equals to maximum function alignment. */ #define ALIGN_FUNCTION() . = ALIGN(8) -@@ -473,14 +483,14 @@ +@@ -484,14 +494,14 @@ /* Kernel symbol table: Normal symbols */ \ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ __start___ksymtab = .; \ @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau __stop___ksymtab_gpl = .; \ } \ \ -@@ -542,7 +552,7 @@ +@@ -511,7 +521,7 @@ \ /* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau } \ \ /* __*init sections */ \ -@@ -1019,6 +1029,8 @@ +@@ -1018,6 +1028,8 @@ #define COMMON_DISCARDS \ SANITIZER_DISCARDS \ @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau "__kstrtabns_" #sym ": \n" \ --- a/scripts/Makefile.build +++ b/scripts/Makefile.build -@@ -367,7 +367,7 @@ targets += $(lib-y) $(always-y) $(MAKECM +@@ -385,7 +385,7 @@ targets += $(real-dtb-y) $(lib-y) $(alwa # Linker scripts preprocessor (.lds.S -> .lds) # --------------------------------------------------------------------------- quiet_cmd_cpp_lds_S = LDS $@ diff --git a/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch b/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch index 906527faf9..8aa5b7c579 100644 --- a/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch +++ b/target/linux/generic/hack-5.15/230-openwrt_lzma_options.patch @@ -23,7 +23,7 @@ Signed-off-by: Imre Kaloz { {0x02, 0x21}, "lz4", unlz4 }, --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -370,7 +370,7 @@ quiet_cmd_bzip2 = BZIP2 $@ +@@ -413,7 +413,7 @@ quiet_cmd_bzip2 = BZIP2 $@ # --------------------------------------------------------------------------- quiet_cmd_lzma = LZMA $@ diff --git a/target/linux/generic/hack-5.15/250-netfilter_depends.patch b/target/linux/generic/hack-5.15/250-netfilter_depends.patch index b27b440157..495c73ffa8 100644 --- a/target/linux/generic/hack-5.15/250-netfilter_depends.patch +++ b/target/linux/generic/hack-5.15/250-netfilter_depends.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -228,7 +228,6 @@ config NF_CONNTRACK_FTP +@@ -243,7 +243,6 @@ config NF_CONNTRACK_FTP config NF_CONNTRACK_H323 tristate "H.323 protocol support" @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau depends on NETFILTER_ADVANCED help H.323 is a VoIP signalling protocol from ITU-T. As one of the most -@@ -1072,7 +1071,6 @@ config NETFILTER_XT_TARGET_SECMARK +@@ -1106,7 +1105,6 @@ config NETFILTER_XT_TARGET_SECMARK config NETFILTER_XT_TARGET_TCPMSS tristate '"TCPMSS" target support' diff --git a/target/linux/generic/hack-5.15/251-kconfig.patch b/target/linux/generic/hack-5.15/251-kconfig.patch index 34a63eaa7c..3304e9543a 100644 --- a/target/linux/generic/hack-5.15/251-kconfig.patch +++ b/target/linux/generic/hack-5.15/251-kconfig.patch @@ -92,7 +92,7 @@ Signed-off-by: John Crispin bool --- a/lib/Kconfig +++ b/lib/Kconfig -@@ -418,16 +418,16 @@ config BCH_CONST_T +@@ -438,16 +438,16 @@ config BCH_CONST_T # Textsearch support is select'ed if needed # config TEXTSEARCH diff --git a/target/linux/generic/hack-5.15/253-ksmbd-config.patch b/target/linux/generic/hack-5.15/253-ksmbd-config.patch index c2b2a96b9c..89be6f6c47 100644 --- a/target/linux/generic/hack-5.15/253-ksmbd-config.patch +++ b/target/linux/generic/hack-5.15/253-ksmbd-config.patch @@ -11,7 +11,7 @@ that can be interpreted by the ASN.1 stream decoder and used to --- a/lib/Kconfig +++ b/lib/Kconfig -@@ -589,7 +589,7 @@ config LIBFDT +@@ -609,7 +609,7 @@ config LIBFDT bool config OID_REGISTRY diff --git a/target/linux/generic/hack-5.15/259-regmap_dynamic.patch b/target/linux/generic/hack-5.15/259-regmap_dynamic.patch index 1d9e862620..6be5875177 100644 --- a/target/linux/generic/hack-5.15/259-regmap_dynamic.patch +++ b/target/linux/generic/hack-5.15/259-regmap_dynamic.patch @@ -94,7 +94,6 @@ Signed-off-by: Felix Fietkau + select REGMAP tristate depends on SPI - --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -2,10 +2,14 @@ @@ -126,7 +125,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -3298,3 +3299,5 @@ static int __init regmap_initcall(void) +@@ -3341,3 +3342,5 @@ static int __init regmap_initcall(void) return 0; } postcore_initcall(regmap_initcall); @@ -134,7 +133,7 @@ Signed-off-by: Felix Fietkau +MODULE_LICENSE("GPL"); --- a/include/linux/regmap.h +++ b/include/linux/regmap.h -@@ -179,7 +179,7 @@ struct reg_sequence { +@@ -180,7 +180,7 @@ struct reg_sequence { __ret ?: __tmp; \ }) diff --git a/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch b/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch index 1eab709c46..c73a1f1f64 100644 --- a/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch +++ b/target/linux/generic/hack-5.15/260-crypto_test_dependencies.patch @@ -37,7 +37,7 @@ Signed-off-by: Felix Fietkau tristate "Userspace cryptographic algorithm configuration" --- a/crypto/algboss.c +++ b/crypto/algboss.c -@@ -230,8 +230,12 @@ static int cryptomgr_schedule_test(struc +@@ -211,8 +211,12 @@ static int cryptomgr_schedule_test(struc type = alg->cra_flags; /* Do not test internal algorithms. */ diff --git a/target/linux/generic/hack-5.15/280-rfkill-stubs.patch b/target/linux/generic/hack-5.15/280-rfkill-stubs.patch index 2e48aea1cf..7a650d132e 100644 --- a/target/linux/generic/hack-5.15/280-rfkill-stubs.patch +++ b/target/linux/generic/hack-5.15/280-rfkill-stubs.patch @@ -26,7 +26,7 @@ Signed-off-by: John Crispin * @name: name of the struct -- the string is not copied internally --- a/net/Makefile +++ b/net/Makefile -@@ -53,7 +53,7 @@ obj-$(CONFIG_TIPC) += tipc/ +@@ -52,7 +52,7 @@ obj-$(CONFIG_TIPC) += tipc/ obj-$(CONFIG_NETLABEL) += netlabel/ obj-$(CONFIG_IUCV) += iucv/ obj-$(CONFIG_SMC) += smc/ @@ -34,7 +34,7 @@ Signed-off-by: John Crispin +obj-$(CONFIG_RFKILL_FULL) += rfkill/ obj-$(CONFIG_NET_9P) += 9p/ obj-$(CONFIG_CAIF) += caif/ - ifneq ($(CONFIG_DCB),) + obj-$(CONFIG_DCB) += dcb/ --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig @@ -2,7 +2,11 @@ diff --git a/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch index fe89de7e08..f21f200136 100644 --- a/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch +++ b/target/linux/generic/hack-5.15/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h -@@ -296,14 +296,46 @@ static inline void prot##extra##blast_## +@@ -286,14 +286,46 @@ static inline void prot##extra##blast_## unsigned long end) \ { \ unsigned long lsize = cpu_##desc##_line_size(); \ diff --git a/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch b/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch index 4edf527246..15e233aceb 100644 --- a/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch +++ b/target/linux/generic/hack-5.15/301-mips_image_cmdline_hack.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -1170,6 +1170,10 @@ config MIPS_MSC +@@ -1180,6 +1180,10 @@ config MIPS_MSC config SYNC_R4K bool diff --git a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch index c9821b57eb..d0f81c485b 100644 --- a/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch +++ b/target/linux/generic/hack-5.15/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -77,7 +77,7 @@ Signed-off-by: Daniel Golle #include "mtdcore.h" -@@ -1000,6 +1001,8 @@ int mtd_device_parse_register(struct mtd +@@ -1002,6 +1003,8 @@ int mtd_device_parse_register(struct mtd ret = mtd_otp_nvmem_add(mtd); diff --git a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch index 65438807de..560196ac72 100644 --- a/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch +++ b/target/linux/generic/hack-5.15/410-block-fit-partition-parser.patch @@ -1,6 +1,6 @@ --- a/block/blk.h +++ b/block/blk.h -@@ -361,6 +361,8 @@ char *disk_name(struct gendisk *hd, int +@@ -354,6 +354,8 @@ void blk_free_ext_minor(unsigned int min #define ADDPART_FLAG_NONE 0 #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 @@ -53,7 +53,7 @@ +int parse_fit_partitions(struct parsed_partitions *state, u64 start_sector, u64 nr_sectors, int *slot, int add_remain); --- a/block/partitions/core.c +++ b/block/partitions/core.c -@@ -10,6 +10,10 @@ +@@ -12,6 +12,10 @@ #include #include #include @@ -64,7 +64,7 @@ #include "check.h" static int (*check_part[])(struct parsed_partitions *) = { -@@ -46,6 +50,9 @@ static int (*check_part[])(struct parsed +@@ -48,6 +52,9 @@ static int (*check_part[])(struct parsed #ifdef CONFIG_EFI_PARTITION efi_partition, /* this must come before msdos */ #endif @@ -74,9 +74,9 @@ #ifdef CONFIG_SGI_PARTITION sgi_partition, #endif -@@ -694,6 +701,14 @@ static bool blk_add_partition(struct gen +@@ -598,6 +605,14 @@ static bool blk_add_partition(struct gen (state->parts[p].flags & ADDPART_FLAG_RAID)) - md_autodetect_dev(part_to_dev(part)->devt); + md_autodetect_dev(part->bd_dev); +#ifdef CONFIG_FIT_PARTITION + if ((state->parts[p].flags & ADDPART_FLAG_ROOTDEV) && ROOT_DEV == 0) @@ -91,7 +91,7 @@ --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -413,6 +417,9 @@ int ubiblock_create(struct ubi_volume_in +@@ -428,6 +428,9 @@ int ubiblock_create(struct ubi_volume_in goto out_cleanup_disk; } gd->private_data = dev; @@ -103,7 +103,7 @@ dev->gd = gd; --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c -@@ -345,6 +345,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) +@@ -345,6 +345,9 @@ int add_mtd_blktrans_dev(struct mtd_blkt gd->first_minor = (new->devnum) << tr->part_bits; gd->minors = 1 << tr->part_bits; gd->fops = &mtd_block_ops; @@ -115,7 +115,7 @@ if (new->devnum < 26) --- a/block/partitions/efi.c +++ b/block/partitions/efi.c -@@ -706,6 +706,9 @@ int efi_partition(struct parsed_partitio +@@ -716,6 +716,9 @@ int efi_partition(struct parsed_partitio gpt_entry *ptes = NULL; u32 i; unsigned ssz = queue_logical_block_size(state->disk->queue) / 512; @@ -125,7 +125,7 @@ if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); -@@ -739,6 +742,11 @@ int efi_partition(struct parsed_partitio +@@ -749,6 +752,11 @@ int efi_partition(struct parsed_partitio ARRAY_SIZE(ptes[i].partition_name)); utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname); state->parts[i + 1].has_info = true; @@ -151,7 +151,7 @@ __le64 signature; --- a/block/partitions/msdos.c +++ b/block/partitions/msdos.c -@@ -563,6 +563,15 @@ static void parse_minix(struct parsed_pa +@@ -564,6 +564,15 @@ static void parse_minix(struct parsed_pa #endif /* CONFIG_MINIX_SUBPARTITION */ } @@ -167,7 +167,7 @@ static struct { unsigned char id; void (*parse)(struct parsed_partitions *, sector_t, sector_t, int); -@@ -574,6 +583,7 @@ static struct { +@@ -575,6 +584,7 @@ static struct { {UNIXWARE_PARTITION, parse_unixware}, {SOLARIS_X86_PARTITION, parse_solaris_x86}, {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86}, diff --git a/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch b/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch index 80122277e9..8ac1dca238 100644 --- a/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch +++ b/target/linux/generic/hack-5.15/420-mtd-set-rootfs-to-be-root-dev.patch @@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos #include #include -@@ -694,6 +695,16 @@ int add_mtd_device(struct mtd_info *mtd) +@@ -697,6 +698,16 @@ int add_mtd_device(struct mtd_info *mtd) of this try_ nonsense, and no bitching about it either. :) */ __module_get(THIS_MODULE); diff --git a/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch b/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch index 62ddd66bf2..2a98fe6f81 100644 --- a/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch +++ b/target/linux/generic/hack-5.15/430-mtk-bmt-support.patch @@ -1,8 +1,8 @@ --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig -@@ -15,6 +15,10 @@ config MTD_NAND_ECC - bool - depends on MTD_NAND_CORE +@@ -46,6 +46,10 @@ config MTD_NAND_ECC_SW_BCH + ECC codes. They are used with NAND devices requiring more than 1 bit + of error correction. +config MTD_NAND_MTK_BMT + bool "Support MediaTek NAND Bad-block Management Table" diff --git a/target/linux/generic/hack-5.15/600-bridge_offload.patch b/target/linux/generic/hack-5.15/600-bridge_offload.patch index 9206722d73..c7942a0aef 100644 --- a/target/linux/generic/hack-5.15/600-bridge_offload.patch +++ b/target/linux/generic/hack-5.15/600-bridge_offload.patch @@ -1,6 +1,6 @@ --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h -@@ -57,6 +57,7 @@ struct br_ip_list { +@@ -59,6 +59,7 @@ struct br_ip_list { #define BR_MRP_LOST_IN_CONT BIT(19) #define BR_TX_FWD_OFFLOAD BIT(20) #define BR_BPDU_FILTER BIT(21) @@ -29,7 +29,7 @@ /* * Handle changes in state of network devices enslaved to a bridge. -@@ -332,6 +333,10 @@ static int __init br_init(void) +@@ -381,6 +382,10 @@ static int __init br_init(void) if (err) goto err_out; @@ -40,7 +40,7 @@ err = register_pernet_subsys(&br_net_ops); if (err) goto err_out1; -@@ -375,6 +380,8 @@ err_out3: +@@ -430,6 +435,8 @@ err_out3: err_out2: unregister_pernet_subsys(&br_net_ops); err_out1: @@ -49,7 +49,7 @@ br_fdb_fini(); err_out: stp_proto_unregister(&br_stp_proto); -@@ -396,6 +403,7 @@ static void __exit br_deinit(void) +@@ -452,6 +459,7 @@ static void __exit br_deinit(void) #if IS_ENABLED(CONFIG_ATM_LANE) br_fdb_test_addr_hook = NULL; #endif @@ -59,7 +59,7 @@ --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c -@@ -529,6 +529,8 @@ void br_dev_setup(struct net_device *dev +@@ -524,6 +524,8 @@ void br_dev_setup(struct net_device *dev br->bridge_hello_time = br->hello_time = 2 * HZ; br->bridge_forward_delay = br->forward_delay = 15 * HZ; br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME; @@ -78,7 +78,7 @@ static const struct rhashtable_params br_fdb_rht_params = { .head_offset = offsetof(struct net_bridge_fdb_entry, rhnode), -@@ -513,6 +514,8 @@ static struct net_bridge_fdb_entry *fdb_ +@@ -518,6 +519,8 @@ static struct net_bridge_fdb_entry *fdb_ fdb->key.vlan_id = vid; fdb->flags = flags; fdb->updated = fdb->used = jiffies; @@ -87,7 +87,7 @@ if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl, &fdb->rhnode, br_fdb_rht_params)) { -@@ -734,6 +737,8 @@ static void fdb_notify(struct net_bridge +@@ -794,6 +797,8 @@ static void fdb_notify(struct net_bridge struct sk_buff *skb; int err = -ENOBUFS; @@ -125,7 +125,7 @@ /* * Determine initial path cost based on speed. -@@ -427,7 +428,7 @@ static struct net_bridge_port *new_nbp(s +@@ -428,7 +429,7 @@ static struct net_bridge_port *new_nbp(s p->path_cost = port_cost(dev); p->priority = 0x8000 >> BR_PORT_BITS; p->port_no = index; @@ -134,7 +134,7 @@ br_init_port(p); br_set_state(p, BR_STATE_DISABLED); br_stp_port_timer_init(p); -@@ -777,6 +778,9 @@ void br_port_flags_change(struct net_bri +@@ -771,6 +772,9 @@ void br_port_flags_change(struct net_bri if (mask & BR_NEIGH_SUPPRESS) br_recalculate_neigh_suppress_enabled(br); @@ -154,7 +154,7 @@ static int br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) -@@ -162,6 +163,7 @@ int br_handle_frame_finish(struct net *n +@@ -164,6 +165,7 @@ int br_handle_frame_finish(struct net *n dst->used = now; br_forward(dst->dst, skb, local_rcv, false); } else { @@ -162,7 +162,7 @@ if (!mcast_hit) br_flood(br, skb, pkt_type, local_rcv, false); else -@@ -280,6 +282,9 @@ static rx_handler_result_t br_handle_fra +@@ -297,6 +299,9 @@ static rx_handler_result_t br_handle_fra memset(skb->cb, 0, sizeof(struct br_input_skb_cb)); p = br_port_get_rcu(skb->dev); @@ -170,7 +170,7 @@ + return RX_HANDLER_CONSUMED; + if (p->flags & BR_VLAN_TUNNEL) - br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p)) + br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p)); --- /dev/null +++ b/net/bridge/br_offload.c @@ -615,7 +615,7 @@ +} --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h -@@ -207,7 +207,13 @@ struct net_bridge_fdb_entry { +@@ -268,7 +268,13 @@ struct net_bridge_fdb_entry { unsigned long updated ____cacheline_aligned_in_smp; unsigned long used; @@ -630,7 +630,7 @@ }; #define MDB_PG_FLAGS_PERMANENT BIT(0) -@@ -280,6 +286,12 @@ struct net_bridge_mdb_entry { +@@ -343,6 +349,12 @@ struct net_bridge_mdb_entry { struct rcu_head rcu; }; @@ -643,7 +643,7 @@ struct net_bridge_port { struct net_bridge *br; struct net_device *dev; -@@ -337,6 +349,7 @@ struct net_bridge_port { +@@ -403,6 +415,7 @@ struct net_bridge_port { u16 backup_redirected_cnt; struct bridge_stp_xstats stp_xstats; @@ -651,7 +651,7 @@ }; #define kobj_to_brport(obj) container_of(obj, struct net_bridge_port, kobj) -@@ -475,6 +488,9 @@ struct net_bridge { +@@ -519,6 +532,9 @@ struct net_bridge { struct kobject *ifobj; u32 auto_cnt; @@ -661,7 +661,7 @@ #ifdef CONFIG_NET_SWITCHDEV /* Counter used to make sure that hardware domains get unique * identifiers in case a bridge spans multiple switchdev instances. -@@ -501,6 +517,10 @@ struct br_input_skb_cb { +@@ -553,6 +569,10 @@ struct br_input_skb_cb { #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE u8 br_netfilter_broute:1; #endif @@ -725,9 +725,9 @@ #include "br_private.h" +#include "br_private_offload.h" - #define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd))) - -@@ -842,6 +843,38 @@ static ssize_t vlan_stats_per_port_store + /* IMPORTANT: new bridge options must be added with netlink support only + * please do not add new sysfs entries +@@ -930,6 +931,38 @@ static ssize_t vlan_stats_per_port_store static DEVICE_ATTR_RW(vlan_stats_per_port); #endif @@ -766,7 +766,7 @@ static struct attribute *bridge_attrs[] = { &dev_attr_forward_delay.attr, &dev_attr_hello_time.attr, -@@ -896,6 +929,8 @@ static struct attribute *bridge_attrs[] +@@ -984,6 +1017,8 @@ static struct attribute *bridge_attrs[] &dev_attr_vlan_stats_enabled.attr, &dev_attr_vlan_stats_per_port.attr, #endif @@ -777,7 +777,7 @@ --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c -@@ -234,6 +234,7 @@ BRPORT_ATTR_FLAG(broadcast_flood, BR_BCA +@@ -241,6 +241,7 @@ BRPORT_ATTR_FLAG(broadcast_flood, BR_BCA BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); BRPORT_ATTR_FLAG(bpdu_filter, BR_BPDU_FILTER); @@ -785,7 +785,7 @@ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) -@@ -288,6 +289,7 @@ static const struct brport_attribute *br +@@ -295,6 +296,7 @@ static const struct brport_attribute *br &brport_attr_isolated, &brport_attr_bpdu_filter, &brport_attr_backup_port, @@ -803,7 +803,7 @@ static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg, const void *ptr) -@@ -180,6 +181,7 @@ int br_handle_ingress_vlan_tunnel(struct +@@ -180,6 +181,7 @@ void br_handle_ingress_vlan_tunnel(struc skb_dst_drop(skb); __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid); @@ -811,7 +811,7 @@ } int br_handle_egress_vlan_tunnel(struct sk_buff *skb, -@@ -203,6 +205,7 @@ int br_handle_egress_vlan_tunnel(struct +@@ -201,6 +203,7 @@ int br_handle_egress_vlan_tunnel(struct if (err) return err; diff --git a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index 23332534bb..c873d606f3 100644 --- a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau depends on !NF_CONNTRACK || NF_CONNTRACK --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig -@@ -683,8 +683,6 @@ config NFT_FIB_NETDEV +@@ -708,8 +708,6 @@ config NFT_REJECT_NETDEV endif # NF_TABLES_NETDEV @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau config NF_FLOW_TABLE_INET tristate "Netfilter flow table mixed IPv4/IPv6 module" depends on NF_FLOW_TABLE -@@ -693,11 +691,12 @@ config NF_FLOW_TABLE_INET +@@ -718,11 +716,12 @@ config NF_FLOW_TABLE_INET To compile it as a module, choose M here. @@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau help This option adds the flow table core infrastructure. -@@ -977,6 +976,15 @@ config NETFILTER_XT_TARGET_NOTRACK +@@ -1011,6 +1010,15 @@ config NETFILTER_XT_TARGET_NOTRACK depends on NETFILTER_ADVANCED select NETFILTER_XT_TARGET_CT @@ -88,7 +88,7 @@ Signed-off-by: Felix Fietkau depends on NETFILTER_ADVANCED --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile -@@ -145,6 +145,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF +@@ -143,6 +143,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o @@ -766,7 +766,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -395,8 +394,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -397,8 +396,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); @@ -776,7 +776,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct flow_offload *flow, void *data), void *data) { -@@ -428,6 +426,7 @@ nf_flow_table_iterate(struct nf_flowtabl +@@ -430,6 +428,7 @@ nf_flow_table_iterate(struct nf_flowtabl return err; } @@ -806,7 +806,7 @@ Signed-off-by: Felix Fietkau +#endif /* _XT_FLOWOFFLOAD_H */ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -270,6 +270,10 @@ void nf_flow_table_free(struct nf_flowta +@@ -273,6 +273,10 @@ void nf_flow_table_free(struct nf_flowta void flow_offload_teardown(struct flow_offload *flow); diff --git a/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch b/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch index 0639ad4e48..12a031ec84 100644 --- a/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch +++ b/target/linux/generic/hack-5.15/651-wireless_mesh_header.patch @@ -11,7 +11,7 @@ Signed-off-by: Imre Kaloz --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -144,8 +144,8 @@ static inline bool dev_xmit_complete(int +@@ -145,8 +145,8 @@ static inline bool dev_xmit_complete(int #if defined(CONFIG_HYPERV_NET) # define LL_MAX_HEADER 128 diff --git a/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch b/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch index 6794349e26..5541c0bc89 100644 --- a/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch +++ b/target/linux/generic/hack-5.15/660-fq_codel_defaults.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c -@@ -461,7 +461,11 @@ static int fq_codel_init(struct Qdisc *s +@@ -469,7 +469,11 @@ static int fq_codel_init(struct Qdisc *s sch->limit = 10*1024; q->flows_cnt = 1024; diff --git a/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch b/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch index f301cc1e2d..f85b558fef 100644 --- a/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch +++ b/target/linux/generic/hack-5.15/710-net-dsa-mv88e6xxx-default-VID-1.patch @@ -1,6 +1,6 @@ --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -2088,6 +2088,7 @@ static int mv88e6xxx_port_fdb_add(struct +@@ -2321,6 +2321,7 @@ static int mv88e6xxx_port_fdb_add(struct struct mv88e6xxx_chip *chip = ds->priv; int err; @@ -8,7 +8,7 @@ mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); -@@ -2102,6 +2103,7 @@ static int mv88e6xxx_port_fdb_del(struct +@@ -2335,6 +2336,7 @@ static int mv88e6xxx_port_fdb_del(struct struct mv88e6xxx_chip *chip = ds->priv; int err; diff --git a/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch index 46a1ba1d96..4e0654f8f3 100644 --- a/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch +++ b/target/linux/generic/hack-5.15/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch @@ -1,8 +1,8 @@ --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -2650,6 +2650,9 @@ static int mv88e6xxx_setup_port(struct m - if (dsa_is_cpu_port(ds, port)) - reg = 0; +@@ -2983,6 +2983,9 @@ static int mv88e6xxx_setup_port(struct m + else + reg = 1 << port; + /* Disable ATU member violation interrupt */ + reg |= MV88E6XXX_PORT_ASSOC_VECTOR_IGNORE_WRONG; diff --git a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch index 979308a908..59124990c3 100644 --- a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch +++ b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch @@ -20,7 +20,7 @@ Signed-off-by: Birger Koblitz #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -330,6 +332,49 @@ static int aqr107_read_rate(struct phy_d +@@ -359,6 +361,49 @@ static int aqr107_read_rate(struct phy_d return 0; } @@ -70,7 +70,7 @@ Signed-off-by: Birger Koblitz static int aqr107_read_status(struct phy_device *phydev) { int val, ret; -@@ -460,7 +505,7 @@ static void aqr107_chip_info(struct phy_ +@@ -489,7 +534,7 @@ static void aqr107_chip_info(struct phy_ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); @@ -79,7 +79,7 @@ Signed-off-by: Birger Koblitz fw_major, fw_minor, build_id, prov_id); } -@@ -632,6 +677,24 @@ static struct phy_driver aqr_driver[] = +@@ -661,6 +706,24 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { @@ -104,8 +104,8 @@ Signed-off-by: Birger Koblitz PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), .name = "Aquantia AQCS109", .probe = aqr107_probe, -@@ -657,6 +720,24 @@ static struct phy_driver aqr_driver[] = - .ack_interrupt = aqr_ack_interrupt, +@@ -686,6 +749,24 @@ static struct phy_driver aqr_driver[] = + .handle_interrupt = aqr_handle_interrupt, .read_status = aqr_read_status, }, +{ @@ -129,7 +129,7 @@ Signed-off-by: Birger Koblitz }; module_phy_driver(aqr_driver); -@@ -667,8 +748,10 @@ static struct mdio_device_id __maybe_unu +@@ -696,8 +777,10 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, diff --git a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch index e36d829ac5..abc0735e36 100644 --- a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch @@ -19,18 +19,18 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1618,6 +1618,10 @@ enum netdev_priv_flags { - IFF_LIVE_RENAME_OK = 1<<30, +@@ -1648,6 +1648,10 @@ enum netdev_priv_flags { IFF_TX_SKB_NO_LINEAR = 1<<31, }; -+ + +enum netdev_extra_priv_flags { + IFF_NO_IP_ALIGN = 1<<0, +}; - ++ #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN #define IFF_EBRIDGE IFF_EBRIDGE -@@ -1650,6 +1651,7 @@ enum netdev_priv_flags { + #define IFF_BONDING IFF_BONDING +@@ -1680,6 +1684,7 @@ enum netdev_priv_flags { #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR @@ -38,15 +38,15 @@ Signed-off-by: Felix Fietkau /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -1987,6 +1987,7 @@ enum netdev_priv_flags { - /* Read-mostly cache-line for fast-path access */ +@@ -1981,6 +1986,7 @@ struct net_device { + /* Read-mostly cache-line for fast-path access */ unsigned int flags; unsigned int priv_flags; + unsigned int extra_priv_flags; const struct net_device_ops *netdev_ops; int ifindex; unsigned short gflags; -@@ -1990,6 +1992,11 @@ struct net_device { +@@ -2041,6 +2047,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -57,9 +57,9 @@ Signed-off-by: Felix Fietkau + const struct header_ops *header_ops; - unsigned int flags; -@@ -2080,6 +2087,10 @@ struct net_device { - struct mpls_dev __rcu *mpls_ptr; + unsigned char operstate; +@@ -2115,6 +2126,10 @@ struct net_device { + struct mctp_dev __rcu *mctp_ptr; #endif +#ifdef CONFIG_ETHERNET_PACKET_MANGLE @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau */ --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2710,6 +2710,10 @@ static inline int pskb_trim(struct sk_bu +@@ -2761,6 +2761,10 @@ static inline int pskb_trim(struct sk_bu return (len < skb->len) ? __pskb_trim(skb, len) : 0; } @@ -82,7 +82,7 @@ Signed-off-by: Felix Fietkau /** * pskb_trim_unique - remove end from a paged unique (not cloned) buffer * @skb: buffer to alter -@@ -2841,16 +2845,6 @@ static inline struct sk_buff *dev_alloc_ +@@ -2911,16 +2915,6 @@ static inline struct sk_buff *dev_alloc_ } @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3646,6 +3646,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3578,6 +3578,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); @@ -130,7 +130,7 @@ Signed-off-by: Felix Fietkau trace_net_dev_start_xmit(skb, dev); --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -60,6 +60,7 @@ +@@ -61,6 +61,7 @@ #include #include #include @@ -138,7 +138,7 @@ Signed-off-by: Felix Fietkau #include #include -@@ -553,6 +554,22 @@ skb_fail: +@@ -602,6 +603,22 @@ skb_fail: } EXPORT_SYMBOL(__napi_alloc_skb); @@ -163,7 +163,7 @@ Signed-off-by: Felix Fietkau { --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c -@@ -171,6 +171,12 @@ __be16 eth_type_trans(struct sk_buff *sk +@@ -170,6 +170,12 @@ __be16 eth_type_trans(struct sk_buff *sk const struct ethhdr *eth; skb->dev = dev; diff --git a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index 6ab7bc7569..37724f6895 100644 --- a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -27,7 +27,7 @@ Signed-off-by: Alex Marginean #define PHY_ID_AQR813 0x31c31cb2 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 -@@ -123,6 +125,29 @@ +@@ -124,6 +126,29 @@ #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) @@ -57,7 +57,7 @@ Signed-off-by: Alex Marginean struct aqr107_hw_stat { const char *name; int reg; -@@ -243,6 +268,51 @@ static int aqr_config_aneg(struct phy_de +@@ -244,6 +269,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -109,7 +109,7 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -738,6 +808,30 @@ static struct phy_driver aqr_driver[] = +@@ -767,6 +837,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -140,7 +140,7 @@ Signed-off-by: Alex Marginean }; module_phy_driver(aqr_driver); -@@ -748,9 +842,11 @@ static struct mdio_device_id __maybe_unu +@@ -777,9 +871,11 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, diff --git a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch index 9c5df905bb..30ee41d122 100644 --- a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch +++ b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -14,7 +14,7 @@ Signed-off-by: Alex Marginean --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -301,10 +301,16 @@ static int aqr_config_aneg_set_prot(stru +@@ -302,10 +302,16 @@ static int aqr_config_aneg_set_prot(stru phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, aquantia_syscfg[if_type].start_rate); diff --git a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch index 1fc7658ff3..27b09c5fbd 100644 --- a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch @@ -18,7 +18,7 @@ Add a new entry for AQR113 PHY_ID #define PHY_ID_AQR113C 0x31c31c12 #define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQR405 0x03a1b4b0 -@@ -827,6 +828,14 @@ static struct phy_driver aqr_driver[] = +@@ -856,6 +857,14 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -33,7 +33,7 @@ Add a new entry for AQR113 PHY_ID PHY_ID_MATCH_MODEL(PHY_ID_AQR412), .name = "Aquantia AQR412", .probe = aqr107_probe, -@@ -849,6 +858,7 @@ static struct mdio_device_id __maybe_unu +@@ -878,6 +887,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, diff --git a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index ba9f3ee120..e27178f8a1 100644 --- a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -21,7 +21,7 @@ Signed-off-by: Daniel Golle #define PHY_ID_AQR113 0x31c31c40 #define PHY_ID_AQR113C 0x31c31c12 #define PHY_ID_AQCS109 0x03a1b5c2 -@@ -828,6 +830,30 @@ static struct phy_driver aqr_driver[] = +@@ -857,6 +859,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle PHY_ID_MATCH_MODEL(PHY_ID_AQR113), .name = "Aquantia AQR113", .config_aneg = aqr_config_aneg, -@@ -858,6 +884,8 @@ static struct mdio_device_id __maybe_unu +@@ -887,6 +913,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, diff --git a/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch b/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch index f94d16c0ff..b71e1df06f 100644 --- a/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch +++ b/target/linux/generic/hack-5.15/760-net-usb-r8152-add-LED-configuration-from-OF.patch @@ -22,7 +22,7 @@ Signed-off-by: David Bauer #include #include #include -@@ -5301,6 +5302,22 @@ static void rtl_tally_reset(struct r8152 +@@ -6852,6 +6853,22 @@ static void rtl_tally_reset(struct r8152 ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); } @@ -45,7 +45,7 @@ Signed-off-by: David Bauer static void r8152b_init(struct r8152 *tp) { u32 ocp_data; -@@ -5342,6 +5359,8 @@ static void r8152b_init(struct r8152 *tp +@@ -6893,6 +6910,8 @@ static void r8152b_init(struct r8152 *tp ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); @@ -54,7 +54,7 @@ Signed-off-by: David Bauer } static void r8153_init(struct r8152 *tp) -@@ -5487,6 +5506,8 @@ static void r8153_init(struct r8152 *tp) +@@ -7033,6 +7052,8 @@ static void r8153_init(struct r8152 *tp) tp->coalesce = COALESCE_SLOW; break; } @@ -63,7 +63,7 @@ Signed-off-by: David Bauer } static void r8153b_init(struct r8152 *tp) -@@ -5573,6 +5594,8 @@ static void r8153b_init(struct r8152 *tp +@@ -7115,6 +7136,8 @@ static void r8153b_init(struct r8152 *tp rtl_tally_reset(tp); tp->coalesce = 15000; /* 15 us */ @@ -71,4 +71,4 @@ Signed-off-by: David Bauer + r8152_led_configuration(tp); } - static int rtl8152_pre_reset(struct usb_interface *intf) + static void r8153c_init(struct r8152 *tp) diff --git a/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch index 5a7e38516c..1e4fc446ce 100644 --- a/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/hack-5.15/773-bgmac-add-srab-switch.patch @@ -14,7 +14,7 @@ Signed-off-by: Hauke Mehrtens --- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c -@@ -266,6 +266,7 @@ static int bgmac_probe(struct bcma_devic +@@ -280,6 +280,7 @@ static int bgmac_probe(struct bcma_devic bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; @@ -78,7 +78,7 @@ Signed-off-by: Hauke Mehrtens netif_napi_del(&bgmac->napi); --- a/drivers/net/ethernet/broadcom/bgmac.h +++ b/drivers/net/ethernet/broadcom/bgmac.h -@@ -428,6 +428,7 @@ +@@ -390,6 +390,7 @@ #define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII BIT(18) #define BGMAC_FEAT_CC7_IF_TYPE_RGMII BIT(19) #define BGMAC_FEAT_IDM_MASK BIT(20) @@ -86,7 +86,7 @@ Signed-off-by: Hauke Mehrtens struct bgmac_slot_info { union { -@@ -533,6 +534,9 @@ struct bgmac { +@@ -495,6 +496,9 @@ struct bgmac { void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask, u32 set); int (*phy_connect)(struct bgmac *bgmac); diff --git a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch index cb6f46760b..85dc3db98d 100644 --- a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c -@@ -1024,6 +1024,7 @@ static const struct usb_device_id produc +@@ -1085,6 +1085,7 @@ static const struct usb_device_id produc {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ diff --git a/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch index 76f89acdcd..f24fe9d192 100644 --- a/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-5.15/800-GPIO-add-named-gpio-exports.patch @@ -15,9 +15,9 @@ Signed-off-by: John Crispin #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1039,3 +1041,72 @@ void of_gpiochip_remove(struct gpio_chip - { - of_node_put(chip->of_node); +@@ -1052,3 +1054,72 @@ void of_gpio_dev_init(struct gpio_chip * + else + gc->of_node = gdev->dev.of_node; } + +#ifdef CONFIG_GPIO_SYSFS @@ -129,7 +129,7 @@ Signed-off-by: John Crispin { --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c -@@ -572,7 +572,7 @@ static struct class gpio_class = { +@@ -561,7 +561,7 @@ static struct class gpio_class = { * * Returns zero on success, else an error. */ @@ -138,7 +138,7 @@ Signed-off-by: John Crispin { struct gpio_chip *chip; struct gpio_device *gdev; -@@ -634,6 +634,8 @@ int gpiod_export(struct gpio_desc *desc, +@@ -623,6 +623,8 @@ int gpiod_export(struct gpio_desc *desc, offset = gpio_chip_hwgpio(desc); if (chip->names && chip->names[offset]) ioname = chip->names[offset]; @@ -147,7 +147,7 @@ Signed-off-by: John Crispin dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), data, gpio_groups, -@@ -655,6 +657,12 @@ err_unlock: +@@ -644,6 +646,12 @@ err_unlock: gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } diff --git a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch index b0e1661019..ab629d598f 100644 --- a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch @@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau --- a/net/Kconfig +++ b/net/Kconfig -@@ -98,6 +98,9 @@ source "net/mptcp/Kconfig" +@@ -104,6 +104,9 @@ source "net/mptcp/Kconfig" endif # if INET @@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau #include -@@ -141,6 +142,7 @@ +@@ -143,6 +144,7 @@ static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); @@ -58,7 +58,7 @@ Signed-off-by: Felix Fietkau static void sock_inuse_add(struct net *net, int val); -@@ -526,6 +528,18 @@ discard_and_relse: +@@ -545,6 +547,18 @@ discard_and_relse: } EXPORT_SYMBOL(__sk_receive_skb); @@ -77,7 +77,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -1816,9 +1830,11 @@ static void __sk_free(struct sock *sk) +@@ -1983,9 +1997,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); @@ -152,7 +152,7 @@ Signed-off-by: Felix Fietkau Support for PF_PACKET sockets monitoring interface used by the ss tool. --- a/net/unix/Kconfig +++ b/net/unix/Kconfig -@@ -28,6 +28,7 @@ config UNIX_SCM +@@ -33,6 +33,7 @@ config AF_UNIX_OOB config UNIX_DIAG tristate "UNIX: socket monitoring interface" depends on UNIX diff --git a/target/linux/generic/hack-5.15/902-debloat_proc.patch b/target/linux/generic/hack-5.15/902-debloat_proc.patch index 33a3e3c5d5..fef28464bc 100644 --- a/target/linux/generic/hack-5.15/902-debloat_proc.patch +++ b/target/linux/generic/hack-5.15/902-debloat_proc.patch @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau --- a/fs/locks.c +++ b/fs/locks.c -@@ -2993,6 +2993,8 @@ static const struct seq_operations locks +@@ -2929,6 +2929,8 @@ static const struct seq_operations locks static int __init proc_locks_init(void) { @@ -147,7 +147,7 @@ Signed-off-by: Felix Fietkau IPC_MSG_IDS, sysvipc_msg_proc_show); --- a/ipc/sem.c +++ b/ipc/sem.c -@@ -266,6 +266,8 @@ void sem_exit_ns(struct ipc_namespace *n +@@ -268,6 +268,8 @@ void sem_exit_ns(struct ipc_namespace *n void __init sem_init(void) { sem_init_ns(&init_ipc_ns); @@ -169,7 +169,7 @@ Signed-off-by: Felix Fietkau " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n", --- a/ipc/util.c +++ b/ipc/util.c -@@ -140,6 +140,9 @@ void __init ipc_init_proc_interface(cons +@@ -141,6 +141,9 @@ void __init ipc_init_proc_interface(cons struct proc_dir_entry *pde; struct ipc_proc_iface *iface; @@ -224,7 +224,7 @@ Signed-off-by: Felix Fietkau if (!root_irq_dir) --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c -@@ -370,6 +370,8 @@ static int __init init_timer_list_procfs +@@ -350,6 +350,8 @@ static int __init init_timer_list_procfs { struct proc_dir_entry *pe; @@ -235,7 +235,7 @@ Signed-off-by: Felix Fietkau if (!pe) --- a/mm/vmalloc.c +++ b/mm/vmalloc.c -@@ -3572,6 +3572,8 @@ static const struct seq_operations vmall +@@ -3962,6 +3962,8 @@ static const struct seq_operations vmall static int __init proc_vmalloc_init(void) { @@ -246,7 +246,7 @@ Signed-off-by: Felix Fietkau &vmalloc_op, --- a/mm/vmstat.c +++ b/mm/vmstat.c -@@ -2044,10 +2044,12 @@ void __init init_mm_internals(void) +@@ -2083,10 +2083,12 @@ void __init init_mm_internals(void) start_shepherd_timer(); #endif #ifdef CONFIG_PROC_FS @@ -286,7 +286,7 @@ Signed-off-by: Felix Fietkau goto err; --- a/net/core/net-procfs.c +++ b/net/core/net-procfs.c -@@ -320,10 +320,12 @@ static int __net_init dev_proc_net_init( +@@ -317,10 +317,12 @@ static int __net_init dev_proc_net_init( if (!proc_create_net("dev", 0444, net->proc_net, &dev_seq_ops, sizeof(struct seq_net_private))) goto out; @@ -301,7 +301,7 @@ Signed-off-by: Felix Fietkau sizeof(struct seq_net_private))) goto out_softnet; -@@ -333,9 +335,11 @@ static int __net_init dev_proc_net_init( +@@ -330,9 +332,11 @@ static int __net_init dev_proc_net_init( out: return rc; out_ptype: @@ -315,7 +315,7 @@ Signed-off-by: Felix Fietkau out_dev: remove_proc_entry("dev", net->proc_net); goto out; -@@ -345,8 +349,10 @@ static void __net_exit dev_proc_net_exit +@@ -342,8 +346,10 @@ static void __net_exit dev_proc_net_exit { wext_proc_exit(net); @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -3699,6 +3699,8 @@ static __net_initdata struct pernet_oper +@@ -3855,6 +3855,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { @@ -341,7 +341,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c -@@ -2986,11 +2986,13 @@ static const struct seq_operations fib_r +@@ -3019,11 +3019,13 @@ static const struct seq_operations fib_r int __net_init fib_proc_init(struct net *net) { @@ -357,7 +357,7 @@ Signed-off-by: Felix Fietkau fib_triestat_seq_show, NULL)) goto out2; -@@ -3001,17 +3003,21 @@ int __net_init fib_proc_init(struct net +@@ -3034,17 +3036,21 @@ int __net_init fib_proc_init(struct net return 0; out3: @@ -385,7 +385,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c -@@ -528,5 +528,8 @@ static __net_initdata struct pernet_oper +@@ -553,5 +553,8 @@ static __net_initdata struct pernet_oper int __init ip_misc_proc_init(void) { @@ -396,7 +396,7 @@ Signed-off-by: Felix Fietkau } --- a/net/ipv4/route.c +++ b/net/ipv4/route.c -@@ -410,6 +410,9 @@ static struct pernet_operations ip_rt_pr +@@ -387,6 +387,9 @@ static struct pernet_operations ip_rt_pr static int __init ip_rt_proc_init(void) { diff --git a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch index b2fdc0991e..fc7cd20963 100644 --- a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig -@@ -184,7 +184,7 @@ config SOC_BUS +@@ -187,7 +187,7 @@ config SOC_BUS source "drivers/base/regmap/Kconfig" config DMA_SHARED_BUFFER @@ -63,16 +63,16 @@ Signed-off-by: Felix Fietkau +dma-shared-buffer-objs := $(dma-buf-objs-y) --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c -@@ -1419,4 +1419,5 @@ static void __exit dma_buf_deinit(void) - dma_buf_uninit_debugfs(); +@@ -1498,4 +1498,5 @@ static void __exit dma_buf_deinit(void) kern_unmount(dma_buf_mnt); + dma_buf_uninit_sysfs_statistics(); } -__exitcall(dma_buf_deinit); +module_exit(dma_buf_deinit); +MODULE_LICENSE("GPL"); --- a/kernel/sched/core.c +++ b/kernel/sched/core.c -@@ -3065,6 +3065,7 @@ int wake_up_state(struct task_struct *p, +@@ -4174,6 +4174,7 @@ int wake_up_state(struct task_struct *p, { return try_to_wake_up(p, state, 0); } @@ -82,7 +82,7 @@ Signed-off-by: Felix Fietkau * Perform scheduler related setup for a newly forked process p. --- a/fs/d_path.c +++ b/fs/d_path.c -@@ -311,6 +311,7 @@ char *dynamic_dname(struct dentry *dentr +@@ -316,6 +316,7 @@ char *dynamic_dname(struct dentry *dentr buffer += buflen - sz; return memcpy(buffer, temp, sz); } diff --git a/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch b/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch index 27d4d7f1e5..287b85996d 100644 --- a/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch +++ b/target/linux/generic/hack-5.15/920-device_tree_cmdline.patch @@ -1,6 +1,6 @@ --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c -@@ -1055,6 +1055,9 @@ int __init early_init_dt_scan_chosen(uns +@@ -1158,6 +1158,9 @@ int __init early_init_dt_scan_chosen(uns p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); From 009f8afe06258adff30d83e936d097e42d5501ca Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 21 Mar 2022 15:22:20 +0100 Subject: [PATCH 22/26] generic: 5.15: refresh pending patch Use 'make target/linux/refresh' to refresh pending patches. Signed-off-by: Ansuel Smith --- ...include-asm-rwonce.h-for-kernel-code.patch | 8 ++-- ...s-negative-stack-offsets-on-stack-tr.patch | 2 +- ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 2 +- ...0-add-linux-spidev-compatible-si3210.patch | 2 +- ...ame2-and-add-RENAME_WHITEOUT-support.patch | 10 ++--- ...41-jffs2-add-RENAME_EXCHANGE-support.patch | 8 ++-- ...ge_allow_receiption_on_disabled_port.patch | 4 +- .../pending-5.15/201-extra_optimization.patch | 2 +- .../203-kallsyms_uncompressed.patch | 8 ++-- .../205-backtrace_module_info.patch | 4 +- .../270-platform-mikrotik-build-bits.patch | 4 +- .../300-mips_expose_boot_raw.patch | 2 +- .../pending-5.15/305-mips_module_reloc.patch | 11 +++--- .../307-mips_highmem_offset.patch | 2 +- .../pending-5.15/308-mips32r2_tune.patch | 2 +- ...t-command-line-parameters-from-users.patch | 4 +- ...ernel-XZ-compression-option-on-PPC_8.patch | 2 +- .../400-mtd-mtdsplit-support.patch | 12 +++--- ...support-for-minor-aligned-partitions.patch | 10 ++--- ...t-add-of_match_table-with-DT-binding.patch | 2 +- .../pending-5.15/420-mtd-redboot_space.patch | 4 +- ...mtd-add-routerbootpart-parser-config.patch | 4 +- ...mtd-cfi_cmdset_0002-no-erase_suspend.patch | 2 +- ...et_0002-add-buffer-write-cmd-timeout.patch | 2 +- ...ort-limiting-4K-sectors-support-base.patch | 10 ++--- .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 8 ++-- ...spinand-add-support-for-xtx-xt26g0xa.patch | 4 +- .../484-mtd-spi-nor-add-esmt-f25l16pa.patch | 2 +- ...mtd-device-named-ubi-or-data-on-boot.patch | 4 +- ...to-create-ubiblock-device-for-rootfs.patch | 4 +- ...ting-ubi0-rootfs-in-init-do_mounts.c.patch | 4 +- ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 4 +- .../494-mtd-ubi-add-EOF-marker-support.patch | 2 +- ...-mtd-core-add-get_mtd_device_by_node.patch | 4 +- ...cat-add-dt-driver-for-concat-devices.patch | 2 +- ...i-nor-locking-support-for-MX25L6405D.patch | 2 +- .../530-jffs2_make_lzma_available.patch | 6 +-- .../600-netfilter_conntrack_flush.patch | 4 +- ...-netfilter_optional_tcp_window_check.patch | 16 ++++---- .../pending-5.15/630-packet_socket_type.patch | 16 ++++---- .../pending-5.15/655-increase_skb_pad.patch | 2 +- ...Add-support-for-MAP-E-FMRs-mesh-mode.patch | 38 +++++++++---------- ...ng-with-source-address-failed-policy.patch | 32 ++++++++-------- ...nes-for-_POLICY_FAILED-until-all-cod.patch | 2 +- ...T-skip-GRO-for-foreign-MAC-addresses.patch | 26 ++++++------- ...et-add-mac-address-increment-support.patch | 2 +- ...83-of_net-add-mac-address-to-of-tree.patch | 6 +-- ..._eth_soc-avoid-creating-duplicate-of.patch | 6 +-- ...soc-add-ipv6-flow-offloading-support.patch | 12 +++--- ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 6 +-- ...detach-callback-to-struct-phy_driver.patch | 4 +- ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 24 ++++++------ ...760-net-dsa-mv88e6xxx-fix-vlan-setup.patch | 6 +-- ...equest-assisted-learning-on-CPU-port.patch | 6 +-- ...pio-cascade-add-generic-GPIO-cascade.patch | 8 ++-- .../810-pci_disable_common_quirks.patch | 10 ++--- .../811-pci_disable_usb_common_quirks.patch | 2 +- .../pending-5.15/834-ledtrig-libata.patch | 12 +++--- ...40-hwrng-bcm2835-set-quality-to-1000.patch | 2 +- ..._wwan-add-ZTE-MF286D-modem-19d2-1485.patch | 2 +- ...lace-custom-PCIE_CORE_INT_-macros-wi.patch | 4 +- ...ark-Fix-reading-MSI-interrupt-number.patch | 4 +- ...dvark-Fix-support-for-MSI-interrupts.patch | 6 +-- ...rite-IRQ-code-to-chained-IRQ-handler.patch | 12 +++--- ...ck-return-value-of-generic_handle_do.patch | 2 +- ...e-MSI-irq_chip-structures-static-dri.patch | 8 ++-- ...e-msi_domain_info-structure-a-static.patch | 6 +-- ...-dev_fwnode-instead-of-of_node_to_fw.patch | 4 +- ...actor-unmasking-summary-MSI-interrup.patch | 2 +- ...d-support-for-masking-MSI-interrupts.patch | 10 ++--- ...PCI-aardvark-Fix-setting-MSI-address.patch | 10 ++--- ...12-PCI-aardvark-Enable-MSI-X-support.patch | 2 +- ...-support-for-ERR-interrupt-on-emulat.patch | 8 ++-- ...-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch | 2 +- ...imize-writing-PCI_EXP_RTCTL_PMEIE-an.patch | 2 +- ...dvark-Add-support-for-PME-interrupts.patch | 2 +- ...-support-for-PME-requester-on-emulat.patch | 10 ++--- ...-separate-INTA-interrupt-for-emulate.patch | 14 +++---- ...ove-irq_mask_ack-callback-for-INTx-i.patch | 2 +- ...aardvark-Don-t-mask-irq-when-mapping.patch | 2 +- ...p-__maybe_unused-from-advk_pcie_disa.patch | 2 +- ...ate-comment-about-link-going-down-af.patch | 2 +- ...e-main-irq_chip-structure-a-static-d.patch | 8 ++-- ...ark-Fix-initialization-with-old-Marv.patch | 2 +- .../pending-5.15/920-mangle_bootargs.patch | 6 +-- 85 files changed, 272 insertions(+), 273 deletions(-) diff --git a/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch index 39b98eac1b..22f52c1d46 100644 --- a/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch +++ b/target/linux/generic/pending-5.15/100-compiler.h-only-include-asm-rwonce.h-for-kernel-code.patch @@ -11,16 +11,16 @@ Signed-off-by: Felix Fietkau --- a/include/linux/compiler.h +++ b/include/linux/compiler.h -@@ -211,6 +211,8 @@ void ftrace_likely_update(struct ftrace_ - __v; \ - }) +@@ -220,6 +220,8 @@ void ftrace_likely_update(struct ftrace_ + #define function_nocfi(x) (x) + #endif +#include + #endif /* __KERNEL__ */ /* -@@ -243,6 +245,4 @@ static inline void *offset_to_ptr(const +@@ -252,6 +254,4 @@ static inline void *offset_to_ptr(const */ #define prevent_tail_call_optimization() mb() diff --git a/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch b/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch index cc9f99e8b0..95a9656d26 100644 --- a/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch +++ b/target/linux/generic/pending-5.15/102-MIPS-only-process-negative-stack-offsets-on-stack-tr.patch @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c -@@ -380,6 +380,8 @@ static inline int is_sp_move_ins(union m +@@ -393,6 +393,8 @@ static inline int is_sp_move_ins(union m if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op) { diff --git a/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch index 0d1d3e1137..30c70a6be9 100644 --- a/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch +++ b/target/linux/generic/pending-5.15/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -71,7 +71,7 @@ Signed-off-by: Tobias Wolf --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7055,7 +7055,7 @@ static void __ref alloc_node_mem_map(str +@@ -7552,7 +7552,7 @@ static void __init alloc_node_mem_map(st if (pgdat == NODE_DATA(0)) { mem_map = NODE_DATA(0)->node_mem_map; if (page_to_pfn(mem_map) != pgdat->node_start_pfn) diff --git a/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch b/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch index ca7b8a6bb1..d260cf1f9a 100644 --- a/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch +++ b/target/linux/generic/pending-5.15/130-add-linux-spidev-compatible-si3210.patch @@ -8,7 +8,7 @@ Signed-off-by: Giuseppe Lippolis --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c -@@ -682,6 +682,7 @@ static const struct of_device_id spidev_ +@@ -696,6 +696,7 @@ static const struct of_device_id spidev_ { .compatible = "menlo,m53cpld" }, { .compatible = "cisco,spi-petra" }, { .compatible = "micron,spi-authenta" }, diff --git a/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch b/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch index 61e133e382..8f40ae3ba2 100644 --- a/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch +++ b/target/linux/generic/pending-5.15/140-jffs2-use-.rename2-and-add-RENAME_WHITEOUT-support.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c -@@ -609,8 +609,8 @@ static int jffs2_rmdir (struct inode *di +@@ -614,8 +614,8 @@ static int jffs2_rmdir (struct inode *di return ret; } @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau { struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; -@@ -748,7 +749,11 @@ static int jffs2_mknod (struct inode *di +@@ -754,7 +754,11 @@ static int jffs2_mknod (struct user_name mutex_unlock(&dir_f->sem); jffs2_complete_reservation(c); @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau return 0; fail: -@@ -756,6 +761,19 @@ static int jffs2_mknod (struct inode *di +@@ -762,6 +766,19 @@ static int jffs2_mknod (struct user_name return ret; } @@ -52,7 +52,7 @@ Signed-off-by: Felix Fietkau static int jffs2_rename (struct user_namespace *mnt_userns, struct inode *old_dir_i, struct dentry *old_dentry, struct inode *new_dir_i, struct dentry *new_dentry, -@@ -766,7 +782,7 @@ static int jffs2_rename (struct inode *o +@@ -773,7 +790,7 @@ static int jffs2_rename (struct user_nam uint8_t type; uint32_t now; @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau return -EINVAL; /* The VFS will check for us and prevent trying to rename a -@@ -832,9 +848,14 @@ static int jffs2_rename (struct inode *o +@@ -839,9 +856,14 @@ static int jffs2_rename (struct user_nam if (d_is_dir(old_dentry) && !victim_f) inc_nlink(new_dir_i); diff --git a/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch b/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch index 7dc830ac37..f58fc791d2 100644 --- a/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch +++ b/target/linux/generic/pending-5.15/141-jffs2-add-RENAME_EXCHANGE-support.patch @@ -6,7 +6,7 @@ Signed-off-by: Felix Fietkau --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c -@@ -779,18 +779,31 @@ static int jffs2_rename (struct inode *o +@@ -787,18 +787,31 @@ static int jffs2_rename (struct user_nam int ret; struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); struct jffs2_inode_info *victim_f = NULL; @@ -40,7 +40,7 @@ Signed-off-by: Felix Fietkau victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); if (d_is_dir(new_dentry)) { struct jffs2_full_dirent *fd; -@@ -825,7 +838,7 @@ static int jffs2_rename (struct inode *o +@@ -833,7 +846,7 @@ static int jffs2_rename (struct user_nam if (ret) return ret; @@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau /* There was a victim. Kill it off nicely */ if (d_is_dir(new_dentry)) clear_nlink(d_inode(new_dentry)); -@@ -851,6 +864,12 @@ static int jffs2_rename (struct inode *o +@@ -859,6 +872,12 @@ static int jffs2_rename (struct user_nam if (flags & RENAME_WHITEOUT) /* Replace with whiteout */ ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry); @@ -62,7 +62,7 @@ Signed-off-by: Felix Fietkau else /* Unlink the original */ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), -@@ -882,7 +901,7 @@ static int jffs2_rename (struct inode *o +@@ -890,7 +909,7 @@ static int jffs2_rename (struct user_nam return ret; } diff --git a/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch index 6de22b1c7d..2b9570e9a0 100644 --- a/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch +++ b/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -195,6 +195,9 @@ static void __br_handle_local_finish(str +@@ -197,6 +197,9 @@ static void __br_handle_local_finish(str /* note: already called with rcu_read_lock */ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau __br_handle_local_finish(skb); /* return 1 to signal the okfn() was called so it's ok to use the skb */ -@@ -348,6 +351,17 @@ static rx_handler_result_t br_handle_fra +@@ -362,6 +365,17 @@ static rx_handler_result_t br_handle_fra forward: switch (p->state) { diff --git a/target/linux/generic/pending-5.15/201-extra_optimization.patch b/target/linux/generic/pending-5.15/201-extra_optimization.patch index cb1de80764..5300a5c4ab 100644 --- a/target/linux/generic/pending-5.15/201-extra_optimization.patch +++ b/target/linux/generic/pending-5.15/201-extra_optimization.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -735,11 +735,11 @@ KBUILD_CFLAGS += $(call cc-disable-warni +@@ -752,11 +752,11 @@ KBUILD_CFLAGS += $(call cc-disable-warni KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE diff --git a/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch b/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch index 348a5afa3d..370fc97eac 100644 --- a/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch +++ b/target/linux/generic/pending-5.15/203-kallsyms_uncompressed.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/init/Kconfig +++ b/init/Kconfig -@@ -1384,6 +1384,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW +@@ -1438,6 +1438,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW the unaligned access emulation. see arch/parisc/kernel/unaligned.c for reference @@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c -@@ -77,6 +77,11 @@ static unsigned int kallsyms_expand_symb +@@ -80,6 +80,11 @@ static unsigned int kallsyms_expand_symb * For every byte on the compressed symbol data, copy the table * entry for that byte. */ @@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau while (len) { tptr = &kallsyms_token_table[kallsyms_token_index[*data]]; data++; -@@ -109,6 +114,9 @@ tail: +@@ -112,6 +117,9 @@ tail: */ static char kallsyms_get_symbol_type(unsigned int off) { @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau } --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh -@@ -186,6 +186,10 @@ kallsyms() +@@ -260,6 +260,10 @@ kallsyms() kallsymopt="${kallsymopt} --base-relative" fi diff --git a/target/linux/generic/pending-5.15/205-backtrace_module_info.patch b/target/linux/generic/pending-5.15/205-backtrace_module_info.patch index f46877f254..f10d863b8b 100644 --- a/target/linux/generic/pending-5.15/205-backtrace_module_info.patch +++ b/target/linux/generic/pending-5.15/205-backtrace_module_info.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/lib/vsprintf.c +++ b/lib/vsprintf.c -@@ -983,8 +983,10 @@ char *symbol_string(char *buf, char *end +@@ -984,8 +984,10 @@ char *symbol_string(char *buf, char *end struct printf_spec spec, const char *fmt) { unsigned long value; @@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau #endif if (fmt[1] == 'R') -@@ -1001,8 +1003,14 @@ char *symbol_string(char *buf, char *end +@@ -1006,8 +1008,14 @@ char *symbol_string(char *buf, char *end return string_nocheck(buf, end, sym, spec); #else diff --git a/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch b/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch index 3fd5c6e95d..99f83bb2c4 100644 --- a/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch +++ b/target/linux/generic/pending-5.15/270-platform-mikrotik-build-bits.patch @@ -16,7 +16,7 @@ Signed-off-by: Thibaut VARÈNE --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig -@@ -13,3 +13,5 @@ source "drivers/platform/chrome/Kconfig" +@@ -15,3 +15,5 @@ source "drivers/platform/mellanox/Kconfi source "drivers/platform/olpc/Kconfig" source "drivers/platform/surface/Kconfig" @@ -24,7 +24,7 @@ Signed-off-by: Thibaut VARÈNE +source "drivers/platform/mikrotik/Kconfig" --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile -@@ -9,3 +9,4 @@ obj-$(CONFIG_MIPS) += mips/ +@@ -10,3 +10,4 @@ obj-$(CONFIG_OLPC_EC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ diff --git a/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch b/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch index 706c5dee22..05d024925d 100644 --- a/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch +++ b/target/linux/generic/pending-5.15/300-mips_expose_boot_raw.patch @@ -9,7 +9,7 @@ Acked-by: Rob Landley --- --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -1085,9 +1085,6 @@ config FW_ARC +@@ -1100,9 +1100,6 @@ config FW_ARC config ARCH_MAY_HAVE_PC_FDC bool diff --git a/target/linux/generic/pending-5.15/305-mips_module_reloc.patch b/target/linux/generic/pending-5.15/305-mips_module_reloc.patch index 153c463ca0..bbea1f61c1 100644 --- a/target/linux/generic/pending-5.15/305-mips_module_reloc.patch +++ b/target/linux/generic/pending-5.15/305-mips_module_reloc.patch @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c -@@ -31,14 +31,221 @@ struct mips_hi16 { +@@ -31,23 +31,261 @@ struct mips_hi16 { static LIST_HEAD(dbe_list); static DEFINE_SPINLOCK(dbe_lock); @@ -267,9 +267,8 @@ Signed-off-by: Felix Fietkau + return 0; +} - static int apply_r_mips_none(struct module *me, u32 *location, - u32 base, Elf_Addr v, bool rela) -@@ -54,9 +261,40 @@ static int apply_r_mips_32(struct module + static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v) + { *location = base + v; } @@ -310,7 +309,7 @@ Signed-off-by: Felix Fietkau if (v % 4) { pr_err("module %s: dangerous R_MIPS_26 relocation\n", me->name); -@@ -64,13 +302,17 @@ static int apply_r_mips_26(struct module +@@ -55,13 +293,17 @@ static int apply_r_mips_26(struct module } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { @@ -332,7 +331,7 @@ Signed-off-by: Felix Fietkau return 0; } -@@ -446,9 +688,36 @@ int module_finalize(const Elf_Ehdr *hdr, +@@ -441,9 +683,36 @@ int module_finalize(const Elf_Ehdr *hdr, list_add(&me->arch.dbe_list, &dbe_list); spin_unlock_irq(&dbe_lock); } diff --git a/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch b/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch index e1ada22f34..0529b0c5c8 100644 --- a/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch +++ b/target/linux/generic/pending-5.15/307-mips_highmem_offset.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/arch/mips/include/asm/mach-generic/spaces.h +++ b/arch/mips/include/asm/mach-generic/spaces.h -@@ -54,7 +54,7 @@ +@@ -46,7 +46,7 @@ * Memory above this physical address will be considered highmem. */ #ifndef HIGHMEM_START diff --git a/target/linux/generic/pending-5.15/308-mips32r2_tune.patch b/target/linux/generic/pending-5.15/308-mips32r2_tune.patch index bbea947382..ef92a5dfb6 100644 --- a/target/linux/generic/pending-5.15/308-mips32r2_tune.patch +++ b/target/linux/generic/pending-5.15/308-mips32r2_tune.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/arch/mips/Makefile +++ b/arch/mips/Makefile -@@ -174,7 +174,7 @@ cflags-$(CONFIG_CPU_VR41XX) += -march=r4 +@@ -175,7 +175,7 @@ cflags-$(CONFIG_CPU_VR41XX) += -march=r4 cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap diff --git a/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch index 91e4b91149..3a5f5a238d 100644 --- a/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch +++ b/target/linux/generic/pending-5.15/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch @@ -251,7 +251,7 @@ Signed-off-by: Yousong Zhou PTR_L a0, arg0 PTR_L a1, arg1 PTR_L a2, arg2 -@@ -96,7 +97,7 @@ done: +@@ -98,7 +99,7 @@ done: #endif /* jump to kexec_start_address */ j s1 @@ -260,7 +260,7 @@ Signed-off-by: Yousong Zhou #ifdef CONFIG_SMP /* -@@ -182,9 +183,15 @@ kexec_indirection_page: +@@ -181,9 +182,15 @@ kexec_indirection_page: PTR_WD 0 .size kexec_indirection_page, PTRSIZE diff --git a/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch b/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch index 6792a66f8a..cb9f295288 100644 --- a/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch +++ b/target/linux/generic/pending-5.15/342-powerpc-Enable-kernel-XZ-compression-option-on-PPC_8.patch @@ -14,7 +14,7 @@ Signed-off-by: Pawel Dembicki --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig -@@ -214,7 +214,7 @@ config PPC +@@ -222,7 +222,7 @@ config PPC select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE select HAVE_KERNEL_LZO if DEFAULT_UIMAGE diff --git a/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch index 6f816a6ad3..18f26d9941 100644 --- a/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch +++ b/target/linux/generic/pending-5.15/400-mtd-mtdsplit-support.patch @@ -41,7 +41,7 @@ /* * MTD methods which simply translate the effective address and pass through -@@ -236,6 +238,146 @@ static int mtd_add_partition_attrs(struc +@@ -235,6 +237,146 @@ static int mtd_add_partition_attrs(struc return ret; } @@ -188,7 +188,7 @@ int mtd_add_partition(struct mtd_info *parent, const char *name, long long offset, long long length) { -@@ -274,6 +416,7 @@ int mtd_add_partition(struct mtd_info *p +@@ -273,6 +415,7 @@ int mtd_add_partition(struct mtd_info *p if (ret) goto err_remove_part; @@ -196,7 +196,7 @@ mtd_add_partition_attrs(child); return 0; -@@ -422,6 +565,7 @@ int add_mtd_partitions(struct mtd_info * +@@ -421,6 +564,7 @@ int add_mtd_partitions(struct mtd_info * goto err_del_partitions; } @@ -204,7 +204,7 @@ mtd_add_partition_attrs(child); /* Look for subpartitions */ -@@ -438,31 +582,6 @@ err_del_partitions: +@@ -437,31 +581,6 @@ err_del_partitions: return ret; } @@ -272,7 +272,7 @@ obj-$(CONFIG_MTD_BLOCK) += mtdblock.o --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h -@@ -608,6 +608,24 @@ static inline void mtd_align_erase_req(s +@@ -615,6 +615,24 @@ static inline void mtd_align_erase_req(s req->len += mtd->erasesize - mod; } @@ -297,7 +297,7 @@ static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) { if (mtd->writesize_shift) -@@ -680,6 +698,13 @@ extern void __put_mtd_device(struct mtd_ +@@ -687,6 +705,13 @@ extern void __put_mtd_device(struct mtd_ extern struct mtd_info *get_mtd_device_nm(const char *name); extern void put_mtd_device(struct mtd_info *mtd); diff --git a/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch b/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch index eaf96e9534..58c33bcd69 100644 --- a/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch +++ b/target/linux/generic/pending-5.15/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch @@ -338,7 +338,7 @@ Reported-by: Dan Carpenter default y --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c -@@ -1075,6 +1075,8 @@ static u8 spi_nor_convert_3to4_erase(u8 +@@ -1262,6 +1262,8 @@ static u8 spi_nor_convert_3to4_erase(u8 static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) { @@ -347,7 +347,7 @@ Reported-by: Dan Carpenter return !!nor->params->erase_map.uniform_erase_type; } -@@ -2560,6 +2562,7 @@ static int spi_nor_select_erase(struct s +@@ -2379,6 +2381,7 @@ static int spi_nor_select_erase(struct s { struct spi_nor_erase_map *map = &nor->params->erase_map; const struct spi_nor_erase_type *erase = NULL; @@ -355,7 +355,7 @@ Reported-by: Dan Carpenter struct mtd_info *mtd = &nor->mtd; u32 wanted_size = nor->info->sector_size; int i; -@@ -2592,8 +2595,9 @@ static int spi_nor_select_erase(struct s +@@ -2411,8 +2414,9 @@ static int spi_nor_select_erase(struct s */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { if (map->erase_type[i].size) { @@ -367,7 +367,7 @@ Reported-by: Dan Carpenter } } -@@ -2601,6 +2605,8 @@ static int spi_nor_select_erase(struct s +@@ -2420,6 +2424,8 @@ static int spi_nor_select_erase(struct s return -EINVAL; mtd->erasesize = erase->size; @@ -378,7 +378,7 @@ Reported-by: Dan Carpenter --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h -@@ -242,6 +242,8 @@ struct mtd_info { +@@ -243,6 +243,8 @@ struct mtd_info { * information below if they desire */ uint32_t erasesize; diff --git a/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch b/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch index 7692f484ae..3d176f8563 100644 --- a/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch +++ b/target/linux/generic/pending-5.15/419-mtd-redboot-add-of_match_table-with-DT-binding.patch @@ -12,7 +12,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/mtd/parsers/redboot.c +++ b/drivers/mtd/parsers/redboot.c -@@ -305,6 +305,7 @@ static int parse_redboot_partitions(stru +@@ -304,6 +304,7 @@ nogood: static const struct of_device_id mtd_parser_redboot_of_match_table[] = { { .compatible = "redboot-fis" }, diff --git a/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch index 2673d720e5..fee1936593 100644 --- a/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch +++ b/target/linux/generic/pending-5.15/420-mtd-redboot_space.patch @@ -11,9 +11,9 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/parsers/redboot.c +++ b/drivers/mtd/parsers/redboot.c -@@ -279,14 +279,21 @@ static int parse_redboot_partitions(stru +@@ -277,14 +277,21 @@ nogood: #endif - names += strlen(names)+1; + names += strlen(names) + 1; -#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED if (fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { diff --git a/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch index b258256db6..721a4d3a5d 100644 --- a/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch +++ b/target/linux/generic/pending-5.15/435-mtd-add-routerbootpart-parser-config.patch @@ -16,7 +16,7 @@ Signed-off-by: Thibaut VARÈNE --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig -@@ -195,3 +195,12 @@ config MTD_REDBOOT_PARTS_READONLY +@@ -202,3 +202,12 @@ config MTD_QCOMSMEM_PARTS help This provides support for parsing partitions from Shared Memory (SMEM) for NAND and SPI flash on Qualcomm platforms. @@ -31,7 +31,7 @@ Signed-off-by: Thibaut VARÈNE + formatted DTS. --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile -@@ -13,3 +13,4 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o +@@ -14,3 +14,4 @@ obj-$(CONFIG_MTD_PARSER_TRX) += parser_ obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o diff --git a/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch index 9983971af5..cb7768a5e7 100644 --- a/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch +++ b/target/linux/generic/pending-5.15/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -913,7 +913,7 @@ static int get_chip(struct map_info *map +@@ -914,7 +914,7 @@ static int get_chip(struct map_info *map return 0; case FL_ERASING: diff --git a/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch index 0bda2ed971..bedd53ccba 100644 --- a/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch +++ b/target/linux/generic/pending-5.15/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch @@ -7,7 +7,7 @@ Signed-off-by: George Kashperko 1 file changed, 1 insertion(+) --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -2057,6 +2057,7 @@ static int __xipram do_write_buffer(stru +@@ -2058,6 +2058,7 @@ static int __xipram do_write_buffer(stru /* Write Buffer Load */ map_write(map, CMD(0x25), cmd_adr); diff --git a/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch index 2748192dd2..308eca72c4 100644 --- a/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +++ b/target/linux/generic/pending-5.15/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch @@ -19,9 +19,9 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig -@@ -34,6 +34,17 @@ config MTD_SPI_NOR_USE_4K_SECTORS - Please note that some tools/drivers/filesystems may not work with - 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). +@@ -78,6 +78,17 @@ config MTD_SPI_NOR_SWP_KEEP + + endchoice +config MTD_SPI_NOR_USE_4K_SECTORS_LIMIT + int "Maximum flash chip size to use 4K sectors on (in KiB)" @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau endif # MTD_SPI_NOR --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c -@@ -2792,6 +2792,21 @@ static void spi_nor_info_init_params(str +@@ -2631,6 +2631,21 @@ static void spi_nor_info_init_params(str */ erase_mask = 0; i = 0; @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau if (info->flags & SECT_4K_PMC) { erase_mask |= BIT(i); spi_nor_set_erase_type(&map->erase_type[i], 4096u, -@@ -2803,6 +2818,7 @@ static void spi_nor_info_init_params(str +@@ -2642,6 +2657,7 @@ static void spi_nor_info_init_params(str SPINOR_OP_BE_4K); i++; } diff --git a/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch index 796bf6becb..c3c59d43bf 100644 --- a/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch +++ b/target/linux/generic/pending-5.15/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -59,7 +59,7 @@ Signed-off-by: Felix Fietkau +}; --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c -@@ -2028,6 +2028,7 @@ static const struct spi_nor_manufacturer +@@ -1848,6 +1848,7 @@ static const struct spi_nor_manufacturer &spi_nor_winbond, &spi_nor_xilinx, &spi_nor_xmc, @@ -69,11 +69,11 @@ Signed-off-by: Felix Fietkau static const struct flash_info * --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h -@@ -398,6 +398,7 @@ extern const struct spi_nor_manufacturer +@@ -489,6 +489,7 @@ extern const struct spi_nor_manufacturer extern const struct spi_nor_manufacturer spi_nor_winbond; extern const struct spi_nor_manufacturer spi_nor_xilinx; extern const struct spi_nor_manufacturer spi_nor_xmc; +extern const struct spi_nor_manufacturer spi_nor_xtx; - int spi_nor_write_enable(struct spi_nor *nor); - int spi_nor_write_disable(struct spi_nor *nor); + extern const struct attribute_group *spi_nor_sysfs_groups[]; + diff --git a/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch b/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch index 11590770cd..4672f8c86a 100644 --- a/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch +++ b/target/linux/generic/pending-5.15/483-mtd-spinand-add-support-for-xtx-xt26g0xa.patch @@ -33,7 +33,7 @@ Signed-off-by: Felix Matouschek obj-$(CONFIG_MTD_SPI_NAND) += spinand.o --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -760,6 +760,7 @@ static const struct spinand_manufacturer +@@ -902,6 +902,7 @@ static const struct spinand_manufacturer ¶gon_spinand_manufacturer, &toshiba_spinand_manufacturer, &winbond_spinand_manufacturer, @@ -168,7 +168,7 @@ Signed-off-by: Felix Matouschek +}; --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h -@@ -244,6 +244,7 @@ extern const struct spinand_manufacturer +@@ -266,6 +266,7 @@ extern const struct spinand_manufacturer extern const struct spinand_manufacturer paragon_spinand_manufacturer; extern const struct spinand_manufacturer toshiba_spinand_manufacturer; extern const struct spinand_manufacturer winbond_spinand_manufacturer; diff --git a/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch b/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch index ce3857d511..b2f0b92a18 100644 --- a/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch +++ b/target/linux/generic/pending-5.15/484-mtd-spi-nor-add-esmt-f25l16pa.patch @@ -7,5 +7,5 @@ + { "f25l16pa-2s", INFO(0x8c2115, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_HAS_LOCK) }, { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, - SECT_4K | SPI_NOR_HAS_LOCK) }, + SECT_4K | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) }, { "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, diff --git a/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch index 7c9766fa7b..393308f717 100644 --- a/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch +++ b/target/linux/generic/pending-5.15/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c -@@ -1192,6 +1192,73 @@ static struct mtd_info * __init open_mtd +@@ -1191,6 +1191,73 @@ static struct mtd_info * __init open_mtd return mtd; } @@ -82,7 +82,7 @@ Signed-off-by: Daniel Golle static int __init ubi_init(void) { int err, i, k; -@@ -1275,6 +1342,12 @@ static int __init ubi_init(void) +@@ -1274,6 +1341,12 @@ static int __init ubi_init(void) } } diff --git a/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch index a2b48fd4fc..ae53770c11 100644 --- a/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch +++ b/target/linux/generic/pending-5.15/491-ubi-auto-create-ubiblock-device-for-rootfs.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -652,6 +652,47 @@ static void __init ubiblock_create_from_ +@@ -642,6 +642,47 @@ static void __init ubiblock_create_from_ } } @@ -56,7 +56,7 @@ Signed-off-by: Daniel Golle static void ubiblock_remove_all(void) { struct ubiblock *next; -@@ -684,6 +725,10 @@ int __init ubiblock_init(void) +@@ -674,6 +715,10 @@ int __init ubiblock_init(void) */ ubiblock_create_from_param(); diff --git a/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch index 0efff2b52f..cf41c8cad3 100644 --- a/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +++ b/target/linux/generic/pending-5.15/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/init/do_mounts.c +++ b/init/do_mounts.c -@@ -474,7 +474,30 @@ retry: +@@ -447,7 +447,30 @@ retry: out: put_page(page); } @@ -40,7 +40,7 @@ Signed-off-by: Daniel Golle #ifdef CONFIG_ROOT_NFS #define NFSROOT_TIMEOUT_MIN 5 -@@ -567,6 +590,10 @@ void __init mount_root(void) +@@ -580,6 +603,10 @@ void __init mount_root(void) return; } #endif diff --git a/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch index 2dff46807e..266a6331c2 100644 --- a/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +++ b/target/linux/generic/pending-5.15/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle #include "ubi-media.h" #include "ubi.h" -@@ -458,6 +459,15 @@ int ubiblock_create(struct ubi_volume_in +@@ -451,6 +452,15 @@ int ubiblock_create(struct ubi_volume_in dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", dev->ubi_num, dev->vol_id, vi->name); mutex_unlock(&devices_mutex); @@ -31,4 +31,4 @@ Signed-off-by: Daniel Golle + return 0; - out_free_queue: + out_remove_minor: diff --git a/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch b/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch index 81d32ca5a5..fc48146221 100644 --- a/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch +++ b/target/linux/generic/pending-5.15/494-mtd-ubi-add-EOF-marker-support.patch @@ -50,7 +50,7 @@ Signed-off-by: Gabor Juhos break; --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h -@@ -782,6 +782,7 @@ struct ubi_attach_info { +@@ -780,6 +780,7 @@ struct ubi_attach_info { int mean_ec; uint64_t ec_sum; int ec_count; diff --git a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch index d5db5fdd54..45fbcf7658 100644 --- a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch +++ b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch @@ -17,7 +17,7 @@ Reviewed-by: Miquel Raynal --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -1046,6 +1046,44 @@ out_unlock: +@@ -1203,6 +1203,44 @@ out_unlock: } EXPORT_SYMBOL_GPL(get_mtd_device_nm); @@ -64,7 +64,7 @@ Reviewed-by: Miquel Raynal mutex_lock(&mtd_table_mutex); --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h -@@ -698,6 +698,8 @@ extern struct mtd_info *get_mtd_device(s +@@ -705,6 +705,8 @@ extern struct mtd_info *get_mtd_device(s extern int __get_mtd_device(struct mtd_info *mtd); extern void __put_mtd_device(struct mtd_info *mtd); extern struct mtd_info *get_mtd_device_nm(const char *name); diff --git a/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch index 058cab09e5..321680154d 100644 --- a/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch +++ b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch @@ -43,7 +43,7 @@ Signed-off-by: Bernhard Frauendienst --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig -@@ -238,4 +238,6 @@ source "drivers/mtd/ubi/Kconfig" +@@ -241,4 +241,6 @@ source "drivers/mtd/ubi/Kconfig" source "drivers/mtd/hyperbus/Kconfig" diff --git a/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch b/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch index 62e977c8d1..81de764876 100644 --- a/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch +++ b/target/linux/generic/pending-5.15/498-mtd-spi-nor-locking-support-for-MX25L6405D.patch @@ -22,7 +22,7 @@ Signed-off-by: Nick Hainke --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c -@@ -42,7 +42,8 @@ static const struct flash_info macronix_ +@@ -41,7 +41,8 @@ static const struct flash_info macronix_ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, diff --git a/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch index a648b6c545..80c8110a82 100644 --- a/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch +++ b/target/linux/generic/pending-5.15/530-jffs2_make_lzma_available.patch @@ -1087,7 +1087,7 @@ Signed-off-by: Alexandros C. Couloumbis #define JFFS2_NODE_ACCURATE 0x2000 --- a/lib/Kconfig +++ b/lib/Kconfig -@@ -315,6 +315,12 @@ config ZSTD_DECOMPRESS +@@ -335,6 +335,12 @@ config ZSTD_DECOMPRESS source "lib/xz/Kconfig" @@ -1102,7 +1102,7 @@ Signed-off-by: Alexandros C. Couloumbis # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) --- a/lib/Makefile +++ b/lib/Makefile -@@ -136,6 +136,16 @@ CFLAGS_kobject.o += -DDEBUG +@@ -135,6 +135,16 @@ CFLAGS_kobject.o += -DDEBUG CFLAGS_kobject_uevent.o += -DDEBUG endif @@ -1119,7 +1119,7 @@ Signed-off-by: Alexandros C. Couloumbis obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any) -@@ -191,6 +201,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ +@@ -192,6 +202,8 @@ obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/ obj-$(CONFIG_XZ_DEC) += xz/ obj-$(CONFIG_RAID6_PQ) += raid6/ diff --git a/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch b/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch index ab6953e557..a88e3d7d9a 100644 --- a/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch +++ b/target/linux/generic/pending-5.15/600-netfilter_conntrack_flush.patch @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau #include #ifdef CONFIG_SYSCTL #include -@@ -457,6 +458,56 @@ static int ct_cpu_seq_show(struct seq_fi +@@ -462,6 +463,56 @@ static int ct_cpu_seq_show(struct seq_fi return 0; } @@ -74,7 +74,7 @@ Signed-off-by: Felix Fietkau static const struct seq_operations ct_cpu_seq_ops = { .start = ct_cpu_seq_start, .next = ct_cpu_seq_next, -@@ -470,8 +521,9 @@ static int nf_conntrack_standalone_init_ +@@ -475,8 +526,9 @@ static int nf_conntrack_standalone_init_ kuid_t root_uid; kgid_t root_gid; diff --git a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch index c7978e5881..249c3c8a82 100644 --- a/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch +++ b/target/linux/generic/pending-5.15/613-netfilter_optional_tcp_window_check.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -476,6 +479,9 @@ static bool tcp_in_window(const struct n +@@ -465,6 +465,9 @@ static bool tcp_in_window(struct nf_conn s32 receiver_offset; bool res, in_recv_win; @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau /* * Get the required data from the packet. */ -@@ -1130,7 +1136,7 @@ int nf_conntrack_tcp_packet(struct nf_co +@@ -1151,7 +1154,7 @@ int nf_conntrack_tcp_packet(struct nf_co IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) timeout = timeouts[TCP_CONNTRACK_UNACK]; @@ -29,16 +29,16 @@ Signed-off-by: Felix Fietkau else --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c -@@ -660,6 +663,7 @@ enum nf_ct_sysctl_index { - NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM, +@@ -671,6 +671,7 @@ enum nf_ct_sysctl_index { + NF_SYSCTL_CT_LWTUNNEL, #endif + NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK, __NF_SYSCTL_CT_LAST_SYSCTL, }; -@@ -1014,6 +1018,13 @@ static struct ctl_table nf_ct_sysctl_tab - .proc_handler = proc_dointvec_jiffies, +@@ -1026,6 +1027,13 @@ static struct ctl_table nf_ct_sysctl_tab + .proc_handler = nf_hooks_lwtunnel_sysctl_handler, }, #endif + [NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK] = { @@ -51,7 +51,7 @@ Signed-off-by: Felix Fietkau {} }; -@@ -1164,6 +1164,7 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) +@@ -1153,6 +1161,7 @@ static int nf_conntrack_standalone_init_ #ifdef CONFIG_NF_CONNTRACK_EVENTS table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events; #endif @@ -59,7 +59,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp; #endif -@@ -1220,6 +1220,7 @@ +@@ -1222,6 +1231,7 @@ static int nf_conntrack_pernet_init(stru int ret; net->ct.sysctl_checksum = 1; diff --git a/target/linux/generic/pending-5.15/630-packet_socket_type.patch b/target/linux/generic/pending-5.15/630-packet_socket_type.patch index 5b396c3a8c..70f07baebb 100644 --- a/target/linux/generic/pending-5.15/630-packet_socket_type.patch +++ b/target/linux/generic/pending-5.15/630-packet_socket_type.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #define PACKET_FANOUT_LB 1 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c -@@ -1822,6 +1822,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1825,6 +1825,7 @@ static int packet_rcv_spkt(struct sk_buf { struct sock *sk; struct sockaddr_pkt *spkt; @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau /* * When we registered the protocol we saved the socket in the data -@@ -1829,6 +1830,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1832,6 +1833,7 @@ static int packet_rcv_spkt(struct sk_buf */ sk = pt->af_packet_priv; @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau /* * Yank back the headers [hope the device set this -@@ -1841,7 +1843,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1844,7 +1846,7 @@ static int packet_rcv_spkt(struct sk_buf * so that this procedure is noop. */ @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau goto out; if (!net_eq(dev_net(dev), sock_net(sk))) -@@ -2079,12 +2081,12 @@ static int packet_rcv(struct sk_buff *sk +@@ -2082,12 +2084,12 @@ static int packet_rcv(struct sk_buff *sk unsigned int snaplen, res; bool is_drop_n_account = false; @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -2210,12 +2212,12 @@ static int tpacket_rcv(struct sk_buff *s +@@ -2213,12 +2215,12 @@ static int tpacket_rcv(struct sk_buff *s BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau if (sock->type == SOCK_PACKET) po->prot_hook.func = packet_rcv_spkt; -@@ -3969,6 +3972,16 @@ packet_setsockopt(struct socket *sock, i +@@ -3966,6 +3969,16 @@ packet_setsockopt(struct socket *sock, i po->xmit = val ? packet_direct_xmit : dev_queue_xmit; return 0; } @@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau default: return -ENOPROTOOPT; } -@@ -4025,6 +4038,13 @@ static int packet_getsockopt(struct sock +@@ -4022,6 +4035,13 @@ static int packet_getsockopt(struct sock case PACKET_VNET_HDR: val = po->has_vnet_hdr; break; @@ -135,4 +135,4 @@ Signed-off-by: Felix Fietkau + unsigned int pkt_type; }; - static struct packet_sock *pkt_sk(struct sock *sk) + static inline struct packet_sock *pkt_sk(struct sock *sk) diff --git a/target/linux/generic/pending-5.15/655-increase_skb_pad.patch b/target/linux/generic/pending-5.15/655-increase_skb_pad.patch index ff39ddb8b3..bb2c995e68 100644 --- a/target/linux/generic/pending-5.15/655-increase_skb_pad.patch +++ b/target/linux/generic/pending-5.15/655-increase_skb_pad.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2676,7 +2676,7 @@ static inline int pskb_network_may_pull( +@@ -2727,7 +2727,7 @@ static inline int pskb_network_may_pull( * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) */ #ifndef NET_SKB_PAD diff --git a/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index 89eb7d61b3..09efa1e72f 100644 --- a/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/target/linux/generic/pending-5.15/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -91,7 +91,7 @@ Signed-off-by: Steven Barth return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT); } -@@ -144,17 +147,33 @@ static struct ip6_tnl * +@@ -114,17 +117,33 @@ static struct ip6_tnl * ip6_tnl_lookup(struct net *net, int link, const struct in6_addr *remote, const struct in6_addr *local) { @@ -127,7 +127,7 @@ Signed-off-by: Steven Barth if (link == t->parms.link) return t; else -@@ -162,7 +181,7 @@ ip6_tnl_lookup(struct net *net, int link +@@ -132,7 +151,7 @@ ip6_tnl_lookup(struct net *net, int link } memset(&any, 0, sizeof(any)); @@ -136,7 +136,7 @@ Signed-off-by: Steven Barth for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { if (!ipv6_addr_equal(local, &t->parms.laddr) || !ipv6_addr_any(&t->parms.raddr) || -@@ -175,7 +194,7 @@ ip6_tnl_lookup(struct net *net, int link +@@ -145,7 +164,7 @@ ip6_tnl_lookup(struct net *net, int link cand = t; } @@ -145,7 +145,7 @@ Signed-off-by: Steven Barth for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { if (!ipv6_addr_equal(remote, &t->parms.raddr) || !ipv6_addr_any(&t->parms.laddr) || -@@ -223,7 +242,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, +@@ -194,7 +213,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { prio = 1; @@ -154,7 +154,7 @@ Signed-off-by: Steven Barth } return &ip6n->tnls[prio][h]; } -@@ -405,6 +424,12 @@ ip6_tnl_dev_uninit(struct net_device *de +@@ -378,6 +397,12 @@ ip6_tnl_dev_uninit(struct net_device *de struct net *net = t->net; struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); @@ -167,7 +167,7 @@ Signed-off-by: Steven Barth if (dev == ip6n->fb_tnl_dev) RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); else -@@ -821,6 +846,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, +@@ -790,6 +815,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, } EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl); @@ -275,7 +275,7 @@ Signed-off-by: Steven Barth static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst, -@@ -873,6 +999,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl +@@ -843,6 +969,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl skb_reset_network_header(skb); memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); @@ -303,7 +303,7 @@ Signed-off-by: Steven Barth __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); err = dscp_ecn_decapsulate(tunnel, ipv6h, skb); -@@ -1024,6 +1171,7 @@ static void init_tel_txopt(struct ipv6_t +@@ -994,6 +1141,7 @@ static void init_tel_txopt(struct ipv6_t opt->ops.opt_nflen = 8; } @@ -311,7 +311,7 @@ Signed-off-by: Steven Barth /** * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own * @t: the outgoing tunnel device -@@ -1304,6 +1452,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str +@@ -1274,6 +1422,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str u8 protocol) { struct ip6_tnl *t = netdev_priv(dev); @@ -319,7 +319,7 @@ Signed-off-by: Steven Barth struct ipv6hdr *ipv6h; const struct iphdr *iph; int encap_limit = -1; -@@ -1403,6 +1552,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str +@@ -1373,6 +1522,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield); @@ -338,7 +338,7 @@ Signed-off-by: Steven Barth if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; -@@ -1555,6 +1716,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1525,6 +1686,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.link = p->link; t->parms.proto = p->proto; t->parms.fwmark = p->fwmark; @@ -353,7 +353,7 @@ Signed-off-by: Steven Barth dst_cache_reset(&t->dst_cache); ip6_tnl_link_config(t); return 0; -@@ -1593,6 +1762,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ +@@ -1563,6 +1732,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ p->flowinfo = u->flowinfo; p->link = u->link; p->proto = u->proto; @@ -361,7 +361,7 @@ Signed-off-by: Steven Barth memcpy(p->name, u->name, sizeof(u->name)); } -@@ -1978,6 +2148,15 @@ static int ip6_tnl_validate(struct nlatt +@@ -1949,6 +2119,15 @@ static int ip6_tnl_validate(struct nlatt return 0; } @@ -377,7 +377,7 @@ Signed-off-by: Steven Barth static void ip6_tnl_netlink_parms(struct nlattr *data[], struct __ip6_tnl_parm *parms) { -@@ -2015,6 +2194,46 @@ static void ip6_tnl_netlink_parms(struct +@@ -1986,6 +2165,46 @@ static void ip6_tnl_netlink_parms(struct if (data[IFLA_IPTUN_FWMARK]) parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); @@ -424,7 +424,7 @@ Signed-off-by: Steven Barth } static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], -@@ -2130,6 +2349,12 @@ static void ip6_tnl_dellink(struct net_d +@@ -2101,6 +2320,12 @@ static void ip6_tnl_dellink(struct net_d static size_t ip6_tnl_get_size(const struct net_device *dev) { @@ -437,7 +437,7 @@ Signed-off-by: Steven Barth return /* IFLA_IPTUN_LINK */ nla_total_size(4) + -@@ -2159,6 +2384,24 @@ static size_t ip6_tnl_get_size(const str +@@ -2130,6 +2355,24 @@ static size_t ip6_tnl_get_size(const str nla_total_size(0) + /* IFLA_IPTUN_FWMARK */ nla_total_size(4) + @@ -462,7 +462,7 @@ Signed-off-by: Steven Barth 0; } -@@ -2166,6 +2409,9 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2137,6 +2380,9 @@ static int ip6_tnl_fill_info(struct sk_b { struct ip6_tnl *tunnel = netdev_priv(dev); struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -472,7 +472,7 @@ Signed-off-by: Steven Barth if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -@@ -2175,9 +2421,27 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2146,9 +2392,27 @@ static int ip6_tnl_fill_info(struct sk_b nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || @@ -501,7 +501,7 @@ Signed-off-by: Steven Barth if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || -@@ -2217,6 +2481,7 @@ static const struct nla_policy ip6_tnl_p +@@ -2188,6 +2452,7 @@ static const struct nla_policy ip6_tnl_p [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index f3e7eae0ea..3fb053ab49 100644 --- a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -20,7 +20,7 @@ Signed-off-by: Jonas Gorski --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h -@@ -88,6 +88,7 @@ struct netns_ipv6 { +@@ -85,6 +85,7 @@ struct netns_ipv6 { unsigned int fib6_routes_require_src; #endif struct rt6_info *ip6_prohibit_entry; @@ -43,7 +43,7 @@ Signed-off-by: Jonas Gorski --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h -@@ -249,6 +249,7 @@ enum { +@@ -256,6 +256,7 @@ enum { RTN_THROW, /* Not in this table */ RTN_NAT, /* Translate this address */ RTN_XRESOLVE, /* Use external resolver */ @@ -66,7 +66,7 @@ Signed-off-by: Jonas Gorski static void rt_fibinfo_free(struct rtable __rcu **rtp) --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c -@@ -2734,6 +2734,7 @@ static const char *const rtn_type_names[ +@@ -2767,6 +2767,7 @@ static const char *const rtn_type_names[ [RTN_THROW] = "THROW", [RTN_NAT] = "NAT", [RTN_XRESOLVE] = "XRESOLVE", @@ -110,7 +110,7 @@ Signed-off-by: Jonas Gorski return -EINVAL; --- a/net/ipv6/route.c +++ b/net/ipv6/route.c -@@ -94,6 +94,8 @@ static int ip6_pkt_discard(struct sk_bu +@@ -97,6 +97,8 @@ static int ip6_pkt_discard(struct sk_bu static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); static int ip6_pkt_prohibit(struct sk_buff *skb); static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb); @@ -119,7 +119,7 @@ Signed-off-by: Jonas Gorski static void ip6_link_failure(struct sk_buff *skb); static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, -@@ -309,6 +311,18 @@ static const struct rt6_info ip6_prohibi +@@ -312,6 +314,18 @@ static const struct rt6_info ip6_prohibi .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), }; @@ -138,7 +138,7 @@ Signed-off-by: Jonas Gorski static const struct rt6_info ip6_blk_hole_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), -@@ -1030,6 +1044,7 @@ static const int fib6_prop[RTN_MAX + 1] +@@ -1033,6 +1047,7 @@ static const int fib6_prop[RTN_MAX + 1] [RTN_BLACKHOLE] = -EINVAL, [RTN_UNREACHABLE] = -EHOSTUNREACH, [RTN_PROHIBIT] = -EACCES, @@ -146,7 +146,7 @@ Signed-off-by: Jonas Gorski [RTN_THROW] = -EAGAIN, [RTN_NAT] = -EINVAL, [RTN_XRESOLVE] = -EINVAL, -@@ -1065,6 +1080,10 @@ static void ip6_rt_init_dst_reject(struc +@@ -1068,6 +1083,10 @@ static void ip6_rt_init_dst_reject(struc rt->dst.output = ip6_pkt_prohibit_out; rt->dst.input = ip6_pkt_prohibit; break; @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4448,6 +4467,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4559,6 +4578,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -4928,7 +4958,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5039,7 +5069,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6127,6 +6158,8 @@ static int ip6_route_dev_notify(struct n +@@ -6292,6 +6323,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6138,6 +6171,7 @@ static int ip6_route_dev_notify(struct n +@@ -6303,6 +6336,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6329,6 +6363,8 @@ static int __net_init ip6_route_net_init +@@ -6494,6 +6528,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6339,11 +6375,21 @@ static int __net_init ip6_route_net_init +@@ -6504,11 +6540,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6370,6 +6416,8 @@ out: +@@ -6535,6 +6581,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6389,6 +6437,7 @@ static void __net_exit ip6_route_net_exi +@@ -6554,6 +6602,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6466,6 +6515,9 @@ void __init ip6_route_init_special_entri +@@ -6631,6 +6680,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch b/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch index 0e7f35db89..bea43b2bad 100644 --- a/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch +++ b/target/linux/generic/pending-5.15/671-net-provide-defines-for-_POLICY_FAILED-until-all-cod.patch @@ -39,7 +39,7 @@ Signed-off-by: Jonas Gorski */ --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h -@@ -253,6 +253,8 @@ enum { +@@ -260,6 +260,8 @@ enum { __RTN_MAX }; diff --git a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index e64e0421e1..af57b4c5bb 100644 --- a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2036,6 +2036,8 @@ struct net_device { +@@ -2068,6 +2068,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; @@ -22,17 +22,17 @@ Signed-off-by: Felix Fietkau #endif --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -858,6 +858,7 @@ struct sk_buff { - #ifdef CONFIG_TLS_DEVICE - __u8 decrypted:1; +@@ -855,6 +855,7 @@ struct sk_buff { + #ifdef CONFIG_IPV6_NDISC_NODETYPE + __u8 ndisc_nodetype:2; #endif + __u8 gro_skip:1; - #ifdef CONFIG_NET_SCHED - __u16 tc_index; /* traffic control index */ + __u8 ipvs_property:1; + __u8 inner_protocol_type:1; --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6062,6 +6062,9 @@ static enum gro_result dev_gro_receive(s +@@ -6051,6 +6051,9 @@ static enum gro_result dev_gro_receive(s int same_flow; int grow; @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau if (netif_elide_gro(skb->dev)) goto normal; -@@ -8039,6 +8042,48 @@ static void __netdev_adjacent_dev_unlink +@@ -8065,6 +8068,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -8090,6 +8135,7 @@ static int __netdev_upper_dev_link(struc +@@ -8116,6 +8161,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -99,7 +99,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -8186,6 +8232,7 @@ static void __netdev_upper_dev_unlink(st +@@ -8212,6 +8258,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8972,6 +9019,7 @@ int dev_set_mac_address(struct net_devic +@@ -9031,6 +9078,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; @@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau return 0; --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c -@@ -143,6 +143,18 @@ u32 eth_get_headlen(const struct net_dev +@@ -142,6 +142,18 @@ u32 eth_get_headlen(const struct net_dev } EXPORT_SYMBOL(eth_get_headlen); @@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau /** * eth_type_trans - determine the packet's protocol ID. * @skb: received socket data -@@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk +@@ -173,6 +185,10 @@ __be16 eth_type_trans(struct sk_buff *sk } else { skb->pkt_type = PACKET_OTHERHOST; } diff --git a/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch b/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch index 2753c76d54..fe6faddc7d 100644 --- a/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch +++ b/target/linux/generic/pending-5.15/682-of_net-add-mac-address-increment-support.patch @@ -20,7 +20,7 @@ Signed-off-by: Ansuel Smith --- a/net/core/of_net.c +++ b/net/core/of_net.c -@@ -115,27 +115,62 @@ static int of_get_mac_addr_nvmem(struct +@@ -119,27 +119,62 @@ static int of_get_mac_addr_nvmem(struct * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists * but is all zeros. * diff --git a/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch index 59dc30bb47..88ade300a4 100644 --- a/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch +++ b/target/linux/generic/pending-5.15/683-of_net-add-mac-address-to-of-tree.patch @@ -26,9 +26,9 @@ +} + /** - * Search the device tree for the best MAC address to use. 'mac-address' is - * checked first, because that is supposed to contain to "most recent" MAC -@@ -171,6 +192,7 @@ found: + * of_get_mac_address() + * @np: Caller's Device Node +@@ -175,6 +196,7 @@ found: addr[5] = (mac_val >> 0) & 0xff; } diff --git a/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch b/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch index ff090f07f1..6323e5e966 100644 --- a/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch +++ b/target/linux/generic/pending-5.15/700-net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch @@ -14,9 +14,9 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -187,6 +187,9 @@ mtk_flow_offload_replace(struct mtk_eth - int hash; - int i; +@@ -189,6 +189,9 @@ mtk_flow_offload_replace(struct mtk_eth + if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) + return -EEXIST; + if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) + return -EEXIST; diff --git a/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch b/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch index 7140c6877e..a36ae0e6e4 100644 --- a/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch +++ b/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch @@ -1,14 +1,14 @@ --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -7,6 +7,7 @@ - #include +@@ -6,6 +6,7 @@ #include + #include #include +#include #include #include #include -@@ -20,6 +21,11 @@ struct mtk_flow_data { +@@ -19,6 +20,11 @@ struct mtk_flow_data { __be32 src_addr; __be32 dst_addr; } v4; @@ -20,7 +20,7 @@ }; __be16 src_port; -@@ -64,6 +70,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en +@@ -63,6 +69,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en data->v4.dst_addr, data->dst_port); } @@ -35,7 +35,7 @@ static void mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth) { -@@ -254,6 +268,9 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -256,6 +270,9 @@ mtk_flow_offload_replace(struct mtk_eth case FLOW_DISSECTOR_KEY_IPV4_ADDRS: offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; break; @@ -45,7 +45,7 @@ default: return -EOPNOTSUPP; } -@@ -289,6 +306,17 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -291,6 +308,17 @@ mtk_flow_offload_replace(struct mtk_eth mtk_flow_set_ipv4_addr(&foe, &data, false); } diff --git a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch index da9c040322..d5ce94d74a 100644 --- a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch +++ b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2171,8 +2171,8 @@ static irqreturn_t mtk_handle_irq_rx(int +@@ -2178,8 +2178,8 @@ static irqreturn_t mtk_handle_irq_rx(int eth->rx_events++; if (likely(napi_schedule_prep(ð->rx_napi))) { @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau } return IRQ_HANDLED; -@@ -2184,8 +2184,8 @@ static irqreturn_t mtk_handle_irq_tx(int +@@ -2191,8 +2191,8 @@ static irqreturn_t mtk_handle_irq_tx(int eth->tx_events++; if (likely(napi_schedule_prep(ð->tx_napi))) { @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau } return IRQ_HANDLED; -@@ -3229,6 +3229,8 @@ static int mtk_probe(struct platform_dev +@@ -3242,6 +3242,8 @@ static int mtk_probe(struct platform_dev * for NAPI to work */ init_dummy_netdev(ð->dummy_dev); diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch index 9aa54082a5..723dbacdd8 100644 --- a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1651,6 +1651,9 @@ void phy_detach(struct phy_device *phyde +@@ -1715,6 +1715,9 @@ void phy_detach(struct phy_device *phyde struct module *ndev_owner = NULL; struct mii_bus *bus; @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -761,6 +761,12 @@ struct phy_driver { +@@ -783,6 +783,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch index 262f1aa35b..f30887fccb 100644 --- a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch +++ b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h -@@ -56,6 +56,7 @@ struct br_ip_list { +@@ -58,6 +58,7 @@ struct br_ip_list { #define BR_MRP_LOST_CONT BIT(18) #define BR_MRP_LOST_IN_CONT BIT(19) #define BR_TX_FWD_OFFLOAD BIT(20) @@ -24,7 +24,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c -@@ -191,6 +191,7 @@ out: +@@ -199,6 +199,7 @@ out: void br_flood(struct net_bridge *br, struct sk_buff *skb, enum br_pkt_type pkt_type, bool local_rcv, bool local_orig) { @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau struct net_bridge_port *prev = NULL; struct net_bridge_port *p; -@@ -206,6 +207,10 @@ void br_flood(struct net_bridge *br, str +@@ -214,6 +215,10 @@ void br_flood(struct net_bridge *br, str case BR_PKT_MULTICAST: if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) continue; @@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -305,6 +305,8 @@ static rx_handler_result_t br_handle_fra +@@ -319,6 +319,8 @@ static rx_handler_result_t br_handle_fra fwd_mask |= p->group_fwd_mask; switch (dest[5]) { case 0x00: /* Bridge Group Address */ @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau if (p->br->stp_enabled == BR_NO_STP || --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c -@@ -233,6 +233,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA +@@ -240,6 +240,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS); BRPORT_ATTR_FLAG(isolated, BR_ISOLATED); @@ -64,7 +64,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) -@@ -285,6 +286,7 @@ static const struct brport_attribute *br +@@ -292,6 +293,7 @@ static const struct brport_attribute *br &brport_attr_group_fwd_mask, &brport_attr_neigh_suppress, &brport_attr_isolated, @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h -@@ -524,6 +524,7 @@ enum { +@@ -536,6 +536,7 @@ enum { IFLA_BRPORT_MRP_IN_OPEN, IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c -@@ -137,6 +137,7 @@ static inline size_t br_port_info_size(v +@@ -184,6 +184,7 @@ static inline size_t br_port_info_size(v + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */ + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */ + nla_total_size(1) /* IFLA_BRPORT_ISOLATED */ @@ -124,7 +124,7 @@ Signed-off-by: Felix Fietkau + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */ + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */ + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */ -@@ -220,7 +221,8 @@ static int br_port_fill_attrs(struct sk_ +@@ -269,7 +270,8 @@ static int br_port_fill_attrs(struct sk_ BR_MRP_LOST_CONT)) || nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN, !!(p->flags & BR_MRP_LOST_IN_CONT)) || @@ -134,7 +134,7 @@ Signed-off-by: Felix Fietkau return -EMSGSIZE; timerval = br_timer_value(&p->message_age_timer); -@@ -728,6 +730,7 @@ static const struct nla_policy br_port_p +@@ -829,6 +831,7 @@ static const struct nla_policy br_port_p [IFLA_BRPORT_ISOLATED] = { .type = NLA_U8 }, [IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 }, [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NLA_U32 }, @@ -142,7 +142,7 @@ Signed-off-by: Felix Fietkau }; /* Change the state of the port and notify spanning tree */ -@@ -826,6 +829,7 @@ static int br_setport(struct net_bridge_ +@@ -893,6 +896,7 @@ static int br_setport(struct net_bridge_ br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, BR_NEIGH_SUPPRESS); br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); @@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau struct rtnl_link { rtnl_doit_func doit; -@@ -4684,7 +4684,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu +@@ -4689,7 +4689,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) || brport_nla_put_flag(skb, flags, mask, diff --git a/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch b/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch index 16be95ea38..0c9604e5a9 100644 --- a/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch +++ b/target/linux/generic/pending-5.15/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch @@ -17,11 +17,11 @@ Signed-off-by: DENG Qingfang --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -2869,6 +2869,7 @@ static int mv88e6xxx_setup(struct dsa_sw +@@ -3193,6 +3193,7 @@ static int mv88e6xxx_setup(struct dsa_sw chip->ds = ds; ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); + ds->configure_vlan_while_not_filtering = true; - mv88e6xxx_reg_lock(chip); - + /* Since virtual bridges are mapped in the PVT, the number we support + * depends on the physical switch topology. We need to let DSA figure diff --git a/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch index 9247401140..8a718a02f2 100644 --- a/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +++ b/target/linux/generic/pending-5.15/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -17,11 +17,11 @@ Signed-off-by: Tobias Waldekranz --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -5436,6 +5436,7 @@ static int mv88e6xxx_register_switch(str +@@ -6319,6 +6319,7 @@ static int mv88e6xxx_register_switch(str ds->ops = &mv88e6xxx_switch_ops; ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; + ds->assisted_learning_on_cpu_port = true; - dev_set_drvdata(dev, ds); - + /* Some chips support up to 32, but that requires enabling the + * 5-bit port mode, which we do not support. 640k^W16 ought to diff --git a/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch index af44ff24ac..c1e14b9271 100644 --- a/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch +++ b/target/linux/generic/pending-5.15/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch @@ -70,9 +70,9 @@ v1 -> v2: --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -1617,4 +1617,19 @@ config GPIO_MOCKUP - tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in - it. +@@ -1683,4 +1683,19 @@ config GPIO_VIRTIO + + endmenu +comment "Other GPIO expanders" + @@ -92,7 +92,7 @@ v1 -> v2: endif --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -44,6 +44,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd +@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o diff --git a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch index f5e444fe46..165ae67260 100644 --- a/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch +++ b/target/linux/generic/pending-5.15/810-pci_disable_common_quirks.patch @@ -31,9 +31,9 @@ Signed-off-by: Gabor Juhos +#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS /* - * The Mellanox Tavor device gives false positive parity errors. Mark this - * device with a broken_parity_status to allow PCI scanning code to "skip" -@@ -3322,6 +3323,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I + * The Mellanox Tavor device gives false positive parity errors. Disable + * parity error reporting. +@@ -3351,6 +3352,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); @@ -42,7 +42,7 @@ Signed-off-by: Gabor Juhos /* * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. * To work around this, query the size it should be configured to by the -@@ -3347,6 +3350,8 @@ static void quirk_intel_ntb(struct pci_d +@@ -3376,6 +3379,8 @@ static void quirk_intel_ntb(struct pci_d DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); @@ -51,7 +51,7 @@ Signed-off-by: Gabor Juhos /* * Some BIOS implementations leave the Intel GPU interrupts enabled, even * though no one is handling them (e.g., if the i915 driver is never -@@ -3385,6 +3390,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN +@@ -3414,6 +3419,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); diff --git a/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch index 42a8397839..9b0ce7100f 100644 --- a/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch +++ b/target/linux/generic/pending-5.15/811-pci_disable_usb_common_quirks.patch @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau #endif /* __LINUX_USB_PCI_QUIRKS_H */ --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h -@@ -484,7 +484,14 @@ extern int usb_hcd_pci_probe(struct pci_ +@@ -495,7 +495,14 @@ extern int usb_hcd_pci_probe(struct pci_ extern void usb_hcd_pci_remove(struct pci_dev *dev); extern void usb_hcd_pci_shutdown(struct pci_dev *dev); diff --git a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch index 95212138b6..dca9f333ba 100644 --- a/target/linux/generic/pending-5.15/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-5.15/834-ledtrig-libata.patch @@ -45,7 +45,7 @@ Signed-off-by: Daniel Golle depends on ACPI --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c -@@ -650,6 +650,19 @@ u64 ata_tf_read_block(const struct ata_t +@@ -656,6 +656,19 @@ u64 ata_tf_read_block(const struct ata_t return block; } @@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @tf: Target ATA taskfile -@@ -4548,6 +4561,9 @@ struct ata_queued_cmd *ata_qc_new_init(s +@@ -4573,6 +4586,9 @@ struct ata_queued_cmd *ata_qc_new_init(s if (tag < 0) return NULL; } @@ -75,7 +75,7 @@ Signed-off-by: Daniel Golle qc = __ata_qc_from_tag(ap, tag); qc->tag = qc->hw_tag = tag; -@@ -5326,6 +5342,9 @@ struct ata_port *ata_port_alloc(struct a +@@ -5351,6 +5367,9 @@ struct ata_port *ata_port_alloc(struct a ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; #endif @@ -85,7 +85,7 @@ Signed-off-by: Daniel Golle ata_sff_port_init(ap); return ap; -@@ -5361,6 +5380,12 @@ static void ata_host_release(struct kref +@@ -5386,6 +5405,12 @@ static void ata_host_release(struct kref kfree(ap->pmp_link); kfree(ap->slave_link); @@ -98,7 +98,7 @@ Signed-off-by: Daniel Golle kfree(ap); host->ports[i] = NULL; } -@@ -5767,7 +5792,23 @@ int ata_host_register(struct ata_host *h +@@ -5792,7 +5817,23 @@ int ata_host_register(struct ata_host *h host->ports[i]->print_id = atomic_inc_return(&ata_print_id); host->ports[i]->local_port_no = i + 1; } @@ -134,7 +134,7 @@ Signed-off-by: Daniel Golle /* * Define if arch has non-standard setup. This is a _PCI_ standard -@@ -882,6 +885,12 @@ struct ata_port { +@@ -888,6 +891,12 @@ struct ata_port { #ifdef CONFIG_ATA_ACPI struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ #endif diff --git a/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch index 580f0b1bfa..5ca8933d6f 100644 --- a/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch +++ b/target/linux/generic/pending-5.15/840-hwrng-bcm2835-set-quality-to-1000.patch @@ -16,7 +16,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/drivers/char/hw_random/bcm2835-rng.c +++ b/drivers/char/hw_random/bcm2835-rng.c -@@ -163,6 +163,7 @@ static int bcm2835_rng_probe(struct plat +@@ -170,6 +170,7 @@ static int bcm2835_rng_probe(struct plat priv->rng.init = bcm2835_rng_init; priv->rng.read = bcm2835_rng_read; priv->rng.cleanup = bcm2835_rng_cleanup; diff --git a/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch b/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch index f2f0e61089..530ab9ba13 100644 --- a/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch +++ b/target/linux/generic/pending-5.15/842-net-qmi_wwan-add-ZTE-MF286D-modem-19d2-1485.patch @@ -49,7 +49,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c -@@ -1252,6 +1252,7 @@ static const struct usb_device_id produc +@@ -1313,6 +1313,7 @@ static const struct usb_device_id produc {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ {QMI_FIXED_INTF(0x19d2, 0x1432, 3)}, /* ZTE ME3620 */ diff --git a/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch b/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch index fecd19166c..1483ff0d6e 100644 --- a/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch +++ b/target/linux/generic/pending-5.15/850-0001-PCI-aardvark-Replace-custom-PCIE_CORE_INT_-macros-wi.patch @@ -18,7 +18,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -37,10 +37,6 @@ +@@ -38,10 +38,6 @@ #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6) #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK BIT(7) #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV BIT(8) @@ -29,7 +29,7 @@ Signed-off-by: Marek Behún /* PIO registers base address and register offsets */ #define PIO_BASE_ADDR 0x4000 #define PIO_CTRL (PIO_BASE_ADDR + 0x0) -@@ -966,7 +962,7 @@ static int advk_sw_pci_bridge_init(struc +@@ -959,7 +955,7 @@ static int advk_sw_pci_bridge_init(struc bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64); /* Support interrupt A for MSI feature */ diff --git a/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch b/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch index 72a432fc06..629005b030 100644 --- a/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch +++ b/target/linux/generic/pending-5.15/850-0002-PCI-aardvark-Fix-reading-MSI-interrupt-number.patch @@ -27,7 +27,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1393,7 +1393,7 @@ static void advk_pcie_remove_irq_domain( +@@ -1386,7 +1386,7 @@ static void advk_pcie_remove_irq_domain( static void advk_pcie_handle_msi(struct advk_pcie *pcie) { u32 msi_val, msi_mask, msi_status, msi_idx; @@ -36,7 +36,7 @@ Signed-off-by: Marek Behún msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG); msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG); -@@ -1403,13 +1403,12 @@ static void advk_pcie_handle_msi(struct +@@ -1396,13 +1396,12 @@ static void advk_pcie_handle_msi(struct if (!(BIT(msi_idx) & msi_status)) continue; diff --git a/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch b/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch index 8b2d07089a..952eb9d405 100644 --- a/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch +++ b/target/linux/generic/pending-5.15/850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch @@ -32,7 +32,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1189,7 +1189,7 @@ static void advk_msi_irq_compose_msi_msg +@@ -1182,7 +1182,7 @@ static void advk_msi_irq_compose_msi_msg msg->address_lo = lower_32_bits(msi_msg); msg->address_hi = upper_32_bits(msi_msg); @@ -41,7 +41,7 @@ Signed-off-by: Marek Behún } static int advk_msi_set_affinity(struct irq_data *irq_data, -@@ -1206,15 +1206,11 @@ static int advk_msi_irq_domain_alloc(str +@@ -1199,15 +1199,11 @@ static int advk_msi_irq_domain_alloc(str int hwirq, i; mutex_lock(&pcie->msi_used_lock); @@ -61,7 +61,7 @@ Signed-off-by: Marek Behún for (i = 0; i < nr_irqs; i++) irq_domain_set_info(domain, virq + i, hwirq + i, -@@ -1232,7 +1228,7 @@ static void advk_msi_irq_domain_free(str +@@ -1225,7 +1221,7 @@ static void advk_msi_irq_domain_free(str struct advk_pcie *pcie = domain->host_data; mutex_lock(&pcie->msi_used_lock); diff --git a/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch b/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch index 47a26ceeb8..0418b1c303 100644 --- a/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch +++ b/target/linux/generic/pending-5.15/850-0004-PCI-aardvark-Rewrite-IRQ-code-to-chained-IRQ-handler.patch @@ -23,7 +23,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -275,6 +275,7 @@ struct advk_pcie { +@@ -268,6 +268,7 @@ struct advk_pcie { u32 actions; } wins[OB_WIN_COUNT]; u8 wins_count; @@ -31,7 +31,7 @@ Signed-off-by: Marek Behún struct irq_domain *irq_domain; struct irq_chip irq_chip; raw_spinlock_t irq_lock; -@@ -1442,21 +1443,26 @@ static void advk_pcie_handle_int(struct +@@ -1434,21 +1435,26 @@ static void advk_pcie_handle_int(struct } } @@ -68,7 +68,7 @@ Signed-off-by: Marek Behún } static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) -@@ -1523,7 +1529,7 @@ static int advk_pcie_probe(struct platfo +@@ -1515,7 +1521,7 @@ static int advk_pcie_probe(struct platfo struct advk_pcie *pcie; struct pci_host_bridge *bridge; struct resource_entry *entry; @@ -77,7 +77,7 @@ Signed-off-by: Marek Behún bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie)); if (!bridge) -@@ -1611,17 +1617,9 @@ static int advk_pcie_probe(struct platfo +@@ -1601,17 +1607,9 @@ static int advk_pcie_probe(struct platfo if (IS_ERR(pcie->base)) return PTR_ERR(pcie->base); @@ -98,7 +98,7 @@ Signed-off-by: Marek Behún pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node, "reset-gpios", 0, -@@ -1670,11 +1668,14 @@ static int advk_pcie_probe(struct platfo +@@ -1660,11 +1658,14 @@ static int advk_pcie_probe(struct platfo return ret; } @@ -113,7 +113,7 @@ Signed-off-by: Marek Behún advk_pcie_remove_msi_irq_domain(pcie); advk_pcie_remove_irq_domain(pcie); return ret; -@@ -1722,6 +1723,9 @@ static int advk_pcie_remove(struct platf +@@ -1712,6 +1713,9 @@ static int advk_pcie_remove(struct platf advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); diff --git a/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch b/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch index 355c835a6e..3910767ea3 100644 --- a/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch +++ b/target/linux/generic/pending-5.15/850-0005-PCI-aardvark-Check-return-value-of-generic_handle_do.patch @@ -18,7 +18,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1439,7 +1439,9 @@ static void advk_pcie_handle_int(struct +@@ -1431,7 +1431,9 @@ static void advk_pcie_handle_int(struct advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i), PCIE_ISR1_REG); diff --git a/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch b/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch index 154b11290a..cf8ab19684 100644 --- a/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch +++ b/target/linux/generic/pending-5.15/850-0006-PCI-aardvark-Make-MSI-irq_chip-structures-static-dri.patch @@ -25,7 +25,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -281,8 +281,6 @@ struct advk_pcie { +@@ -274,8 +274,6 @@ struct advk_pcie { raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; @@ -34,7 +34,7 @@ Signed-off-by: Marek Behún struct msi_domain_info msi_domain_info; DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); struct mutex msi_used_lock; -@@ -1199,6 +1197,12 @@ static int advk_msi_set_affinity(struct +@@ -1192,6 +1190,12 @@ static int advk_msi_set_affinity(struct return -EINVAL; } @@ -47,7 +47,7 @@ Signed-off-by: Marek Behún static int advk_msi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *args) -@@ -1215,7 +1219,7 @@ static int advk_msi_irq_domain_alloc(str +@@ -1208,7 +1212,7 @@ static int advk_msi_irq_domain_alloc(str for (i = 0; i < nr_irqs; i++) irq_domain_set_info(domain, virq + i, hwirq + i, @@ -56,7 +56,7 @@ Signed-off-by: Marek Behún domain->host_data, handle_simple_irq, NULL, NULL); -@@ -1285,29 +1289,23 @@ static const struct irq_domain_ops advk_ +@@ -1278,29 +1282,23 @@ static const struct irq_domain_ops advk_ .xlate = irq_domain_xlate_onecell, }; diff --git a/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch b/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch index 2f15b5b8d6..370de6cdc7 100644 --- a/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch +++ b/target/linux/generic/pending-5.15/850-0007-PCI-aardvark-Make-msi_domain_info-structure-a-static.patch @@ -17,7 +17,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -281,7 +281,6 @@ struct advk_pcie { +@@ -274,7 +274,6 @@ struct advk_pcie { raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; @@ -25,7 +25,7 @@ Signed-off-by: Marek Behún DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); struct mutex msi_used_lock; u16 msi_msg; -@@ -1293,20 +1292,20 @@ static struct irq_chip advk_msi_irq_chip +@@ -1286,20 +1285,20 @@ static struct irq_chip advk_msi_irq_chip .name = "advk-MSI", }; @@ -52,7 +52,7 @@ Signed-off-by: Marek Behún msi_msg_phys = virt_to_phys(&pcie->msi_msg); advk_writel(pcie, lower_32_bits(msi_msg_phys), -@@ -1322,7 +1321,8 @@ static int advk_pcie_init_msi_irq_domain +@@ -1315,7 +1314,8 @@ static int advk_pcie_init_msi_irq_domain pcie->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), diff --git a/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch b/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch index 73f7cb9476..46f0d7f83b 100644 --- a/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch +++ b/target/linux/generic/pending-5.15/850-0008-PCI-aardvark-Use-dev_fwnode-instead-of-of_node_to_fw.patch @@ -21,7 +21,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1301,7 +1301,6 @@ static struct msi_domain_info advk_msi_d +@@ -1294,7 +1294,6 @@ static struct msi_domain_info advk_msi_d static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) { struct device *dev = &pcie->pdev->dev; @@ -29,7 +29,7 @@ Signed-off-by: Marek Behún phys_addr_t msi_msg_phys; mutex_init(&pcie->msi_used_lock); -@@ -1320,7 +1319,7 @@ static int advk_pcie_init_msi_irq_domain +@@ -1313,7 +1312,7 @@ static int advk_pcie_init_msi_irq_domain return -ENOMEM; pcie->msi_domain = diff --git a/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch b/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch index 6cdaddc51c..7c36f7d2d6 100644 --- a/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch +++ b/target/linux/generic/pending-5.15/850-0009-PCI-aardvark-Refactor-unmasking-summary-MSI-interrup.patch @@ -20,7 +20,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -578,15 +578,17 @@ static void advk_pcie_setup_hw(struct ad +@@ -571,15 +571,17 @@ static void advk_pcie_setup_hw(struct ad advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); /* Disable All ISR0/1 Sources */ diff --git a/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch b/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch index 808094ebd8..8a80d67af3 100644 --- a/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch +++ b/target/linux/generic/pending-5.15/850-0010-PCI-aardvark-Add-support-for-masking-MSI-interrupts.patch @@ -20,7 +20,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -281,6 +281,7 @@ struct advk_pcie { +@@ -274,6 +274,7 @@ struct advk_pcie { raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; @@ -28,7 +28,7 @@ Signed-off-by: Marek Behún DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); struct mutex msi_used_lock; u16 msi_msg; -@@ -577,12 +578,10 @@ static void advk_pcie_setup_hw(struct ad +@@ -570,12 +571,10 @@ static void advk_pcie_setup_hw(struct ad advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); @@ -43,7 +43,7 @@ Signed-off-by: Marek Behún /* Unmask summary MSI interrupt */ reg = advk_readl(pcie, PCIE_ISR0_MASK_REG); -@@ -1198,10 +1197,52 @@ static int advk_msi_set_affinity(struct +@@ -1191,10 +1190,52 @@ static int advk_msi_set_affinity(struct return -EINVAL; } @@ -96,7 +96,7 @@ Signed-off-by: Marek Behún }; static int advk_msi_irq_domain_alloc(struct irq_domain *domain, -@@ -1291,7 +1332,9 @@ static const struct irq_domain_ops advk_ +@@ -1284,7 +1325,9 @@ static const struct irq_domain_ops advk_ }; static struct irq_chip advk_msi_irq_chip = { @@ -107,7 +107,7 @@ Signed-off-by: Marek Behún }; static struct msi_domain_info advk_msi_domain_info = { -@@ -1305,6 +1348,7 @@ static int advk_pcie_init_msi_irq_domain +@@ -1298,6 +1341,7 @@ static int advk_pcie_init_msi_irq_domain struct device *dev = &pcie->pdev->dev; phys_addr_t msi_msg_phys; diff --git a/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch b/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch index 4807f24a12..e481fb2799 100644 --- a/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch +++ b/target/linux/generic/pending-5.15/850-0011-PCI-aardvark-Fix-setting-MSI-address.patch @@ -28,7 +28,7 @@ Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -284,7 +284,6 @@ struct advk_pcie { +@@ -277,7 +277,6 @@ struct advk_pcie { raw_spinlock_t msi_irq_lock; DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); struct mutex msi_used_lock; @@ -36,7 +36,7 @@ Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling int link_gen; struct pci_bridge_emul bridge; struct gpio_desc *reset_gpio; -@@ -479,6 +478,7 @@ static void advk_pcie_disable_ob_win(str +@@ -472,6 +471,7 @@ static void advk_pcie_disable_ob_win(str static void advk_pcie_setup_hw(struct advk_pcie *pcie) { @@ -44,7 +44,7 @@ Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling u32 reg; int i; -@@ -567,6 +567,11 @@ static void advk_pcie_setup_hw(struct ad +@@ -560,6 +560,11 @@ static void advk_pcie_setup_hw(struct ad reg |= LANE_COUNT_1; advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); @@ -56,7 +56,7 @@ Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling /* Enable MSI */ reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG); reg |= PCIE_CORE_CTRL2_MSI_ENABLE; -@@ -1184,10 +1189,10 @@ static void advk_msi_irq_compose_msi_msg +@@ -1177,10 +1182,10 @@ static void advk_msi_irq_compose_msi_msg struct msi_msg *msg) { struct advk_pcie *pcie = irq_data_get_irq_chip_data(data); @@ -70,7 +70,7 @@ Cc: stable@vger.kernel.org # f21a8b1b6837 ("PCI: aardvark: Move to MSI handling msg->data = data->hwirq; } -@@ -1346,18 +1351,10 @@ static struct msi_domain_info advk_msi_d +@@ -1339,18 +1344,10 @@ static struct msi_domain_info advk_msi_d static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) { struct device *dev = &pcie->pdev->dev; diff --git a/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch b/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch index 20757c7a80..85d57d40ef 100644 --- a/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch +++ b/target/linux/generic/pending-5.15/850-0012-PCI-aardvark-Enable-MSI-X-support.patch @@ -27,7 +27,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1344,7 +1344,7 @@ static struct irq_chip advk_msi_irq_chip +@@ -1337,7 +1337,7 @@ static struct irq_chip advk_msi_irq_chip static struct msi_domain_info advk_msi_domain_info = { .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | diff --git a/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch b/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch index eb27610aa3..4a552a2ed3 100644 --- a/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch +++ b/target/linux/generic/pending-5.15/850-0013-PCI-aardvark-Add-support-for-ERR-interrupt-on-emulat.patch @@ -30,7 +30,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -97,6 +97,10 @@ +@@ -98,6 +98,10 @@ #define PCIE_MSG_PM_PME_MASK BIT(7) #define PCIE_ISR0_MASK_REG (CONTROL_BASE_ADDR + 0x44) #define PCIE_ISR0_MSI_INT_PENDING BIT(24) @@ -41,7 +41,7 @@ Signed-off-by: Marek Behún #define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val)) #define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val)) #define PCIE_ISR0_ALL_MASK GENMASK(31, 0) -@@ -785,11 +789,15 @@ advk_pci_bridge_emul_base_conf_read(stru +@@ -778,11 +782,15 @@ advk_pci_bridge_emul_base_conf_read(stru case PCI_INTERRUPT_LINE: { /* * From the whole 32bit register we support reading from HW only @@ -58,7 +58,7 @@ Signed-off-by: Marek Behún if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN) val |= PCI_BRIDGE_CTL_BUS_RESET << 16; else -@@ -815,6 +823,19 @@ advk_pci_bridge_emul_base_conf_write(str +@@ -808,6 +816,19 @@ advk_pci_bridge_emul_base_conf_write(str break; case PCI_INTERRUPT_LINE: @@ -78,7 +78,7 @@ Signed-off-by: Marek Behún if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) -@@ -1466,6 +1487,19 @@ static void advk_pcie_handle_int(struct +@@ -1459,6 +1480,19 @@ static void advk_pcie_handle_int(struct isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); diff --git a/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch b/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch index 4a2cd77144..55ae07e703 100644 --- a/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch +++ b/target/linux/generic/pending-5.15/850-0014-PCI-aardvark-Fix-reading-PCI_EXP_RTSTA_PME-bit-on-em.patch @@ -31,7 +31,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -874,7 +874,9 @@ advk_pci_bridge_emul_pcie_conf_read(stru +@@ -867,7 +867,9 @@ advk_pci_bridge_emul_pcie_conf_read(stru case PCI_EXP_RTSTA: { u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG); u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG); diff --git a/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch b/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch index 5ed809def2..f988bb3e62 100644 --- a/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch +++ b/target/linux/generic/pending-5.15/850-0015-PCI-aardvark-Optimize-writing-PCI_EXP_RTCTL_PMEIE-an.patch @@ -19,7 +19,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -932,19 +932,21 @@ advk_pci_bridge_emul_pcie_conf_write(str +@@ -925,19 +925,21 @@ advk_pci_bridge_emul_pcie_conf_write(str advk_pcie_wait_for_retrain(pcie); break; diff --git a/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch b/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch index 4272b6dd6e..64641e7710 100644 --- a/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch +++ b/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch @@ -25,7 +25,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1491,6 +1491,19 @@ static void advk_pcie_handle_int(struct +@@ -1484,6 +1484,19 @@ static void advk_pcie_handle_int(struct isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); diff --git a/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch b/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch index 6aa7dcbd76..c2a0d8f723 100644 --- a/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch +++ b/target/linux/generic/pending-5.15/850-0017-PCI-aardvark-Fix-support-for-PME-requester-on-emulat.patch @@ -40,7 +40,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -597,6 +597,11 @@ static void advk_pcie_setup_hw(struct ad +@@ -590,6 +590,11 @@ static void advk_pcie_setup_hw(struct ad reg &= ~PCIE_ISR0_MSI_INT_PENDING; advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); @@ -52,7 +52,7 @@ Signed-off-by: Marek Behún /* Enable summary interrupt for GIC SPI source */ reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG); -@@ -863,22 +868,11 @@ advk_pci_bridge_emul_pcie_conf_read(stru +@@ -856,22 +861,11 @@ advk_pci_bridge_emul_pcie_conf_read(stru *value = PCI_EXP_SLTSTA_PDS << 16; return PCI_BRIDGE_EMUL_HANDLED; @@ -80,7 +80,7 @@ Signed-off-by: Marek Behún case PCI_EXP_LNKCAP: { u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); -@@ -932,22 +926,19 @@ advk_pci_bridge_emul_pcie_conf_write(str +@@ -925,22 +919,19 @@ advk_pci_bridge_emul_pcie_conf_write(str advk_pcie_wait_for_retrain(pcie); break; @@ -114,7 +114,7 @@ Signed-off-by: Marek Behún case PCI_EXP_DEVCTL: case PCI_EXP_DEVCTL2: -@@ -1452,6 +1443,34 @@ static void advk_pcie_remove_irq_domain( +@@ -1445,6 +1436,34 @@ static void advk_pcie_remove_irq_domain( irq_domain_remove(pcie->irq_domain); } @@ -149,7 +149,7 @@ Signed-off-by: Marek Behún static void advk_pcie_handle_msi(struct advk_pcie *pcie) { u32 msi_val, msi_mask, msi_status, msi_idx; -@@ -1491,18 +1510,9 @@ static void advk_pcie_handle_int(struct +@@ -1484,18 +1503,9 @@ static void advk_pcie_handle_int(struct isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); diff --git a/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch b/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch index e9f65aca23..dfcd84f475 100644 --- a/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch +++ b/target/linux/generic/pending-5.15/850-0018-PCI-aardvark-Use-separate-INTA-interrupt-for-emulate.patch @@ -33,7 +33,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -280,6 +280,7 @@ struct advk_pcie { +@@ -273,6 +273,7 @@ struct advk_pcie { } wins[OB_WIN_COUNT]; u8 wins_count; int irq; @@ -41,7 +41,7 @@ Signed-off-by: Marek Behún struct irq_domain *irq_domain; struct irq_chip irq_chip; raw_spinlock_t irq_lock; -@@ -1443,6 +1444,44 @@ static void advk_pcie_remove_irq_domain( +@@ -1436,6 +1437,44 @@ static void advk_pcie_remove_irq_domain( irq_domain_remove(pcie->irq_domain); } @@ -86,7 +86,7 @@ Signed-off-by: Marek Behún static void advk_pcie_handle_pme(struct advk_pcie *pcie) { u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16; -@@ -1465,7 +1504,7 @@ static void advk_pcie_handle_pme(struct +@@ -1458,7 +1497,7 @@ static void advk_pcie_handle_pme(struct if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE)) return; @@ -95,7 +95,7 @@ Signed-off-by: Marek Behún if (generic_handle_irq(virq) == -EINVAL) dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n"); } -@@ -1522,7 +1561,7 @@ static void advk_pcie_handle_int(struct +@@ -1515,7 +1554,7 @@ static void advk_pcie_handle_int(struct * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use * PCIe interrupt 0 */ @@ -104,7 +104,7 @@ Signed-off-by: Marek Behún if (generic_handle_irq(virq) == -EINVAL) dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n"); } -@@ -1568,6 +1607,21 @@ static void advk_pcie_irq_handler(struct +@@ -1560,6 +1599,21 @@ static void advk_pcie_irq_handler(struct chained_irq_exit(chip, desc); } @@ -126,7 +126,7 @@ Signed-off-by: Marek Behún static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) { phy_power_off(pcie->phy); -@@ -1771,14 +1825,24 @@ static int advk_pcie_probe(struct platfo +@@ -1761,14 +1815,24 @@ static int advk_pcie_probe(struct platfo return ret; } @@ -151,7 +151,7 @@ Signed-off-by: Marek Behún advk_pcie_remove_msi_irq_domain(pcie); advk_pcie_remove_irq_domain(pcie); return ret; -@@ -1830,6 +1894,7 @@ static int advk_pcie_remove(struct platf +@@ -1820,6 +1884,7 @@ static int advk_pcie_remove(struct platf irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); /* Remove IRQ domains */ diff --git a/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch b/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch index 75f31ba19e..49422f4c68 100644 --- a/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch +++ b/target/linux/generic/pending-5.15/850-0019-PCI-aardvark-Remove-irq_mask_ack-callback-for-INTx-i.patch @@ -19,7 +19,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1422,7 +1422,6 @@ static int advk_pcie_init_irq_domain(str +@@ -1415,7 +1415,6 @@ static int advk_pcie_init_irq_domain(str } irq_chip->irq_mask = advk_pcie_irq_mask; diff --git a/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch b/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch index 5583dc1b6f..803441293d 100644 --- a/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch +++ b/target/linux/generic/pending-5.15/850-0020-PCI-aardvark-Don-t-mask-irq-when-mapping.patch @@ -17,7 +17,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1339,7 +1339,6 @@ static int advk_pcie_irq_map(struct irq_ +@@ -1332,7 +1332,6 @@ static int advk_pcie_irq_map(struct irq_ { struct advk_pcie *pcie = h->host_data; diff --git a/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch b/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch index f359663ca4..c10352ebfd 100644 --- a/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch +++ b/target/linux/generic/pending-5.15/850-0021-PCI-aardvark-Drop-__maybe_unused-from-advk_pcie_disa.patch @@ -17,7 +17,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1620,7 +1620,7 @@ static int advk_pcie_map_irq(const struc +@@ -1612,7 +1612,7 @@ static int advk_pcie_map_irq(const struc return of_irq_parse_and_map_pci(dev, slot, pin); } diff --git a/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch b/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch index cc489ebc8a..fc3efac283 100644 --- a/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch +++ b/target/linux/generic/pending-5.15/850-0022-PCI-aardvark-Update-comment-about-link-going-down-af.patch @@ -18,7 +18,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1005,8 +1005,12 @@ static bool advk_pcie_valid_device(struc +@@ -998,8 +998,12 @@ static bool advk_pcie_valid_device(struc return false; /* diff --git a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch index a5e2d8a3dd..96a55ba311 100644 --- a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch +++ b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch @@ -33,7 +33,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -282,7 +282,6 @@ struct advk_pcie { +@@ -275,7 +275,6 @@ struct advk_pcie { int irq; struct irq_domain *rp_irq_domain; struct irq_domain *irq_domain; @@ -41,7 +41,7 @@ Signed-off-by: Marek Behún raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; -@@ -1338,14 +1337,19 @@ static void advk_pcie_irq_unmask(struct +@@ -1331,14 +1330,19 @@ static void advk_pcie_irq_unmask(struct raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); } @@ -63,7 +63,7 @@ Signed-off-by: Marek Behún irq_set_chip_data(virq, pcie); return 0; -@@ -1404,7 +1408,6 @@ static int advk_pcie_init_irq_domain(str +@@ -1397,7 +1401,6 @@ static int advk_pcie_init_irq_domain(str struct device *dev = &pcie->pdev->dev; struct device_node *node = dev->of_node; struct device_node *pcie_intc_node; @@ -71,7 +71,7 @@ Signed-off-by: Marek Behún int ret = 0; raw_spin_lock_init(&pcie->irq_lock); -@@ -1415,28 +1418,14 @@ static int advk_pcie_init_irq_domain(str +@@ -1408,28 +1411,14 @@ static int advk_pcie_init_irq_domain(str return -ENODEV; } diff --git a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch index 857ee66a31..3012120a10 100644 --- a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch +++ b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch @@ -23,7 +23,7 @@ Acked-by: Miquel Raynal --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1637,9 +1637,7 @@ static int advk_pcie_enable_phy(struct a +@@ -1629,9 +1629,7 @@ static int advk_pcie_enable_phy(struct a } ret = phy_power_on(pcie->phy); diff --git a/target/linux/generic/pending-5.15/920-mangle_bootargs.patch b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch index bd9de92000..d3f3a1c639 100644 --- a/target/linux/generic/pending-5.15/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-5.15/920-mangle_bootargs.patch @@ -13,7 +13,7 @@ Signed-off-by: Imre Kaloz --- a/init/Kconfig +++ b/init/Kconfig -@@ -1800,6 +1800,15 @@ config EMBEDDED +@@ -1805,6 +1805,15 @@ config EMBEDDED an embedded system so certain expert options are available for configuration. @@ -31,7 +31,7 @@ Signed-off-by: Imre Kaloz help --- a/init/main.c +++ b/init/main.c -@@ -608,6 +608,29 @@ static inline void setup_nr_cpu_ids(void +@@ -614,6 +614,29 @@ static inline void setup_nr_cpu_ids(void static inline void smp_prepare_cpus(unsigned int maxcpus) { } #endif @@ -61,7 +61,7 @@ Signed-off-by: Imre Kaloz /* * We need to store the untouched command line for future reference. * We also need to store the touched command line since the parameter -@@ -869,6 +892,7 @@ asmlinkage __visible void __init __no_sa +@@ -954,6 +977,7 @@ asmlinkage __visible void __init __no_sa pr_notice("%s", linux_banner); early_security_init(); setup_arch(&command_line); From 0f029b3d2b505b40aca9a24a002838ed1060f83d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 30 Nov 2021 11:55:24 +0100 Subject: [PATCH 23/26] mediatek: add patches for MT7622 WED (wireless ethernet dispatch) This series also contains other improvement for hardware flow offload support Signed-off-by: Felix Fietkau --- .../721-net-add-packet-mangeling.patch | 10 +- .../721-net-add-packet-mangeling.patch | 12 +- ..._eth_soc-add-support-for-coherent-DM.patch | 327 ++++ ...ek-mt7622-add-support-for-coherent-D.patch | 30 + ..._eth_soc-add-support-for-Wireless-Et.patch | 1679 +++++++++++++++++ ..._eth_soc-implement-flow-offloading-t.patch | 269 +++ ...ek-mt7622-introduce-nodes-for-Wirele.patch | 62 + ...eth_soc-add-ipv6-flow-offload-suppo.patch} | 26 +- ..._eth_soc-support-TC_SETUP_BLOCK-for-.patch | 29 + ..._eth_soc-allocate-struct-mtk_ppe-sep.patch | 159 ++ ..._eth_soc-rework-hardware-flow-table-.patch | 424 +++++ ..._eth_soc-remove-bridge-flow-offload-.patch | 44 + ..._eth_soc-support-creating-mac-addres.patch | 553 ++++++ ..._eth_soc-add-support-for-coherent-DM.patch | 327 ++++ ...ek-mt7622-add-support-for-coherent-D.patch | 30 + ..._eth_soc-add-support-for-Wireless-Et.patch | 1679 +++++++++++++++++ ..._eth_soc-implement-flow-offloading-t.patch | 269 +++ ...ek-mt7622-introduce-nodes-for-Wirele.patch | 62 + ...eth_soc-add-ipv6-flow-offload-suppo.patch} | 24 +- ..._eth_soc-support-TC_SETUP_BLOCK-for-.patch | 29 + ..._eth_soc-allocate-struct-mtk_ppe-sep.patch | 159 ++ ..._eth_soc-rework-hardware-flow-table-.patch | 424 +++++ ..._eth_soc-remove-bridge-flow-offload-.patch | 44 + ..._eth_soc-support-creating-mac-addres.patch | 553 ++++++ ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 6 +- ...mediatek-add-flow-offload-for-mt7623.patch | 2 +- ..._eth_soc-add-support-for-coherent-DM.patch | 85 - ..._eth_soc-fix-return-values-and-refac.patch | 4 +- ..._eth_soc-implement-Clause-45-MDIO-ac.patch | 8 +- ...ernet-mtk_eth_soc-announce-2500baseT.patch | 2 +- ...ediatek-add-support-for-coherent-DMA.patch | 12 - ...ethernet-mediatek-support-net-labels.patch | 4 +- 32 files changed, 7215 insertions(+), 132 deletions(-) create mode 100644 target/linux/generic/pending-5.10/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch create mode 100644 target/linux/generic/pending-5.10/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch create mode 100644 target/linux/generic/pending-5.10/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch create mode 100644 target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch create mode 100644 target/linux/generic/pending-5.10/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch rename target/linux/generic/{pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch => pending-5.10/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch} (67%) create mode 100644 target/linux/generic/pending-5.10/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch create mode 100644 target/linux/generic/pending-5.10/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch create mode 100644 target/linux/generic/pending-5.10/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch create mode 100644 target/linux/generic/pending-5.10/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch create mode 100644 target/linux/generic/pending-5.10/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch create mode 100644 target/linux/generic/pending-5.15/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch create mode 100644 target/linux/generic/pending-5.15/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch create mode 100644 target/linux/generic/pending-5.15/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch create mode 100644 target/linux/generic/pending-5.15/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch create mode 100644 target/linux/generic/pending-5.15/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch rename target/linux/generic/{pending-5.10/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch => pending-5.15/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch} (69%) create mode 100644 target/linux/generic/pending-5.15/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch create mode 100644 target/linux/generic/pending-5.15/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch create mode 100644 target/linux/generic/pending-5.15/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch create mode 100644 target/linux/generic/pending-5.15/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch create mode 100644 target/linux/generic/pending-5.15/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch delete mode 100644 target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch diff --git a/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch index 67808c35f8..530322eb06 100644 --- a/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1618,6 +1618,7 @@ enum netdev_priv_flags { +@@ -1625,6 +1625,7 @@ enum netdev_priv_flags { IFF_FAILOVER_SLAVE = 1<<28, IFF_L3MDEV_RX_HANDLER = 1<<29, IFF_LIVE_RENAME_OK = 1<<30, @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN -@@ -1650,6 +1651,7 @@ enum netdev_priv_flags { +@@ -1657,6 +1658,7 @@ enum netdev_priv_flags { #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK @@ -35,7 +35,7 @@ Signed-off-by: Felix Fietkau /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -1990,6 +1992,11 @@ struct net_device { +@@ -1997,6 +1999,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau const struct header_ops *header_ops; unsigned int flags; -@@ -2080,6 +2087,10 @@ struct net_device { +@@ -2087,6 +2094,10 @@ struct net_device { struct mpls_dev __rcu *mpls_ptr; #endif @@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3646,6 +3646,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3650,6 +3650,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch index abc0735e36..6abd1ec55f 100644 --- a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1648,6 +1648,10 @@ enum netdev_priv_flags { +@@ -1655,6 +1655,10 @@ enum netdev_priv_flags { IFF_TX_SKB_NO_LINEAR = 1<<31, }; @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN #define IFF_EBRIDGE IFF_EBRIDGE #define IFF_BONDING IFF_BONDING -@@ -1680,6 +1684,7 @@ enum netdev_priv_flags { +@@ -1687,6 +1691,7 @@ enum netdev_priv_flags { #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -1981,6 +1986,7 @@ struct net_device { +@@ -1988,6 +1993,7 @@ struct net_device { /* Read-mostly cache-line for fast-path access */ unsigned int flags; unsigned int priv_flags; @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau const struct net_device_ops *netdev_ops; int ifindex; unsigned short gflags; -@@ -2041,6 +2047,11 @@ struct net_device { +@@ -2048,6 +2054,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -58,7 +58,7 @@ Signed-off-by: Felix Fietkau const struct header_ops *header_ops; unsigned char operstate; -@@ -2115,6 +2126,10 @@ struct net_device { +@@ -2122,6 +2133,10 @@ struct net_device { struct mctp_dev __rcu *mctp_ptr; #endif @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3578,6 +3578,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3582,6 +3582,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/pending-5.10/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch b/target/linux/generic/pending-5.10/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch new file mode 100644 index 0000000000..245a996c96 --- /dev/null +++ b/target/linux/generic/pending-5.10/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch @@ -0,0 +1,327 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 17:59:07 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for coherent + DMA + +It improves performance by eliminating the need for a cache flush on rx and tx +In preparation for supporting WED (Wireless Ethernet Dispatch), also add a +function for disabling coherent DMA at runtime. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -821,7 +822,7 @@ static int mtk_init_fq_dma(struct mtk_et + dma_addr_t dma_addr; + int i; + +- eth->scratch_ring = dma_alloc_coherent(eth->dev, ++ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, + cnt * sizeof(struct mtk_tx_dma), + ð->phy_scratch_ring, + GFP_ATOMIC); +@@ -833,10 +834,10 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(!eth->scratch_head)) + return -ENOMEM; + +- dma_addr = dma_map_single(eth->dev, ++ dma_addr = dma_map_single(eth->dma_dev, + eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE, + DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, dma_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + + phy_ring_tail = eth->phy_scratch_ring + +@@ -890,26 +891,26 @@ static void mtk_tx_unmap(struct mtk_eth + { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { + if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) { +- dma_unmap_single(eth->dev, ++ dma_unmap_single(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } else if (tx_buf->flags & MTK_TX_FLAGS_PAGE0) { +- dma_unmap_page(eth->dev, ++ dma_unmap_page(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } + } else { + if (dma_unmap_len(tx_buf, dma_len0)) { +- dma_unmap_page(eth->dev, ++ dma_unmap_page(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } + + if (dma_unmap_len(tx_buf, dma_len1)) { +- dma_unmap_page(eth->dev, ++ dma_unmap_page(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr1), + dma_unmap_len(tx_buf, dma_len1), + DMA_TO_DEVICE); +@@ -987,9 +988,9 @@ static int mtk_tx_map(struct sk_buff *sk + if (skb_vlan_tag_present(skb)) + txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb); + +- mapped_addr = dma_map_single(eth->dev, skb->data, ++ mapped_addr = dma_map_single(eth->dma_dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, mapped_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr))) + return -ENOMEM; + + WRITE_ONCE(itxd->txd1, mapped_addr); +@@ -1028,10 +1029,10 @@ static int mtk_tx_map(struct sk_buff *sk + + + frag_map_size = min(frag_size, MTK_TX_DMA_BUF_LEN); +- mapped_addr = skb_frag_dma_map(eth->dev, frag, offset, ++ mapped_addr = skb_frag_dma_map(eth->dma_dev, frag, offset, + frag_map_size, + DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, mapped_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr))) + goto err_dma; + + if (i == nr_frags - 1 && +@@ -1309,18 +1310,18 @@ static int mtk_poll_rx(struct napi_struc + netdev->stats.rx_dropped++; + goto release_desc; + } +- dma_addr = dma_map_single(eth->dev, ++ dma_addr = dma_map_single(eth->dma_dev, + new_data + NET_SKB_PAD + + eth->ip_align, + ring->buf_size, + DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, dma_addr))) { ++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) { + skb_free_frag(new_data); + netdev->stats.rx_dropped++; + goto release_desc; + } + +- dma_unmap_single(eth->dev, trxd.rxd1, ++ dma_unmap_single(eth->dma_dev, trxd.rxd1, + ring->buf_size, DMA_FROM_DEVICE); + + /* receive data */ +@@ -1593,7 +1594,7 @@ static int mtk_tx_alloc(struct mtk_eth * + if (!ring->buf) + goto no_tx_mem; + +- ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz, ++ ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, + &ring->phys, GFP_ATOMIC); + if (!ring->dma) + goto no_tx_mem; +@@ -1611,7 +1612,7 @@ static int mtk_tx_alloc(struct mtk_eth * + * descriptors in ring->dma_pdma. + */ + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { +- ring->dma_pdma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz, ++ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, + &ring->phys_pdma, + GFP_ATOMIC); + if (!ring->dma_pdma) +@@ -1670,7 +1671,7 @@ static void mtk_tx_clean(struct mtk_eth + } + + if (ring->dma) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + MTK_DMA_SIZE * sizeof(*ring->dma), + ring->dma, + ring->phys); +@@ -1678,7 +1679,7 @@ static void mtk_tx_clean(struct mtk_eth + } + + if (ring->dma_pdma) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + MTK_DMA_SIZE * sizeof(*ring->dma_pdma), + ring->dma_pdma, + ring->phys_pdma); +@@ -1723,18 +1724,18 @@ static int mtk_rx_alloc(struct mtk_eth * + return -ENOMEM; + } + +- ring->dma = dma_alloc_coherent(eth->dev, ++ ring->dma = dma_alloc_coherent(eth->dma_dev, + rx_dma_size * sizeof(*ring->dma), + &ring->phys, GFP_ATOMIC); + if (!ring->dma) + return -ENOMEM; + + for (i = 0; i < rx_dma_size; i++) { +- dma_addr_t dma_addr = dma_map_single(eth->dev, ++ dma_addr_t dma_addr = dma_map_single(eth->dma_dev, + ring->data[i] + NET_SKB_PAD + eth->ip_align, + ring->buf_size, + DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, dma_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + ring->dma[i].rxd1 = (unsigned int)dma_addr; + +@@ -1770,7 +1771,7 @@ static void mtk_rx_clean(struct mtk_eth + continue; + if (!ring->dma[i].rxd1) + continue; +- dma_unmap_single(eth->dev, ++ dma_unmap_single(eth->dma_dev, + ring->dma[i].rxd1, + ring->buf_size, + DMA_FROM_DEVICE); +@@ -1781,7 +1782,7 @@ static void mtk_rx_clean(struct mtk_eth + } + + if (ring->dma) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + ring->dma_size * sizeof(*ring->dma), + ring->dma, + ring->phys); +@@ -2134,7 +2135,7 @@ static void mtk_dma_free(struct mtk_eth + if (eth->netdev[i]) + netdev_reset_queue(eth->netdev[i]); + if (eth->scratch_ring) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + MTK_DMA_SIZE * sizeof(struct mtk_tx_dma), + eth->scratch_ring, + eth->phy_scratch_ring); +@@ -2482,6 +2483,8 @@ static void mtk_dim_tx(struct work_struc + + static int mtk_hw_init(struct mtk_eth *eth) + { ++ u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | ++ ETHSYS_DMA_AG_MAP_PPE; + int i, val, ret; + + if (test_and_set_bit(MTK_HW_INIT, ð->state)) +@@ -2494,6 +2497,10 @@ static int mtk_hw_init(struct mtk_eth *e + if (ret) + goto err_disable_pm; + ++ if (eth->ethsys) ++ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, dma_mask, ++ of_dma_is_coherent(eth->dma_dev->of_node) * dma_mask); ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { + ret = device_reset(eth->dev); + if (ret) { +@@ -3043,6 +3050,35 @@ free_netdev: + return err; + } + ++void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) ++{ ++ struct net_device *dev, *tmp; ++ LIST_HEAD(dev_list); ++ int i; ++ ++ rtnl_lock(); ++ ++ for (i = 0; i < MTK_MAC_COUNT; i++) { ++ dev = eth->netdev[i]; ++ ++ if (!dev || !(dev->flags & IFF_UP)) ++ continue; ++ ++ list_add_tail(&dev->close_list, &dev_list); ++ } ++ ++ dev_close_many(&dev_list, false); ++ ++ eth->dma_dev = dma_dev; ++ ++ list_for_each_entry_safe(dev, tmp, &dev_list, close_list) { ++ list_del_init(&dev->close_list); ++ dev_open(dev, NULL); ++ } ++ ++ rtnl_unlock(); ++} ++ + static int mtk_probe(struct platform_device *pdev) + { + struct device_node *mac_np; +@@ -3056,6 +3092,7 @@ static int mtk_probe(struct platform_dev + eth->soc = of_device_get_match_data(&pdev->dev); + + eth->dev = &pdev->dev; ++ eth->dma_dev = &pdev->dev; + eth->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(eth->base)) + return PTR_ERR(eth->base); +@@ -3104,6 +3141,16 @@ static int mtk_probe(struct platform_dev + } + } + ++ if (of_dma_is_coherent(pdev->dev.of_node)) { ++ struct regmap *cci; ++ ++ cci = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, ++ "mediatek,cci-control"); ++ /* enable CPU/bus coherency */ ++ if (!IS_ERR(cci)) ++ regmap_write(cci, 0, 3); ++ } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { + eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), + GFP_KERNEL); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -456,6 +456,12 @@ + #define RSTCTRL_FE BIT(6) + #define RSTCTRL_PPE BIT(31) + ++/* ethernet dma channel agent map */ ++#define ETHSYS_DMA_AG_MAP 0x408 ++#define ETHSYS_DMA_AG_MAP_PDMA BIT(0) ++#define ETHSYS_DMA_AG_MAP_QDMA BIT(1) ++#define ETHSYS_DMA_AG_MAP_PPE BIT(2) ++ + /* SGMII subsystem config registers */ + /* Register to auto-negotiation restart */ + #define SGMSYS_PCS_CONTROL_1 0x0 +@@ -873,6 +879,7 @@ struct mtk_sgmii { + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver + * @dev: The device pointer ++ * @dev: The device pointer used for dma mapping/alloc + * @base: The mapped register i/o base + * @page_lock: Make sure that register operations are atomic + * @tx_irq__lock: Make sure that IRQ register operations are atomic +@@ -916,6 +923,7 @@ struct mtk_sgmii { + + struct mtk_eth { + struct device *dev; ++ struct device *dma_dev; + void __iomem *base; + spinlock_t page_lock; + spinlock_t tx_irq_lock; +@@ -1014,6 +1022,7 @@ int mtk_gmac_rgmii_path_setup(struct mtk + int mtk_eth_offload_init(struct mtk_eth *eth); + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data); ++void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); + + + #endif /* MTK_ETH_H */ diff --git a/target/linux/generic/pending-5.10/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch b/target/linux/generic/pending-5.10/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch new file mode 100644 index 0000000000..892e01aece --- /dev/null +++ b/target/linux/generic/pending-5.10/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch @@ -0,0 +1,30 @@ +From: Felix Fietkau +Date: Mon, 7 Feb 2022 10:27:22 +0100 +Subject: [PATCH] arm64: dts: mediatek: mt7622: add support for coherent + DMA + +It improves performance by eliminating the need for a cache flush on rx and tx + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -357,7 +357,7 @@ + }; + + cci_control2: slave-if@5000 { +- compatible = "arm,cci-400-ctrl-if"; ++ compatible = "arm,cci-400-ctrl-if", "syscon"; + interface-type = "ace"; + reg = <0x5000 0x1000>; + }; +@@ -936,6 +936,8 @@ + power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys>; ++ mediatek,cci-control = <&cci_control2>; ++ dma-coherent; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; diff --git a/target/linux/generic/pending-5.10/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch b/target/linux/generic/pending-5.10/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch new file mode 100644 index 0000000000..874f9a8a04 --- /dev/null +++ b/target/linux/generic/pending-5.10/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch @@ -0,0 +1,1679 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 17:56:08 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for Wireless + Ethernet Dispatch (WED) + +The Wireless Ethernet Dispatch subsystem on the MT7622 SoC can be +configured to intercept and handle access to the DMA queues and +PCIe interrupts for a MT7615/MT7915 wireless card. +It can manage the internal WDMA (Wireless DMA) controller, which allows +ethernet packets to be passed from the packet switch engine (PSE) to the +wireless card, bypassing the CPU entirely. +This can be used to implement hardware flow offloading from ethernet to +WLAN. + +Signed-off-by: Felix Fietkau +--- + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed.h + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_debugfs.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ops.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_regs.h + create mode 100644 include/linux/soc/mediatek/mtk_wed.h + +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -7,6 +7,10 @@ config NET_VENDOR_MEDIATEK + + if NET_VENDOR_MEDIATEK + ++config NET_MEDIATEK_SOC_WED ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ def_bool NET_MEDIATEK_SOC != n ++ + config NET_MEDIATEK_SOC + tristate "MediaTek SoC Gigabit Ethernet support" + select PHYLINK +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -5,4 +5,9 @@ + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o + mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o ++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o ++ifdef CONFIG_DEBUG_FS ++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o ++endif ++obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o + obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -24,6 +24,7 @@ + #include + + #include "mtk_eth_soc.h" ++#include "mtk_wed.h" + + static int mtk_msg_level = -1; + module_param_named(msg_level, mtk_msg_level, int, 0); +@@ -3173,6 +3174,22 @@ static int mtk_probe(struct platform_dev + } + } + ++ for (i = 0;; i++) { ++ struct device_node *np = of_parse_phandle(pdev->dev.of_node, ++ "mediatek,wed", i); ++ static const u32 wdma_regs[] = { ++ MTK_WDMA0_BASE, ++ MTK_WDMA1_BASE ++ }; ++ void __iomem *wdma; ++ ++ if (!np || i >= ARRAY_SIZE(wdma_regs)) ++ break; ++ ++ wdma = eth->base + wdma_regs[i]; ++ mtk_wed_add_hw(np, eth, wdma, i); ++ } ++ + for (i = 0; i < 3; i++) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) + eth->irq[i] = eth->irq[0]; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -295,6 +295,9 @@ + #define MTK_GDM1_TX_GPCNT 0x2438 + #define MTK_STAT_OFFSET 0x40 + ++#define MTK_WDMA0_BASE 0x2800 ++#define MTK_WDMA1_BASE 0x2c00 ++ + /* QDMA descriptor txd4 */ + #define TX_DMA_CHKSUM (0x7 << 29) + #define TX_DMA_TSO BIT(28) +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -0,0 +1,875 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2021 Felix Fietkau */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mtk_eth_soc.h" ++#include "mtk_wed_regs.h" ++#include "mtk_wed.h" ++#include "mtk_ppe.h" ++ ++#define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) ++ ++#define MTK_WED_PKT_SIZE 1900 ++#define MTK_WED_BUF_SIZE 2048 ++#define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) ++ ++#define MTK_WED_TX_RING_SIZE 2048 ++#define MTK_WED_WDMA_RING_SIZE 1024 ++ ++static struct mtk_wed_hw *hw_list[2]; ++static DEFINE_MUTEX(hw_lock); ++ ++static void ++wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) ++{ ++ regmap_update_bits(dev->hw->regs, reg, mask | val, val); ++} ++ ++static void ++wed_set(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ return wed_m32(dev, reg, 0, mask); ++} ++ ++static void ++wed_clr(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ return wed_m32(dev, reg, mask, 0); ++} ++ ++static void ++wdma_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) ++{ ++ wdma_w32(dev, reg, (wdma_r32(dev, reg) & ~mask) | val); ++} ++ ++static void ++wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ wdma_m32(dev, reg, 0, mask); ++} ++ ++static u32 ++mtk_wed_read_reset(struct mtk_wed_device *dev) ++{ ++ return wed_r32(dev, MTK_WED_RESET); ++} ++ ++static void ++mtk_wed_reset(struct mtk_wed_device *dev, u32 mask) ++{ ++ u32 status; ++ ++ wed_w32(dev, MTK_WED_RESET, mask); ++ if (readx_poll_timeout(mtk_wed_read_reset, dev, status, ++ !(status & mask), 0, 1000)) ++ WARN_ON_ONCE(1); ++} ++ ++static struct mtk_wed_hw * ++mtk_wed_assign(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_hw *hw; ++ ++ hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)]; ++ if (!hw || hw->wed_dev) ++ return NULL; ++ ++ hw->wed_dev = dev; ++ return hw; ++} ++ ++static int ++mtk_wed_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ void **page_list; ++ int token = dev->wlan.token_start; ++ int ring_size; ++ int n_pages; ++ int i, page_idx; ++ ++ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); ++ n_pages = ring_size / MTK_WED_BUF_PER_PAGE; ++ ++ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL); ++ if (!page_list) ++ return -ENOMEM; ++ ++ dev->buf_ring.size = ring_size; ++ dev->buf_ring.pages = page_list; ++ ++ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), ++ &desc_phys, GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ dev->buf_ring.desc = desc; ++ dev->buf_ring.desc_phys = desc_phys; ++ ++ for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { ++ dma_addr_t page_phys, buf_phys; ++ struct page *page; ++ void *buf; ++ int s; ++ ++ page = __dev_alloc_pages(GFP_KERNEL, 0); ++ if (!page) ++ return -ENOMEM; ++ ++ page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(dev->hw->dev, page_phys)) { ++ __free_page(page); ++ return -ENOMEM; ++ } ++ ++ page_list[page_idx++] = page; ++ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ ++ buf = page_to_virt(page); ++ buf_phys = page_phys; ++ ++ for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) { ++ u32 txd_size; ++ ++ txd_size = dev->wlan.init_buf(buf, buf_phys, token++); ++ ++ desc->buf0 = buf_phys; ++ desc->buf1 = buf_phys + txd_size; ++ desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, ++ txd_size) | ++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, ++ MTK_WED_BUF_SIZE - txd_size) | ++ MTK_WDMA_DESC_CTRL_LAST_SEG1; ++ desc->info = 0; ++ desc++; ++ ++ buf += MTK_WED_BUF_SIZE; ++ buf_phys += MTK_WED_BUF_SIZE; ++ } ++ ++ dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ } ++ ++ return 0; ++} ++ ++static void ++mtk_wed_free_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_wdma_desc *desc = dev->buf_ring.desc; ++ void **page_list = dev->buf_ring.pages; ++ int page_idx; ++ int i; ++ ++ if (!page_list) ++ return; ++ ++ if (!desc) ++ goto free_pagelist; ++ ++ for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { ++ void *page = page_list[page_idx++]; ++ ++ if (!page) ++ break; ++ ++ dma_unmap_page(dev->hw->dev, desc[i].buf0, ++ PAGE_SIZE, DMA_BIDIRECTIONAL); ++ __free_page(page); ++ } ++ ++ dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc), ++ desc, dev->buf_ring.desc_phys); ++ ++free_pagelist: ++ kfree(page_list); ++} ++ ++static void ++mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring) ++{ ++ if (!ring->desc) ++ return; ++ ++ dma_free_coherent(dev->hw->dev, ring->size * sizeof(*ring->desc), ++ ring->desc, ring->desc_phys); ++} ++ ++static void ++mtk_wed_free_tx_rings(struct mtk_wed_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) ++ mtk_wed_free_ring(dev, &dev->tx_ring[i]); ++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) ++ mtk_wed_free_ring(dev, &dev->tx_wdma[i]); ++} ++ ++static void ++mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en) ++{ ++ u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; ++ ++ if (!dev->hw->num_flows) ++ mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; ++ ++ wed_w32(dev, MTK_WED_EXT_INT_MASK, en ? mask : 0); ++ wed_r32(dev, MTK_WED_EXT_INT_MASK); ++} ++ ++static void ++mtk_wed_stop(struct mtk_wed_device *dev) ++{ ++ regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); ++ mtk_wed_set_ext_int(dev, false); ++ ++ wed_clr(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); ++ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); ++ wdma_w32(dev, MTK_WDMA_INT_MASK, 0); ++ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); ++ ++ wed_clr(dev, MTK_WED_GLO_CFG, ++ MTK_WED_GLO_CFG_TX_DMA_EN | ++ MTK_WED_GLO_CFG_RX_DMA_EN); ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++} ++ ++static void ++mtk_wed_detach(struct mtk_wed_device *dev) ++{ ++ struct device_node *wlan_node = dev->wlan.pci_dev->dev.of_node; ++ struct mtk_wed_hw *hw = dev->hw; ++ ++ mutex_lock(&hw_lock); ++ ++ mtk_wed_stop(dev); ++ ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ ++ mtk_wed_free_buffer(dev); ++ mtk_wed_free_tx_rings(dev); ++ ++ if (of_dma_is_coherent(wlan_node)) ++ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, ++ BIT(hw->index), BIT(hw->index)); ++ ++ if (!hw_list[!hw->index]->wed_dev && ++ hw->eth->dma_dev != hw->eth->dev) ++ mtk_eth_set_dma_device(hw->eth, hw->eth->dev); ++ ++ memset(dev, 0, sizeof(*dev)); ++ module_put(THIS_MODULE); ++ ++ hw->wed_dev = NULL; ++ mutex_unlock(&hw_lock); ++} ++ ++static void ++mtk_wed_hw_init_early(struct mtk_wed_device *dev) ++{ ++ u32 mask, set; ++ u32 offset; ++ ++ mtk_wed_stop(dev); ++ mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ ++ mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE | ++ MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE | ++ MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE; ++ set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) | ++ MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP | ++ MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; ++ wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); ++ ++ wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO_PRERES); ++ ++ offset = dev->hw->index ? 0x04000400 : 0; ++ wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset); ++ wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset); ++ ++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, MTK_PCIE_BASE(dev->hw->index)); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); ++} ++ ++static void ++mtk_wed_hw_init(struct mtk_wed_device *dev) ++{ ++ if (dev->init_done) ++ return; ++ ++ dev->init_done = true; ++ mtk_wed_set_ext_int(dev, false); ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++ dev->buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); ++ ++ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys); ++ ++ wed_w32(dev, MTK_WED_TX_BM_TKID, ++ FIELD_PREP(MTK_WED_TX_BM_TKID_START, ++ dev->wlan.token_start) | ++ FIELD_PREP(MTK_WED_TX_BM_TKID_END, ++ dev->wlan.token_start + dev->wlan.nbuf - 1)); ++ ++ wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); ++ ++ wed_w32(dev, MTK_WED_TX_BM_DYN_THR, ++ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) | ++ MTK_WED_TX_BM_DYN_THR_HI); ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); ++ ++ wed_set(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ ++ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); ++} ++ ++static void ++mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i++) { ++ desc[i].buf0 = 0; ++ desc[i].ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ desc[i].buf1 = 0; ++ desc[i].info = 0; ++ } ++} ++ ++static u32 ++mtk_wed_check_busy(struct mtk_wed_device *dev) ++{ ++ if (wed_r32(dev, MTK_WED_GLO_CFG) & MTK_WED_GLO_CFG_TX_DMA_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_WPDMA_GLO_CFG) & ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_CTRL) & MTK_WED_CTRL_WDMA_INT_AGENT_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_WDMA_GLO_CFG) & ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) ++ return true; ++ ++ if (wdma_r32(dev, MTK_WDMA_GLO_CFG) & ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_CTRL) & ++ (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY)) ++ return true; ++ ++ return false; ++} ++ ++static int ++mtk_wed_poll_busy(struct mtk_wed_device *dev) ++{ ++ int sleep = 15000; ++ int timeout = 100 * sleep; ++ u32 val; ++ ++ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, ++ timeout, false, dev); ++} ++ ++static void ++mtk_wed_reset_dma(struct mtk_wed_device *dev) ++{ ++ bool busy = false; ++ u32 val; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) { ++ struct mtk_wdma_desc *desc = dev->tx_ring[i].desc; ++ ++ if (!desc) ++ continue; ++ ++ mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE); ++ } ++ ++ if (mtk_wed_poll_busy(dev)) ++ busy = mtk_wed_check_busy(dev); ++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); ++ } else { ++ wed_w32(dev, MTK_WED_RESET_IDX, ++ MTK_WED_RESET_IDX_TX | ++ MTK_WED_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_RESET_IDX, 0); ++ } ++ ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); ++ } else { ++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, ++ MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV); ++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0); ++ ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); ++ ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); ++ } ++ ++ for (i = 0; i < 100; i++) { ++ val = wed_r32(dev, MTK_WED_TX_BM_INTF); ++ if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) ++ break; ++ } ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); ++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV); ++ } else { ++ wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, ++ MTK_WED_WPDMA_RESET_IDX_TX | ++ MTK_WED_WPDMA_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); ++ } ++ ++} ++ ++static int ++mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, ++ int size) ++{ ++ ring->desc = dma_alloc_coherent(dev->hw->dev, ++ size * sizeof(*ring->desc), ++ &ring->desc_phys, GFP_KERNEL); ++ if (!ring->desc) ++ return -ENOMEM; ++ ++ ring->size = size; ++ mtk_wed_ring_reset(ring->desc, size); ++ ++ return 0; ++} ++ ++static int ++mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++{ ++ struct mtk_wed_ring *wdma = &dev->tx_wdma[idx]; ++ ++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE)) ++ return -ENOMEM; ++ ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, ++ wdma->desc_phys); ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT, ++ size); ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ ++ wed_w32(dev, MTK_WED_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, ++ wdma->desc_phys); ++ wed_w32(dev, MTK_WED_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT, ++ size); ++ ++ return 0; ++} ++ ++static void ++mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask) ++{ ++ u32 wdma_mask; ++ u32 val; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) ++ if (!dev->tx_wdma[i].desc) ++ mtk_wed_wdma_ring_setup(dev, i, 16); ++ ++ wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0)); ++ ++ mtk_wed_hw_init(dev); ++ ++ wed_set(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ ++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, MTK_WED_PCIE_INT_TRIGGER_STATUS); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, ++ MTK_WED_WPDMA_INT_TRIGGER_RX_DONE | ++ MTK_WED_WPDMA_INT_TRIGGER_TX_DONE); ++ ++ wed_set(dev, MTK_WED_WPDMA_INT_CTRL, ++ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); ++ ++ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask); ++ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); ++ ++ wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask); ++ wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask); ++ wed_w32(dev, MTK_WED_INT_MASK, irq_mask); ++ ++ wed_set(dev, MTK_WED_GLO_CFG, ++ MTK_WED_GLO_CFG_TX_DMA_EN | ++ MTK_WED_GLO_CFG_RX_DMA_EN); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ ++ mtk_wed_set_ext_int(dev, true); ++ val = dev->wlan.wpdma_phys | ++ MTK_PCIE_MIRROR_MAP_EN | ++ FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index); ++ ++ if (dev->hw->index) ++ val |= BIT(1); ++ val |= BIT(0); ++ regmap_write(dev->hw->mirror, dev->hw->index * 4, val); ++ ++ dev->running = true; ++} ++ ++static int ++mtk_wed_attach(struct mtk_wed_device *dev) ++ __releases(RCU) ++{ ++ struct mtk_wed_hw *hw; ++ int ret = 0; ++ ++ RCU_LOCKDEP_WARN(!rcu_read_lock_held(), ++ "mtk_wed_attach without holding the RCU read lock"); ++ ++ if (pci_domain_nr(dev->wlan.pci_dev->bus) > 1 || ++ !try_module_get(THIS_MODULE)) ++ ret = -ENODEV; ++ ++ rcu_read_unlock(); ++ ++ if (ret) ++ return ret; ++ ++ mutex_lock(&hw_lock); ++ ++ hw = mtk_wed_assign(dev); ++ if (!hw) { ++ module_put(THIS_MODULE); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ dev_info(&dev->wlan.pci_dev->dev, "attaching wed device %d\n", hw->index); ++ ++ dev->hw = hw; ++ dev->dev = hw->dev; ++ dev->irq = hw->irq; ++ dev->wdma_idx = hw->index; ++ ++ if (hw->eth->dma_dev == hw->eth->dev && ++ of_dma_is_coherent(hw->eth->dev->of_node)) ++ mtk_eth_set_dma_device(hw->eth, hw->dev); ++ ++ ret = mtk_wed_buffer_alloc(dev); ++ if (ret) { ++ mtk_wed_detach(dev); ++ goto out; ++ } ++ ++ mtk_wed_hw_init_early(dev); ++ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, BIT(hw->index), 0); ++ ++out: ++ mutex_unlock(&hw_lock); ++ ++ return ret; ++} ++ ++static int ++mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->tx_ring[idx]; ++ ++ /* ++ * Tx ring redirection: ++ * Instead of configuring the WLAN PDMA TX ring directly, the WLAN ++ * driver allocated DMA ring gets configured into WED MTK_WED_RING_TX(n) ++ * registers. ++ * ++ * WED driver posts its own DMA ring as WLAN PDMA TX and configures it ++ * into MTK_WED_WPDMA_RING_TX(n) registers. ++ * It gets filled with packets picked up from WED TX ring and from ++ * WDMA RX. ++ */ ++ ++ BUG_ON(idx > ARRAY_SIZE(dev->tx_ring)); ++ ++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE)) ++ return -ENOMEM; ++ ++ if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ return -ENOMEM; ++ ++ ring->reg_base = MTK_WED_RING_TX(idx); ++ ring->wpdma = regs; ++ ++ /* WED -> WPDMA */ ++ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); ++ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_TX_RING_SIZE); ++ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_CPU_IDX, 0); ++ ++ wed_w32(dev, MTK_WED_WPDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, ++ ring->desc_phys); ++ wed_w32(dev, MTK_WED_WPDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, ++ MTK_WED_TX_RING_SIZE); ++ wed_w32(dev, MTK_WED_WPDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ ++ return 0; ++} ++ ++static int ++mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->txfree_ring; ++ int i; ++ ++ /* ++ * For txfree event handling, the same DMA ring is shared between WED ++ * and WLAN. The WLAN driver accesses the ring index registers through ++ * WED ++ */ ++ ring->reg_base = MTK_WED_RING_RX(1); ++ ring->wpdma = regs; ++ ++ for (i = 0; i < 12; i += 4) { ++ u32 val = readl(regs + i); ++ ++ wed_w32(dev, MTK_WED_RING_RX(1) + i, val); ++ wed_w32(dev, MTK_WED_WPDMA_RING_RX(1) + i, val); ++ } ++ ++ return 0; ++} ++ ++static u32 ++mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) ++{ ++ u32 val; ++ ++ val = wed_r32(dev, MTK_WED_EXT_INT_STATUS); ++ wed_w32(dev, MTK_WED_EXT_INT_STATUS, val); ++ val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK; ++ if (!dev->hw->num_flows) ++ val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; ++ if (val && net_ratelimit()) ++ pr_err("mtk_wed%d: error status=%08x\n", dev->hw->index, val); ++ ++ val = wed_r32(dev, MTK_WED_INT_STATUS); ++ val &= mask; ++ wed_w32(dev, MTK_WED_INT_STATUS, val); /* ACK */ ++ ++ return val; ++} ++ ++static void ++mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) ++{ ++ if (!dev->running) ++ return; ++ ++ mtk_wed_set_ext_int(dev, !!mask); ++ wed_w32(dev, MTK_WED_INT_MASK, mask); ++} ++ ++int mtk_wed_flow_add(int index) ++{ ++ struct mtk_wed_hw *hw = hw_list[index]; ++ int ret; ++ ++ if (!hw || !hw->wed_dev) ++ return -ENODEV; ++ ++ if (hw->num_flows) { ++ hw->num_flows++; ++ return 0; ++ } ++ ++ mutex_lock(&hw_lock); ++ if (!hw->wed_dev) { ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ ret = hw->wed_dev->wlan.offload_enable(hw->wed_dev); ++ if (!ret) ++ hw->num_flows++; ++ mtk_wed_set_ext_int(hw->wed_dev, true); ++ ++out: ++ mutex_unlock(&hw_lock); ++ ++ return ret; ++} ++ ++void mtk_wed_flow_remove(int index) ++{ ++ struct mtk_wed_hw *hw = hw_list[index]; ++ ++ if (!hw) ++ return; ++ ++ if (--hw->num_flows) ++ return; ++ ++ mutex_lock(&hw_lock); ++ if (!hw->wed_dev) ++ goto out; ++ ++ hw->wed_dev->wlan.offload_disable(hw->wed_dev); ++ mtk_wed_set_ext_int(hw->wed_dev, true); ++ ++out: ++ mutex_unlock(&hw_lock); ++} ++ ++void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, ++ void __iomem *wdma, int index) ++{ ++ static const struct mtk_wed_ops wed_ops = { ++ .attach = mtk_wed_attach, ++ .tx_ring_setup = mtk_wed_tx_ring_setup, ++ .txfree_ring_setup = mtk_wed_txfree_ring_setup, ++ .start = mtk_wed_start, ++ .stop = mtk_wed_stop, ++ .reset_dma = mtk_wed_reset_dma, ++ .reg_read = wed_r32, ++ .reg_write = wed_w32, ++ .irq_get = mtk_wed_irq_get, ++ .irq_set_mask = mtk_wed_irq_set_mask, ++ .detach = mtk_wed_detach, ++ }; ++ struct device_node *eth_np = eth->dev->of_node; ++ struct platform_device *pdev; ++ struct mtk_wed_hw *hw; ++ struct regmap *regs; ++ int irq; ++ ++ if (!np) ++ return; ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev) ++ return; ++ ++ get_device(&pdev->dev); ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return; ++ ++ regs = syscon_regmap_lookup_by_phandle(np, NULL); ++ if (!regs) ++ return; ++ ++ rcu_assign_pointer(mtk_soc_wed_ops, &wed_ops); ++ ++ mutex_lock(&hw_lock); ++ ++ if (WARN_ON(hw_list[index])) ++ goto unlock; ++ ++ hw = kzalloc(sizeof(*hw), GFP_KERNEL); ++ hw->node = np; ++ hw->regs = regs; ++ hw->eth = eth; ++ hw->dev = &pdev->dev; ++ hw->wdma = wdma; ++ hw->index = index; ++ hw->irq = irq; ++ hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, ++ "mediatek,pcie-mirror"); ++ hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, ++ "mediatek,hifsys"); ++ if (IS_ERR(hw->mirror) || IS_ERR(hw->hifsys)) { ++ kfree(hw); ++ goto unlock; ++ } ++ ++ if (!index) { ++ regmap_write(hw->mirror, 0, 0); ++ regmap_write(hw->mirror, 4, 0); ++ } ++ mtk_wed_hw_add_debugfs(hw); ++ ++ hw_list[index] = hw; ++ ++unlock: ++ mutex_unlock(&hw_lock); ++} ++ ++void mtk_wed_exit(void) ++{ ++ int i; ++ ++ rcu_assign_pointer(mtk_soc_wed_ops, NULL); ++ ++ synchronize_rcu(); ++ ++ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { ++ struct mtk_wed_hw *hw; ++ ++ hw = hw_list[i]; ++ if (!hw) ++ continue; ++ ++ hw_list[i] = NULL; ++ debugfs_remove(hw->debugfs_dir); ++ put_device(hw->dev); ++ kfree(hw); ++ } ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -0,0 +1,128 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2021 Felix Fietkau */ ++ ++#ifndef __MTK_WED_PRIV_H ++#define __MTK_WED_PRIV_H ++ ++#include ++#include ++#include ++ ++struct mtk_eth; ++ ++struct mtk_wed_hw { ++ struct device_node *node; ++ struct mtk_eth *eth; ++ struct regmap *regs; ++ struct regmap *hifsys; ++ struct device *dev; ++ void __iomem *wdma; ++ struct regmap *mirror; ++ struct dentry *debugfs_dir; ++ struct mtk_wed_device *wed_dev; ++ u32 debugfs_reg; ++ u32 num_flows; ++ char dirname[5]; ++ int irq; ++ int index; ++}; ++ ++ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++static inline void ++wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ regmap_write(dev->hw->regs, reg, val); ++} ++ ++static inline u32 ++wed_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ unsigned int val; ++ ++ regmap_read(dev->hw->regs, reg, &val); ++ ++ return val; ++} ++ ++static inline void ++wdma_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ writel(val, dev->hw->wdma + reg); ++} ++ ++static inline u32 ++wdma_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ return readl(dev->hw->wdma + reg); ++} ++ ++static inline u32 ++wpdma_tx_r32(struct mtk_wed_device *dev, int ring, u32 reg) ++{ ++ if (!dev->tx_ring[ring].wpdma) ++ return 0; ++ ++ return readl(dev->tx_ring[ring].wpdma + reg); ++} ++ ++static inline void ++wpdma_tx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val) ++{ ++ if (!dev->tx_ring[ring].wpdma) ++ return; ++ ++ writel(val, dev->tx_ring[ring].wpdma + reg); ++} ++ ++static inline u32 ++wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ if (!dev->txfree_ring.wpdma) ++ return 0; ++ ++ return readl(dev->txfree_ring.wpdma + reg); ++} ++ ++static inline void ++wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ if (!dev->txfree_ring.wpdma) ++ return; ++ ++ writel(val, dev->txfree_ring.wpdma + reg); ++} ++ ++void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, ++ void __iomem *wdma, int index); ++void mtk_wed_exit(void); ++int mtk_wed_flow_add(int index); ++void mtk_wed_flow_remove(int index); ++#else ++static inline void ++mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, ++ void __iomem *wdma, int index) ++{ ++} ++static inline void ++mtk_wed_exit(void) ++{ ++} ++static inline int mtk_wed_flow_add(int index) ++{ ++ return -EINVAL; ++} ++static inline void mtk_wed_flow_remove(int index) ++{ ++} ++#endif ++ ++#ifdef CONFIG_DEBUG_FS ++void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw); ++#else ++static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw) ++{ ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -0,0 +1,175 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2021 Felix Fietkau */ ++ ++#include ++#include "mtk_wed.h" ++#include "mtk_wed_regs.h" ++ ++struct reg_dump { ++ const char *name; ++ u16 offset; ++ u8 type; ++ u8 base; ++}; ++ ++enum { ++ DUMP_TYPE_STRING, ++ DUMP_TYPE_WED, ++ DUMP_TYPE_WDMA, ++ DUMP_TYPE_WPDMA_TX, ++ DUMP_TYPE_WPDMA_TXFREE, ++}; ++ ++#define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } ++#define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ } ++#define DUMP_RING(_prefix, _base, ...) \ ++ { _prefix " BASE", _base, __VA_ARGS__ }, \ ++ { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \ ++ { _prefix " CIDX", _base + 0x8, __VA_ARGS__ }, \ ++ { _prefix " DIDX", _base + 0xc, __VA_ARGS__ } ++ ++#define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED) ++#define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED) ++ ++#define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA) ++#define DUMP_WDMA_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WDMA) ++ ++#define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n) ++#define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE) ++ ++static void ++print_reg_val(struct seq_file *s, const char *name, u32 val) ++{ ++ seq_printf(s, "%-32s %08x\n", name, val); ++} ++ ++static void ++dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev, ++ const struct reg_dump *regs, int n_regs) ++{ ++ const struct reg_dump *cur; ++ u32 val; ++ ++ for (cur = regs; cur < ®s[n_regs]; cur++) { ++ switch (cur->type) { ++ case DUMP_TYPE_STRING: ++ seq_printf(s, "%s======== %s:\n", ++ cur > regs ? "\n" : "", ++ cur->name); ++ continue; ++ case DUMP_TYPE_WED: ++ val = wed_r32(dev, cur->offset); ++ break; ++ case DUMP_TYPE_WDMA: ++ val = wdma_r32(dev, cur->offset); ++ break; ++ case DUMP_TYPE_WPDMA_TX: ++ val = wpdma_tx_r32(dev, cur->base, cur->offset); ++ break; ++ case DUMP_TYPE_WPDMA_TXFREE: ++ val = wpdma_txfree_r32(dev, cur->offset); ++ break; ++ } ++ print_reg_val(s, cur->name, val); ++ } ++} ++ ++ ++static int ++wed_txinfo_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WED TX"), ++ DUMP_WED(WED_TX_MIB(0)), ++ DUMP_WED_RING(WED_RING_TX(0)), ++ ++ DUMP_WED(WED_TX_MIB(1)), ++ DUMP_WED_RING(WED_RING_TX(1)), ++ ++ DUMP_STR("WPDMA TX"), ++ DUMP_WED(WED_WPDMA_TX_MIB(0)), ++ DUMP_WED_RING(WED_WPDMA_RING_TX(0)), ++ DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(0)), ++ ++ DUMP_WED(WED_WPDMA_TX_MIB(1)), ++ DUMP_WED_RING(WED_WPDMA_RING_TX(1)), ++ DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(1)), ++ ++ DUMP_STR("WPDMA TX"), ++ DUMP_WPDMA_TX_RING(0), ++ DUMP_WPDMA_TX_RING(1), ++ ++ DUMP_STR("WED WDMA RX"), ++ DUMP_WED(WED_WDMA_RX_MIB(0)), ++ DUMP_WED_RING(WED_WDMA_RING_RX(0)), ++ DUMP_WED(WED_WDMA_RX_THRES(0)), ++ DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(0)), ++ DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(0)), ++ ++ DUMP_WED(WED_WDMA_RX_MIB(1)), ++ DUMP_WED_RING(WED_WDMA_RING_RX(1)), ++ DUMP_WED(WED_WDMA_RX_THRES(1)), ++ DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(1)), ++ DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(1)), ++ ++ DUMP_STR("WDMA RX"), ++ DUMP_WDMA(WDMA_GLO_CFG), ++ DUMP_WDMA_RING(WDMA_RING_RX(0)), ++ DUMP_WDMA_RING(WDMA_RING_RX(1)), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (!dev) ++ return 0; ++ ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_txinfo); ++ ++ ++static int ++mtk_wed_reg_set(void *data, u64 val) ++{ ++ struct mtk_wed_hw *hw = data; ++ ++ regmap_write(hw->regs, hw->debugfs_reg, val); ++ ++ return 0; ++} ++ ++static int ++mtk_wed_reg_get(void *data, u64 *val) ++{ ++ struct mtk_wed_hw *hw = data; ++ unsigned int regval; ++ int ret; ++ ++ ret = regmap_read(hw->regs, hw->debugfs_reg, ®val); ++ if (ret) ++ return ret; ++ ++ *val = regval; ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set, ++ "0x%08llx\n"); ++ ++void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw) ++{ ++ struct dentry *dir; ++ ++ snprintf(hw->dirname, sizeof(hw->dirname), "wed%d", hw->index); ++ dir = debugfs_create_dir(hw->dirname, NULL); ++ if (!dir) ++ return; ++ ++ hw->debugfs_dir = dir; ++ debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); ++ debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); ++ debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_ops.c +@@ -0,0 +1,8 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#include ++#include ++ ++const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; ++EXPORT_SYMBOL_GPL(mtk_soc_wed_ops); +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -0,0 +1,251 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#ifndef __MTK_WED_REGS_H ++#define __MTK_WED_REGS_H ++ ++#define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0) ++#define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15) ++#define MTK_WDMA_DESC_CTRL_BURST BIT(16) ++#define MTK_WDMA_DESC_CTRL_LEN0 GENMASK(29, 16) ++#define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30) ++#define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31) ++ ++struct mtk_wdma_desc { ++ __le32 buf0; ++ __le32 ctrl; ++ __le32 buf1; ++ __le32 info; ++} __packed __aligned(4); ++ ++#define MTK_WED_RESET 0x008 ++#define MTK_WED_RESET_TX_BM BIT(0) ++#define MTK_WED_RESET_TX_FREE_AGENT BIT(4) ++#define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) ++#define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) ++#define MTK_WED_RESET_WPDMA_INT_AGENT BIT(11) ++#define MTK_WED_RESET_WED_TX_DMA BIT(12) ++#define MTK_WED_RESET_WDMA_RX_DRV BIT(17) ++#define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) ++#define MTK_WED_RESET_WED BIT(31) ++ ++#define MTK_WED_CTRL 0x00c ++#define MTK_WED_CTRL_WPDMA_INT_AGENT_EN BIT(0) ++#define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY BIT(1) ++#define MTK_WED_CTRL_WDMA_INT_AGENT_EN BIT(2) ++#define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3) ++#define MTK_WED_CTRL_WED_TX_BM_EN BIT(8) ++#define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) ++#define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) ++#define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11) ++#define MTK_WED_CTRL_RESERVE_EN BIT(12) ++#define MTK_WED_CTRL_RESERVE_BUSY BIT(13) ++#define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) ++#define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) ++ ++#define MTK_WED_EXT_INT_STATUS 0x020 ++#define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR BIT(0) ++#define MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD BIT(1) ++#define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID BIT(4) ++#define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH BIT(8) ++#define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH BIT(9) ++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH BIT(12) ++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH BIT(13) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN BIT(19) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_BM_DMAD_COHERENT BIT(20) ++#define MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR BIT(21) ++#define MTK_WED_EXT_INT_STATUS_TX_DRV_W_RESP_ERR BIT(22) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_DMA_RECYCLE BIT(24) ++#define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \ ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \ ++ MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \ ++ MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \ ++ MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \ ++ MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \ ++ MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR | \ ++ MTK_WED_EXT_INT_STATUS_TX_DRV_W_RESP_ERR) ++ ++#define MTK_WED_EXT_INT_MASK 0x028 ++ ++#define MTK_WED_STATUS 0x060 ++#define MTK_WED_STATUS_TX GENMASK(15, 8) ++ ++#define MTK_WED_TX_BM_CTRL 0x080 ++#define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0) ++#define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16) ++#define MTK_WED_TX_BM_CTRL_PAUSE BIT(28) ++ ++#define MTK_WED_TX_BM_BASE 0x084 ++ ++#define MTK_WED_TX_BM_TKID 0x088 ++#define MTK_WED_TX_BM_TKID_START GENMASK(15, 0) ++#define MTK_WED_TX_BM_TKID_END GENMASK(31, 16) ++ ++#define MTK_WED_TX_BM_BUF_LEN 0x08c ++ ++#define MTK_WED_TX_BM_INTF 0x09c ++#define MTK_WED_TX_BM_INTF_TKID GENMASK(15, 0) ++#define MTK_WED_TX_BM_INTF_TKFIFO_FDEP GENMASK(23, 16) ++#define MTK_WED_TX_BM_INTF_TKID_VALID BIT(28) ++#define MTK_WED_TX_BM_INTF_TKID_READ BIT(29) ++ ++#define MTK_WED_TX_BM_DYN_THR 0x0a0 ++#define MTK_WED_TX_BM_DYN_THR_LO GENMASK(6, 0) ++#define MTK_WED_TX_BM_DYN_THR_HI GENMASK(22, 16) ++ ++#define MTK_WED_INT_STATUS 0x200 ++#define MTK_WED_INT_MASK 0x204 ++ ++#define MTK_WED_GLO_CFG 0x208 ++#define MTK_WED_GLO_CFG_TX_DMA_EN BIT(0) ++#define MTK_WED_GLO_CFG_TX_DMA_BUSY BIT(1) ++#define MTK_WED_GLO_CFG_RX_DMA_EN BIT(2) ++#define MTK_WED_GLO_CFG_RX_DMA_BUSY BIT(3) ++#define MTK_WED_GLO_CFG_RX_BT_SIZE GENMASK(5, 4) ++#define MTK_WED_GLO_CFG_TX_WB_DDONE BIT(6) ++#define MTK_WED_GLO_CFG_BIG_ENDIAN BIT(7) ++#define MTK_WED_GLO_CFG_DIS_BT_SIZE_ALIGN BIT(8) ++#define MTK_WED_GLO_CFG_TX_BT_SIZE_LO BIT(9) ++#define MTK_WED_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) ++#define MTK_WED_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) ++#define MTK_WED_GLO_CFG_MI_DEPTH_RD GENMASK(21, 13) ++#define MTK_WED_GLO_CFG_TX_BT_SIZE_HI GENMASK(23, 22) ++#define MTK_WED_GLO_CFG_SW_RESET BIT(24) ++#define MTK_WED_GLO_CFG_FIRST_TOKEN_ONLY BIT(26) ++#define MTK_WED_GLO_CFG_OMIT_RX_INFO BIT(27) ++#define MTK_WED_GLO_CFG_OMIT_TX_INFO BIT(28) ++#define MTK_WED_GLO_CFG_BYTE_SWAP BIT(29) ++#define MTK_WED_GLO_CFG_RX_2B_OFFSET BIT(31) ++ ++#define MTK_WED_RESET_IDX 0x20c ++#define MTK_WED_RESET_IDX_TX GENMASK(3, 0) ++#define MTK_WED_RESET_IDX_RX GENMASK(17, 16) ++ ++#define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) ++ ++#define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10) ++ ++#define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) ++ ++#define MTK_WED_WPDMA_INT_TRIGGER 0x504 ++#define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) ++#define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) ++ ++#define MTK_WED_WPDMA_GLO_CFG 0x508 ++#define MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN BIT(0) ++#define MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY BIT(1) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN BIT(2) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY BIT(3) ++#define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE GENMASK(5, 4) ++#define MTK_WED_WPDMA_GLO_CFG_TX_WB_DDONE BIT(6) ++#define MTK_WED_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) ++#define MTK_WED_WPDMA_GLO_CFG_DIS_BT_SIZE_ALIGN BIT(8) ++#define MTK_WED_WPDMA_GLO_CFG_TX_BT_SIZE_LO BIT(9) ++#define MTK_WED_WPDMA_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) ++#define MTK_WED_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) ++#define MTK_WED_WPDMA_GLO_CFG_MI_DEPTH_RD GENMASK(21, 13) ++#define MTK_WED_WPDMA_GLO_CFG_TX_BT_SIZE_HI GENMASK(23, 22) ++#define MTK_WED_WPDMA_GLO_CFG_SW_RESET BIT(24) ++#define MTK_WED_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY BIT(26) ++#define MTK_WED_WPDMA_GLO_CFG_OMIT_RX_INFO BIT(27) ++#define MTK_WED_WPDMA_GLO_CFG_OMIT_TX_INFO BIT(28) ++#define MTK_WED_WPDMA_GLO_CFG_BYTE_SWAP BIT(29) ++#define MTK_WED_WPDMA_GLO_CFG_RX_2B_OFFSET BIT(31) ++ ++#define MTK_WED_WPDMA_RESET_IDX 0x50c ++#define MTK_WED_WPDMA_RESET_IDX_TX GENMASK(3, 0) ++#define MTK_WED_WPDMA_RESET_IDX_RX GENMASK(17, 16) ++ ++#define MTK_WED_WPDMA_INT_CTRL 0x520 ++#define MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV BIT(21) ++ ++#define MTK_WED_WPDMA_INT_MASK 0x524 ++ ++#define MTK_WED_PCIE_CFG_BASE 0x560 ++ ++#define MTK_WED_PCIE_INT_TRIGGER 0x570 ++#define MTK_WED_PCIE_INT_TRIGGER_STATUS BIT(16) ++ ++#define MTK_WED_WPDMA_CFG_BASE 0x580 ++ ++#define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) ++#define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) ++ ++#define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) ++#define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) ++#define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) ++#define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) ++ ++#define MTK_WED_WDMA_GLO_CFG 0xa04 ++#define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) ++#define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2) ++#define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3) ++#define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4) ++#define MTK_WED_WDMA_GLO_CFG_TX_WB_DDONE BIT(6) ++#define MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE BIT(13) ++#define MTK_WED_WDMA_GLO_CFG_WCOMPLETE_SEL BIT(16) ++#define MTK_WED_WDMA_GLO_CFG_INIT_PHASE_RXDMA_BYPASS BIT(17) ++#define MTK_WED_WDMA_GLO_CFG_INIT_PHASE_BYPASS BIT(18) ++#define MTK_WED_WDMA_GLO_CFG_FSM_RETURN_IDLE BIT(19) ++#define MTK_WED_WDMA_GLO_CFG_WAIT_COHERENT BIT(20) ++#define MTK_WED_WDMA_GLO_CFG_AXI_W_AFTER_AW BIT(21) ++#define MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY_SINGLE_W BIT(22) ++#define MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY BIT(23) ++#define MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP BIT(24) ++#define MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE BIT(25) ++#define MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE BIT(26) ++#define MTK_WED_WDMA_GLO_CFG_RXDRV_CLKGATE_BYPASS BIT(30) ++ ++#define MTK_WED_WDMA_RESET_IDX 0xa08 ++#define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16) ++#define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24) ++ ++#define MTK_WED_WDMA_INT_TRIGGER 0xa28 ++#define MTK_WED_WDMA_INT_TRIGGER_RX_DONE GENMASK(17, 16) ++ ++#define MTK_WED_WDMA_INT_CTRL 0xa2c ++#define MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL GENMASK(17, 16) ++ ++#define MTK_WED_WDMA_OFFSET0 0xaa4 ++#define MTK_WED_WDMA_OFFSET1 0xaa8 ++ ++#define MTK_WED_WDMA_RX_MIB(_n) (0xae0 + (_n) * 4) ++#define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4) ++#define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4) ++ ++#define MTK_WED_RING_OFS_BASE 0x00 ++#define MTK_WED_RING_OFS_COUNT 0x04 ++#define MTK_WED_RING_OFS_CPU_IDX 0x08 ++#define MTK_WED_RING_OFS_DMA_IDX 0x0c ++ ++#define MTK_WDMA_RING_RX(_n) (0x100 + (_n) * 0x10) ++ ++#define MTK_WDMA_GLO_CFG 0x204 ++#define MTK_WDMA_GLO_CFG_RX_INFO_PRERES GENMASK(28, 26) ++ ++#define MTK_WDMA_RESET_IDX 0x208 ++#define MTK_WDMA_RESET_IDX_TX GENMASK(3, 0) ++#define MTK_WDMA_RESET_IDX_RX GENMASK(17, 16) ++ ++#define MTK_WDMA_INT_MASK 0x228 ++#define MTK_WDMA_INT_MASK_TX_DONE GENMASK(3, 0) ++#define MTK_WDMA_INT_MASK_RX_DONE GENMASK(17, 16) ++#define MTK_WDMA_INT_MASK_TX_DELAY BIT(28) ++#define MTK_WDMA_INT_MASK_TX_COHERENT BIT(29) ++#define MTK_WDMA_INT_MASK_RX_DELAY BIT(30) ++#define MTK_WDMA_INT_MASK_RX_COHERENT BIT(31) ++ ++#define MTK_WDMA_INT_GRP1 0x250 ++#define MTK_WDMA_INT_GRP2 0x254 ++ ++#define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0) ++#define MTK_PCIE_MIRROR_MAP_EN BIT(0) ++#define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1) ++ ++/* DMA channel mapping */ ++#define HIFSYS_DMA_AG_MAP 0x008 ++ ++#endif +--- /dev/null ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -0,0 +1,131 @@ ++#ifndef __MTK_WED_H ++#define __MTK_WED_H ++ ++#include ++#include ++#include ++#include ++ ++#define MTK_WED_TX_QUEUES 2 ++ ++struct mtk_wed_hw; ++struct mtk_wdma_desc; ++ ++struct mtk_wed_ring { ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ int size; ++ ++ u32 reg_base; ++ void __iomem *wpdma; ++}; ++ ++struct mtk_wed_device { ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ const struct mtk_wed_ops *ops; ++ struct device *dev; ++ struct mtk_wed_hw *hw; ++ bool init_done, running; ++ int wdma_idx; ++ int irq; ++ ++ struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; ++ struct mtk_wed_ring txfree_ring; ++ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; ++ ++ struct { ++ int size; ++ void **pages; ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ } buf_ring; ++ ++ /* filled by driver: */ ++ struct { ++ struct pci_dev *pci_dev; ++ ++ u32 wpdma_phys; ++ ++ u16 token_start; ++ unsigned int nbuf; ++ ++ u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); ++ int (*offload_enable)(struct mtk_wed_device *wed); ++ void (*offload_disable)(struct mtk_wed_device *wed); ++ } wlan; ++#endif ++}; ++ ++struct mtk_wed_ops { ++ int (*attach)(struct mtk_wed_device *dev); ++ int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); ++ int (*txfree_ring_setup)(struct mtk_wed_device *dev, ++ void __iomem *regs); ++ void (*detach)(struct mtk_wed_device *dev); ++ ++ void (*stop)(struct mtk_wed_device *dev); ++ void (*start)(struct mtk_wed_device *dev, u32 irq_mask); ++ void (*reset_dma)(struct mtk_wed_device *dev); ++ ++ u32 (*reg_read)(struct mtk_wed_device *dev, u32 reg); ++ void (*reg_write)(struct mtk_wed_device *dev, u32 reg, u32 val); ++ ++ u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask); ++ void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); ++}; ++ ++extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; ++ ++static inline int ++mtk_wed_device_attach(struct mtk_wed_device *dev) ++{ ++ int ret = -ENODEV; ++ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ rcu_read_lock(); ++ dev->ops = rcu_dereference(mtk_soc_wed_ops); ++ if (dev->ops) ++ ret = dev->ops->attach(dev); ++ else ++ rcu_read_unlock(); ++ ++ if (ret) ++ dev->ops = NULL; ++#endif ++ ++ return ret; ++} ++ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++#define mtk_wed_device_active(_dev) !!(_dev)->ops ++#define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) ++#define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask) ++#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_txfree_ring_setup(_dev, _regs) \ ++ (_dev)->ops->txfree_ring_setup(_dev, _regs) ++#define mtk_wed_device_reg_read(_dev, _reg) \ ++ (_dev)->ops->reg_read(_dev, _reg) ++#define mtk_wed_device_reg_write(_dev, _reg, _val) \ ++ (_dev)->ops->reg_write(_dev, _reg, _val) ++#define mtk_wed_device_irq_get(_dev, _mask) \ ++ (_dev)->ops->irq_get(_dev, _mask) ++#define mtk_wed_device_irq_set_mask(_dev, _mask) \ ++ (_dev)->ops->irq_set_mask(_dev, _mask) ++#else ++static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) ++{ ++ return false; ++} ++#define mtk_wed_device_detach(_dev) do {} while (0) ++#define mtk_wed_device_start(_dev, _mask) do {} while (0) ++#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_reg_read(_dev, _reg) 0 ++#define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) ++#define mtk_wed_device_irq_get(_dev, _mask) 0 ++#define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) ++#endif ++ ++#endif diff --git a/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch b/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch new file mode 100644 index 0000000000..1193cb0f9d --- /dev/null +++ b/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch @@ -0,0 +1,269 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 18:29:22 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: implement flow offloading + to WED devices + +This allows hardware flow offloading from Ethernet to WLAN on MT7622 SoC + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -329,6 +329,24 @@ int mtk_foe_entry_set_pppoe(struct mtk_f + return 0; + } + ++int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, ++ int bss, int wcid) ++{ ++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); ++ u32 *ib2 = mtk_foe_entry_ib2(entry); ++ ++ *ib2 &= ~MTK_FOE_IB2_PORT_MG; ++ *ib2 |= MTK_FOE_IB2_WDMA_WINFO; ++ if (wdma_idx) ++ *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX; ++ ++ l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | ++ FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | ++ FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); ++ ++ return 0; ++} ++ + static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry) + { + return !(entry->ib1 & MTK_FOE_IB1_STATIC) && +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -48,9 +48,9 @@ enum { + #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) + #define MTK_FOE_IB2_MULTICAST BIT(8) + +-#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12) +-#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16) +-#define MTK_FOE_IB2_WHNAT_NAT BIT(17) ++#define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) ++#define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) ++#define MTK_FOE_IB2_WDMA_WINFO BIT(17) + + #define MTK_FOE_IB2_PORT_MG GENMASK(17, 12) + +@@ -58,9 +58,9 @@ enum { + + #define MTK_FOE_IB2_DSCP GENMASK(31, 24) + +-#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0) +-#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6) +-#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14) ++#define MTK_FOE_VLAN2_WINFO_BSS GENMASK(5, 0) ++#define MTK_FOE_VLAN2_WINFO_WCID GENMASK(13, 6) ++#define MTK_FOE_VLAN2_WINFO_RING GENMASK(15, 14) + + enum { + MTK_FOE_STATE_INVALID, +@@ -281,6 +281,8 @@ int mtk_foe_entry_set_ipv6_tuple(struct + int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port); + int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); + int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); ++int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, ++ int bss, int wcid); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, + u16 timestamp); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -11,6 +11,7 @@ + #include + #include + #include "mtk_eth_soc.h" ++#include "mtk_wed.h" + + struct mtk_flow_data { + struct ethhdr eth; +@@ -40,6 +41,7 @@ struct mtk_flow_entry { + struct rhash_head node; + unsigned long cookie; + u16 hash; ++ s8 wed_index; + }; + + static const struct rhashtable_params mtk_flow_ht_params = { +@@ -81,6 +83,35 @@ mtk_flow_offload_mangle_eth(const struct + memcpy(dest, src, act->mangle.mask ? 2 : 4); + } + ++static int ++mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info) ++{ ++ struct net_device_path_ctx ctx = { ++ .dev = dev, ++ .daddr = addr, ++ }; ++ struct net_device_path path = {}; ++ ++ if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)) ++ return -1; ++ ++ if (!dev->netdev_ops->ndo_fill_forward_path) ++ return -1; ++ ++ if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path)) ++ return -1; ++ ++ if (path.type != DEV_PATH_MTK_WDMA) ++ return -1; ++ ++ info->wdma_idx = path.mtk_wdma.wdma_idx; ++ info->queue = path.mtk_wdma.queue; ++ info->bss = path.mtk_wdma.bss; ++ info->wcid = path.mtk_wdma.wcid; ++ ++ return 0; ++} ++ + + static int + mtk_flow_mangle_ports(const struct flow_action_entry *act, +@@ -150,10 +181,20 @@ mtk_flow_get_dsa_port(struct net_device + + static int + mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, +- struct net_device *dev) ++ struct net_device *dev, const u8 *dest_mac, ++ int *wed_index) + { ++ struct mtk_wdma_info info = {}; + int pse_port, dsa_port; + ++ if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { ++ mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss, ++ info.wcid); ++ pse_port = 3; ++ *wed_index = info.wdma_idx; ++ goto out; ++ } ++ + dsa_port = mtk_flow_get_dsa_port(&dev); + if (dsa_port >= 0) + mtk_foe_entry_set_dsa(foe, dsa_port); +@@ -165,6 +206,7 @@ mtk_flow_set_output_device(struct mtk_et + else + return -EOPNOTSUPP; + ++out: + mtk_foe_entry_set_pse_port(foe, pse_port); + + return 0; +@@ -180,6 +222,7 @@ mtk_flow_offload_replace(struct mtk_eth + struct net_device *odev = NULL; + struct mtk_flow_entry *entry; + int offload_type = 0; ++ int wed_index = -1; + u16 addr_type = 0; + u32 timestamp; + u8 l4proto = 0; +@@ -327,10 +370,14 @@ mtk_flow_offload_replace(struct mtk_eth + if (data.pppoe.num == 1) + mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); + +- err = mtk_flow_set_output_device(eth, &foe, odev); ++ err = mtk_flow_set_output_device(eth, &foe, odev, data.eth.h_dest, ++ &wed_index); + if (err) + return err; + ++ if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0) ++ return err; ++ + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; +@@ -344,6 +391,7 @@ mtk_flow_offload_replace(struct mtk_eth + } + + entry->hash = hash; ++ entry->wed_index = wed_index; + err = rhashtable_insert_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (err < 0) +@@ -354,6 +402,8 @@ clear_flow: + mtk_foe_entry_clear(ð->ppe, hash); + free: + kfree(entry); ++ if (wed_index >= 0) ++ mtk_wed_flow_remove(wed_index); + return err; + } + +@@ -370,6 +420,8 @@ mtk_flow_offload_destroy(struct mtk_eth + mtk_foe_entry_clear(ð->ppe, entry->hash); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); ++ if (entry->wed_index >= 0) ++ mtk_wed_flow_remove(entry->wed_index); + kfree(entry); + + return 0; +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + struct mtk_eth; + +@@ -27,6 +28,12 @@ struct mtk_wed_hw { + int index; + }; + ++struct mtk_wdma_info { ++ u8 wdma_idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++}; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + static inline void +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -833,6 +833,7 @@ enum net_device_path_type { + DEV_PATH_BRIDGE, + DEV_PATH_PPPOE, + DEV_PATH_DSA, ++ DEV_PATH_MTK_WDMA, + }; + + struct net_device_path { +@@ -858,6 +859,12 @@ struct net_device_path { + int port; + u16 proto; + } dsa; ++ struct { ++ u8 wdma_idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++ } mtk_wdma; + }; + }; + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -883,6 +883,10 @@ int dev_fill_forward_path(const struct n + if (WARN_ON_ONCE(last_dev == ctx.dev)) + return -1; + } ++ ++ if (!ctx.dev) ++ return ret; ++ + path = dev_fwd_path(stack); + if (!path) + return -1; diff --git a/target/linux/generic/pending-5.10/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch b/target/linux/generic/pending-5.10/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch new file mode 100644 index 0000000000..91d706f85b --- /dev/null +++ b/target/linux/generic/pending-5.10/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch @@ -0,0 +1,62 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 18:36:36 +0100 +Subject: [PATCH] arm64: dts: mediatek: mt7622: introduce nodes for + Wireless Ethernet Dispatch + +Introduce wed0 and wed1 nodes in order to enable offloading forwarding +between ethernet and wireless devices on the mt7622 chipset. + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -892,6 +892,11 @@ + }; + }; + ++ hifsys: syscon@1af00000 { ++ compatible = "mediatek,mt7622-hifsys", "syscon"; ++ reg = <0 0x1af00000 0 0x70>; ++ }; ++ + ethsys: syscon@1b000000 { + compatible = "mediatek,mt7622-ethsys", + "syscon"; +@@ -910,6 +915,26 @@ + #dma-cells = <1>; + }; + ++ pcie_mirror: pcie-mirror@10000400 { ++ compatible = "mediatek,mt7622-pcie-mirror", ++ "syscon"; ++ reg = <0 0x10000400 0 0x10>; ++ }; ++ ++ wed0: wed@1020a000 { ++ compatible = "mediatek,mt7622-wed", ++ "syscon"; ++ reg = <0 0x1020a000 0 0x1000>; ++ interrupts = ; ++ }; ++ ++ wed1: wed@1020b000 { ++ compatible = "mediatek,mt7622-wed", ++ "syscon"; ++ reg = <0 0x1020b000 0 0x1000>; ++ interrupts = ; ++ }; ++ + eth: ethernet@1b100000 { + compatible = "mediatek,mt7622-eth", + "mediatek,mt2701-eth", +@@ -937,6 +962,9 @@ + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys>; + mediatek,cci-control = <&cci_control2>; ++ mediatek,wed = <&wed0>, <&wed1>; ++ mediatek,pcie-mirror = <&pcie_mirror>; ++ mediatek,hifsys = <&hifsys>; + dma-coherent; + #address-cells = <1>; + #size-cells = <0>; diff --git a/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch b/target/linux/generic/pending-5.10/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch similarity index 67% rename from target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch rename to target/linux/generic/pending-5.10/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch index a36ae0e6e4..925c16ac69 100644 --- a/target/linux/generic/pending-5.15/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch +++ b/target/linux/generic/pending-5.10/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch @@ -1,14 +1,28 @@ +From: David Bentham +Date: Mon, 21 Feb 2022 15:36:16 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add ipv6 flow offload + support + +Add the missing IPv6 flow offloading support for routing only. +Hardware flow offloading is done by the packet processing engine (PPE) +of the Ethernet MAC and as it doesn't support mangling of IPv6 packets, +IPv6 NAT cannot be supported. + +Signed-off-by: David Bentham +Signed-off-by: Felix Fietkau +--- + --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -6,6 +6,7 @@ - #include +@@ -7,6 +7,7 @@ #include + #include #include +#include #include #include #include -@@ -19,6 +20,11 @@ struct mtk_flow_data { +@@ -21,6 +22,11 @@ struct mtk_flow_data { __be32 src_addr; __be32 dst_addr; } v4; @@ -20,7 +34,7 @@ }; __be16 src_port; -@@ -63,6 +69,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en +@@ -66,6 +72,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en data->v4.dst_addr, data->dst_port); } @@ -35,7 +49,7 @@ static void mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth) { -@@ -256,6 +270,9 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -297,6 +311,9 @@ mtk_flow_offload_replace(struct mtk_eth case FLOW_DISSECTOR_KEY_IPV4_ADDRS: offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; break; @@ -45,7 +59,7 @@ default: return -EOPNOTSUPP; } -@@ -291,6 +308,17 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -332,6 +349,17 @@ mtk_flow_offload_replace(struct mtk_eth mtk_flow_set_ipv4_addr(&foe, &data, false); } diff --git a/target/linux/generic/pending-5.10/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch b/target/linux/generic/pending-5.10/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch new file mode 100644 index 0000000000..1950d81ebb --- /dev/null +++ b/target/linux/generic/pending-5.10/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:37:21 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: support TC_SETUP_BLOCK for + PPE offload + +This allows offload entries to be created from user space + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -564,10 +564,13 @@ mtk_eth_setup_tc_block(struct net_device + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data) + { +- if (type == TC_SETUP_FT) ++ switch (type) { ++ case TC_SETUP_BLOCK: ++ case TC_SETUP_FT: + return mtk_eth_setup_tc_block(dev, type_data); +- +- return -EOPNOTSUPP; ++ default: ++ return -EOPNOTSUPP; ++ } + } + + int mtk_eth_offload_init(struct mtk_eth *eth) diff --git a/target/linux/generic/pending-5.10/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch b/target/linux/generic/pending-5.10/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch new file mode 100644 index 0000000000..a1c4fbfc55 --- /dev/null +++ b/target/linux/generic/pending-5.10/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch @@ -0,0 +1,159 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:38:20 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: allocate struct mtk_ppe + separately + +Preparation for adding more data to it, which will increase its size. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2305,7 +2305,7 @@ static int mtk_open(struct net_device *d + if (err) + return err; + +- if (eth->soc->offload_version && mtk_ppe_start(ð->ppe) == 0) ++ if (eth->soc->offload_version && mtk_ppe_start(eth->ppe) == 0) + gdm_config = MTK_GDMA_TO_PPE; + + mtk_gdm_config(eth, gdm_config); +@@ -2379,7 +2379,7 @@ static int mtk_stop(struct net_device *d + mtk_dma_free(eth); + + if (eth->soc->offload_version) +- mtk_ppe_stop(ð->ppe); ++ mtk_ppe_stop(eth->ppe); + + return 0; + } +@@ -3265,10 +3265,11 @@ static int mtk_probe(struct platform_dev + } + + if (eth->soc->offload_version) { +- err = mtk_ppe_init(ð->ppe, eth->dev, +- eth->base + MTK_ETH_PPE_BASE, 2); +- if (err) ++ eth->ppe = mtk_ppe_init(eth->dev, eth->base + MTK_ETH_PPE_BASE, 2); ++ if (!eth->ppe) { ++ err = -ENOMEM; + goto err_free_dev; ++ } + + err = mtk_eth_offload_init(eth); + if (err) +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -976,7 +976,7 @@ struct mtk_eth { + u32 rx_dma_l4_valid; + int ip_align; + +- struct mtk_ppe ppe; ++ struct mtk_ppe *ppe; + struct rhashtable flow_table; + }; + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -384,10 +384,15 @@ int mtk_foe_entry_commit(struct mtk_ppe + return hash; + } + +-int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, ++struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, + int version) + { + struct mtk_foe_entry *foe; ++ struct mtk_ppe *ppe; ++ ++ ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL); ++ if (!ppe) ++ return NULL; + + /* need to allocate a separate device, since it PPE DMA access is + * not coherent. +@@ -399,13 +404,13 @@ int mtk_ppe_init(struct mtk_ppe *ppe, st + foe = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*foe), + &ppe->foe_phys, GFP_KERNEL); + if (!foe) +- return -ENOMEM; ++ return NULL; + + ppe->foe_table = foe; + + mtk_ppe_debugfs_init(ppe); + +- return 0; ++ return ppe; + } + + static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -246,8 +246,7 @@ struct mtk_ppe { + void *acct_table; + }; + +-int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, +- int version); ++struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, int version); + int mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -412,7 +412,7 @@ mtk_flow_offload_replace(struct mtk_eth + + entry->cookie = f->cookie; + timestamp = mtk_eth_timestamp(eth); +- hash = mtk_foe_entry_commit(ð->ppe, &foe, timestamp); ++ hash = mtk_foe_entry_commit(eth->ppe, &foe, timestamp); + if (hash < 0) { + err = hash; + goto free; +@@ -427,7 +427,7 @@ mtk_flow_offload_replace(struct mtk_eth + + return 0; + clear_flow: +- mtk_foe_entry_clear(ð->ppe, hash); ++ mtk_foe_entry_clear(eth->ppe, hash); + free: + kfree(entry); + if (wed_index >= 0) +@@ -445,7 +445,7 @@ mtk_flow_offload_destroy(struct mtk_eth + if (!entry) + return -ENOENT; + +- mtk_foe_entry_clear(ð->ppe, entry->hash); ++ mtk_foe_entry_clear(eth->ppe, entry->hash); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (entry->wed_index >= 0) +@@ -467,7 +467,7 @@ mtk_flow_offload_stats(struct mtk_eth *e + if (!entry) + return -ENOENT; + +- timestamp = mtk_foe_entry_timestamp(ð->ppe, entry->hash); ++ timestamp = mtk_foe_entry_timestamp(eth->ppe, entry->hash); + if (timestamp < 0) + return -ETIMEDOUT; + +@@ -523,7 +523,7 @@ mtk_eth_setup_tc_block(struct net_device + struct flow_block_cb *block_cb; + flow_setup_cb_t *cb; + +- if (!eth->ppe.foe_table) ++ if (!eth->ppe || !eth->ppe->foe_table) + return -EOPNOTSUPP; + + if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) +@@ -575,7 +575,7 @@ int mtk_eth_setup_tc(struct net_device * + + int mtk_eth_offload_init(struct mtk_eth *eth) + { +- if (!eth->ppe.foe_table) ++ if (!eth->ppe || !eth->ppe->foe_table) + return 0; + + return rhashtable_init(ð->flow_table, &mtk_flow_ht_params); diff --git a/target/linux/generic/pending-5.10/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch b/target/linux/generic/pending-5.10/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch new file mode 100644 index 0000000000..ac67f8078c --- /dev/null +++ b/target/linux/generic/pending-5.10/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch @@ -0,0 +1,424 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:39:18 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: rework hardware flow table + management + +The hardware was designed to handle flow detection and creation of flow entries +by itself, relying on the software primarily for filling in egress routing +information. +When there is a hash collision between multiple flows, this allows the hardware +to maintain the entry for the most active flow. +Additionally, the hardware only keeps offloading active for entries with at +least 30 packets per second. + +With this rework, the code no longer creates a hardware entries directly. +Instead, the hardware entry is only created when the PPE reports a matching +unbound flow with the minimum target rate. +In order to reduce CPU overhead, looking for flows belonging to a hash entry +is rate limited to once every 100ms. + +This rework is also used as preparation for emulating bridge offload by +managing L4 offload entries on demand. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + + #include "mtk_eth_soc.h" +@@ -1274,7 +1275,7 @@ static int mtk_poll_rx(struct napi_struc + struct net_device *netdev; + unsigned int pktlen; + dma_addr_t dma_addr; +- u32 hash; ++ u32 hash, reason; + int mac; + + ring = mtk_get_rx_ring(eth); +@@ -1350,6 +1351,11 @@ static int mtk_poll_rx(struct napi_struc + skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); + } + ++ reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4); ++ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) ++ mtk_ppe_check_skb(eth->ppe, skb, ++ trxd.rxd4 & MTK_RXD4_FOE_ENTRY); ++ + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && + (trxd.rxd2 & RX_DMA_VTAG)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), +@@ -3265,7 +3271,7 @@ static int mtk_probe(struct platform_dev + } + + if (eth->soc->offload_version) { +- eth->ppe = mtk_ppe_init(eth->dev, eth->base + MTK_ETH_PPE_BASE, 2); ++ eth->ppe = mtk_ppe_init(eth, eth->base + MTK_ETH_PPE_BASE, 2); + if (!eth->ppe) { + err = -ENOMEM; + goto err_free_dev; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -6,9 +6,12 @@ + #include + #include + #include ++#include "mtk_eth_soc.h" + #include "mtk_ppe.h" + #include "mtk_ppe_regs.h" + ++static DEFINE_SPINLOCK(ppe_lock); ++ + static void ppe_w32(struct mtk_ppe *ppe, u32 reg, u32 val) + { + writel(val, ppe->base + reg); +@@ -41,6 +44,11 @@ static u32 ppe_clear(struct mtk_ppe *ppe + return ppe_m32(ppe, reg, val, 0); + } + ++static u32 mtk_eth_timestamp(struct mtk_eth *eth) ++{ ++ return mtk_r32(eth, 0x0010) & MTK_FOE_IB1_BIND_TIMESTAMP; ++} ++ + static int mtk_ppe_wait_busy(struct mtk_ppe *ppe) + { + int ret; +@@ -353,26 +361,59 @@ static inline bool mtk_foe_entry_usable( + FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1) != MTK_FOE_STATE_BIND; + } + +-int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, +- u16 timestamp) ++static bool ++mtk_flow_entry_match(struct mtk_flow_entry *entry, struct mtk_foe_entry *data) ++{ ++ int type, len; ++ ++ if ((data->ib1 ^ entry->data.ib1) & MTK_FOE_IB1_UDP) ++ return false; ++ ++ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->data.ib1); ++ if (type > MTK_PPE_PKT_TYPE_IPV4_DSLITE) ++ len = offsetof(struct mtk_foe_entry, ipv6._rsv); ++ else ++ len = offsetof(struct mtk_foe_entry, ipv4.ib2); ++ ++ return !memcmp(&entry->data.data, &data->data, len - 4); ++} ++ ++static void ++mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + struct mtk_foe_entry *hwe; +- u32 hash; ++ struct mtk_foe_entry foe; + ++ spin_lock_bh(&ppe_lock); ++ if (entry->hash == 0xffff) ++ goto out; ++ ++ hwe = &ppe->foe_table[entry->hash]; ++ memcpy(&foe, hwe, sizeof(foe)); ++ if (!mtk_flow_entry_match(entry, &foe)) { ++ entry->hash = 0xffff; ++ goto out; ++ } ++ ++ entry->data.ib1 = foe.ib1; ++ ++out: ++ spin_unlock_bh(&ppe_lock); ++} ++ ++static void ++__mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, ++ u16 hash) ++{ ++ struct mtk_foe_entry *hwe; ++ u16 timestamp; ++ ++ timestamp = mtk_eth_timestamp(ppe->eth); + timestamp &= MTK_FOE_IB1_BIND_TIMESTAMP; + entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP; + entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP, timestamp); + +- hash = mtk_ppe_hash_entry(entry); + hwe = &ppe->foe_table[hash]; +- if (!mtk_foe_entry_usable(hwe)) { +- hwe++; +- hash++; +- +- if (!mtk_foe_entry_usable(hwe)) +- return -ENOSPC; +- } +- + memcpy(&hwe->data, &entry->data, sizeof(hwe->data)); + wmb(); + hwe->ib1 = entry->ib1; +@@ -380,13 +421,77 @@ int mtk_foe_entry_commit(struct mtk_ppe + dma_wmb(); + + mtk_ppe_cache_clear(ppe); ++} + +- return hash; ++void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ spin_lock_bh(&ppe_lock); ++ hlist_del_init(&entry->list); ++ if (entry->hash != 0xffff) { ++ ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE; ++ ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, ++ MTK_FOE_STATE_BIND); ++ dma_wmb(); ++ } ++ entry->hash = 0xffff; ++ spin_unlock_bh(&ppe_lock); ++} ++ ++int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ u32 hash = mtk_ppe_hash_entry(&entry->data); ++ ++ entry->hash = 0xffff; ++ spin_lock_bh(&ppe_lock); ++ hlist_add_head(&entry->list, &ppe->foe_flow[hash / 2]); ++ spin_unlock_bh(&ppe_lock); ++ ++ return 0; ++} ++ ++void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) ++{ ++ struct hlist_head *head = &ppe->foe_flow[hash / 2]; ++ struct mtk_flow_entry *entry; ++ struct mtk_foe_entry *hwe = &ppe->foe_table[hash]; ++ bool found = false; ++ ++ if (hlist_empty(head)) ++ return; ++ ++ spin_lock_bh(&ppe_lock); ++ hlist_for_each_entry(entry, head, list) { ++ if (found || !mtk_flow_entry_match(entry, hwe)) { ++ if (entry->hash != 0xffff) ++ entry->hash = 0xffff; ++ continue; ++ } ++ ++ entry->hash = hash; ++ __mtk_foe_entry_commit(ppe, &entry->data, hash); ++ found = true; ++ } ++ spin_unlock_bh(&ppe_lock); ++} ++ ++int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ u16 now = mtk_eth_timestamp(ppe->eth) & MTK_FOE_IB1_BIND_TIMESTAMP; ++ u16 timestamp; ++ ++ mtk_flow_entry_update(ppe, entry); ++ timestamp = entry->data.ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; ++ ++ if (timestamp > now) ++ return MTK_FOE_IB1_BIND_TIMESTAMP + 1 - timestamp + now; ++ else ++ return now - timestamp; + } + +-struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, ++struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, + int version) + { ++ struct device *dev = eth->dev; + struct mtk_foe_entry *foe; + struct mtk_ppe *ppe; + +@@ -398,6 +503,7 @@ struct mtk_ppe *mtk_ppe_init(struct devi + * not coherent. + */ + ppe->base = base; ++ ppe->eth = eth; + ppe->dev = dev; + ppe->version = version; + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -235,7 +235,17 @@ enum { + MTK_PPE_CPU_REASON_INVALID = 0x1f, + }; + ++struct mtk_flow_entry { ++ struct rhash_head node; ++ struct hlist_node list; ++ unsigned long cookie; ++ struct mtk_foe_entry data; ++ u16 hash; ++ s8 wed_index; ++}; ++ + struct mtk_ppe { ++ struct mtk_eth *eth; + struct device *dev; + void __iomem *base; + int version; +@@ -243,18 +253,33 @@ struct mtk_ppe { + struct mtk_foe_entry *foe_table; + dma_addr_t foe_phys; + ++ u16 foe_check_time[MTK_PPE_ENTRIES]; ++ struct hlist_head foe_flow[MTK_PPE_ENTRIES / 2]; ++ + void *acct_table; + }; + +-struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, int version); ++struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version); + int mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + ++void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); ++ + static inline void +-mtk_foe_entry_clear(struct mtk_ppe *ppe, u16 hash) ++mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) + { +- ppe->foe_table[hash].ib1 = 0; +- dma_wmb(); ++ u16 now, diff; ++ ++ if (!ppe) ++ return; ++ ++ now = (u16)jiffies; ++ diff = now - ppe->foe_check_time[hash]; ++ if (diff < HZ / 10) ++ return; ++ ++ ppe->foe_check_time[hash] = now; ++ __mtk_ppe_check_skb(ppe, skb, hash); + } + + static inline int +@@ -282,8 +307,9 @@ int mtk_foe_entry_set_vlan(struct mtk_fo + int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); + int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, + int bss, int wcid); +-int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, +- u16 timestamp); ++int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); + + #endif +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -43,13 +43,6 @@ struct mtk_flow_data { + } pppoe; + }; + +-struct mtk_flow_entry { +- struct rhash_head node; +- unsigned long cookie; +- u16 hash; +- s8 wed_index; +-}; +- + static const struct rhashtable_params mtk_flow_ht_params = { + .head_offset = offsetof(struct mtk_flow_entry, node), + .key_offset = offsetof(struct mtk_flow_entry, cookie), +@@ -57,12 +50,6 @@ static const struct rhashtable_params mt + .automatic_shrinking = true, + }; + +-static u32 +-mtk_eth_timestamp(struct mtk_eth *eth) +-{ +- return mtk_r32(eth, 0x0010) & MTK_FOE_IB1_BIND_TIMESTAMP; +-} +- + static int + mtk_flow_set_ipv4_addr(struct mtk_foe_entry *foe, struct mtk_flow_data *data, + bool egress) +@@ -238,10 +225,8 @@ mtk_flow_offload_replace(struct mtk_eth + int offload_type = 0; + int wed_index = -1; + u16 addr_type = 0; +- u32 timestamp; + u8 l4proto = 0; + int err = 0; +- int hash; + int i; + + if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) +@@ -411,23 +396,21 @@ mtk_flow_offload_replace(struct mtk_eth + return -ENOMEM; + + entry->cookie = f->cookie; +- timestamp = mtk_eth_timestamp(eth); +- hash = mtk_foe_entry_commit(eth->ppe, &foe, timestamp); +- if (hash < 0) { +- err = hash; ++ memcpy(&entry->data, &foe, sizeof(entry->data)); ++ entry->wed_index = wed_index; ++ ++ if (mtk_foe_entry_commit(eth->ppe, entry) < 0) + goto free; +- } + +- entry->hash = hash; +- entry->wed_index = wed_index; + err = rhashtable_insert_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (err < 0) +- goto clear_flow; ++ goto clear; + + return 0; +-clear_flow: +- mtk_foe_entry_clear(eth->ppe, hash); ++ ++clear: ++ mtk_foe_entry_clear(eth->ppe, entry); + free: + kfree(entry); + if (wed_index >= 0) +@@ -445,7 +428,7 @@ mtk_flow_offload_destroy(struct mtk_eth + if (!entry) + return -ENOENT; + +- mtk_foe_entry_clear(eth->ppe, entry->hash); ++ mtk_foe_entry_clear(eth->ppe, entry); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (entry->wed_index >= 0) +@@ -459,7 +442,6 @@ static int + mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) + { + struct mtk_flow_entry *entry; +- int timestamp; + u32 idle; + + entry = rhashtable_lookup(ð->flow_table, &f->cookie, +@@ -467,11 +449,7 @@ mtk_flow_offload_stats(struct mtk_eth *e + if (!entry) + return -ENOENT; + +- timestamp = mtk_foe_entry_timestamp(eth->ppe, entry->hash); +- if (timestamp < 0) +- return -ETIMEDOUT; +- +- idle = mtk_eth_timestamp(eth) - timestamp; ++ idle = mtk_foe_entry_idle_time(eth->ppe, entry); + f->stats.lastused = jiffies - idle * HZ; + + return 0; diff --git a/target/linux/generic/pending-5.10/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch b/target/linux/generic/pending-5.10/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch new file mode 100644 index 0000000000..2ff0b341f9 --- /dev/null +++ b/target/linux/generic/pending-5.10/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch @@ -0,0 +1,44 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:55:19 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: remove bridge flow offload + type entry support + +According to MediaTek, this feature is not supported in current hardware + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -84,13 +84,6 @@ static u32 mtk_ppe_hash_entry(struct mtk + u32 hash; + + switch (FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, e->ib1)) { +- case MTK_PPE_PKT_TYPE_BRIDGE: +- hv1 = e->bridge.src_mac_lo; +- hv1 ^= ((e->bridge.src_mac_hi & 0xffff) << 16); +- hv2 = e->bridge.src_mac_hi >> 16; +- hv2 ^= e->bridge.dest_mac_lo; +- hv3 = e->bridge.dest_mac_hi; +- break; + case MTK_PPE_PKT_TYPE_IPV4_ROUTE: + case MTK_PPE_PKT_TYPE_IPV4_HNAPT: + hv1 = e->ipv4.orig.ports; +@@ -572,7 +565,6 @@ int mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_FLOW_CFG_IP4_NAT | + MTK_PPE_FLOW_CFG_IP4_NAPT | + MTK_PPE_FLOW_CFG_IP4_DSLITE | +- MTK_PPE_FLOW_CFG_L2_BRIDGE | + MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; + ppe_w32(ppe, MTK_PPE_FLOW_CFG, val); + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +@@ -32,7 +32,6 @@ static const char *mtk_foe_pkt_type_str( + static const char * const type_str[] = { + [MTK_PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T", + [MTK_PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T", +- [MTK_PPE_PKT_TYPE_BRIDGE] = "L2", + [MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE", + [MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T", + [MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T", diff --git a/target/linux/generic/pending-5.10/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch b/target/linux/generic/pending-5.10/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch new file mode 100644 index 0000000000..99e597a3d1 --- /dev/null +++ b/target/linux/generic/pending-5.10/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch @@ -0,0 +1,553 @@ +From: Felix Fietkau +Date: Wed, 23 Feb 2022 10:56:34 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: support creating mac + address based offload entries + +This will be used to implement a limited form of bridge offloading. +Since the hardware does not support flow table entries with just source +and destination MAC address, the driver has to emulate it. + +The hardware automatically creates entries entries for incoming flows, even +when they are bridged instead of routed, and reports when packets for these +flows have reached the minimum PPS rate for offloading. + +After this happens, we look up the L2 flow offload entry based on the MAC +header and fill in the output routing information in the flow table. +The dynamically created per-flow entries are automatically removed when +either the hardware flowtable entry expires, is replaced, or if the offload +rule they belong to is removed + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -6,12 +6,22 @@ + #include + #include + #include ++#include ++#include ++#include + #include "mtk_eth_soc.h" + #include "mtk_ppe.h" + #include "mtk_ppe_regs.h" + + static DEFINE_SPINLOCK(ppe_lock); + ++static const struct rhashtable_params mtk_flow_l2_ht_params = { ++ .head_offset = offsetof(struct mtk_flow_entry, l2_node), ++ .key_offset = offsetof(struct mtk_flow_entry, data.bridge), ++ .key_len = offsetof(struct mtk_foe_bridge, key_end), ++ .automatic_shrinking = true, ++}; ++ + static void ppe_w32(struct mtk_ppe *ppe, u32 reg, u32 val) + { + writel(val, ppe->base + reg); +@@ -123,6 +133,9 @@ mtk_foe_entry_l2(struct mtk_foe_entry *e + { + int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); + ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return &entry->bridge.l2; ++ + if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) + return &entry->ipv6.l2; + +@@ -134,6 +147,9 @@ mtk_foe_entry_ib2(struct mtk_foe_entry * + { + int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); + ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return &entry->bridge.ib2; ++ + if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) + return &entry->ipv6.ib2; + +@@ -168,7 +184,12 @@ int mtk_foe_entry_prepare(struct mtk_foe + if (type == MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T) + entry->ipv6.ports = ports_pad; + +- if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) { ++ ether_addr_copy(entry->bridge.src_mac, src_mac); ++ ether_addr_copy(entry->bridge.dest_mac, dest_mac); ++ entry->bridge.ib2 = val; ++ l2 = &entry->bridge.l2; ++ } else if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { + entry->ipv6.ib2 = val; + l2 = &entry->ipv6.l2; + } else { +@@ -372,12 +393,96 @@ mtk_flow_entry_match(struct mtk_flow_ent + } + + static void ++__mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ struct hlist_head *head; ++ struct hlist_node *tmp; ++ ++ if (entry->type == MTK_FLOW_TYPE_L2) { ++ rhashtable_remove_fast(&ppe->l2_flows, &entry->l2_node, ++ mtk_flow_l2_ht_params); ++ ++ head = &entry->l2_flows; ++ hlist_for_each_entry_safe(entry, tmp, head, l2_data.list) ++ __mtk_foe_entry_clear(ppe, entry); ++ return; ++ } ++ ++ hlist_del_init(&entry->list); ++ if (entry->hash != 0xffff) { ++ ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE; ++ ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, ++ MTK_FOE_STATE_BIND); ++ dma_wmb(); ++ } ++ entry->hash = 0xffff; ++ ++ if (entry->type != MTK_FLOW_TYPE_L2_SUBFLOW) ++ return; ++ ++ hlist_del_init(&entry->l2_data.list); ++ kfree(entry); ++} ++ ++static int __mtk_foe_entry_idle_time(struct mtk_ppe *ppe, u32 ib1) ++{ ++ u16 timestamp; ++ u16 now; ++ ++ now = mtk_eth_timestamp(ppe->eth) & MTK_FOE_IB1_BIND_TIMESTAMP; ++ timestamp = ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; ++ ++ if (timestamp > now) ++ return MTK_FOE_IB1_BIND_TIMESTAMP + 1 - timestamp + now; ++ else ++ return now - timestamp; ++} ++ ++static void ++mtk_flow_entry_update_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ struct mtk_flow_entry *cur; ++ struct mtk_foe_entry *hwe; ++ struct hlist_node *tmp; ++ int idle; ++ ++ idle = __mtk_foe_entry_idle_time(ppe, entry->data.ib1); ++ hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_data.list) { ++ int cur_idle; ++ u32 ib1; ++ ++ hwe = &ppe->foe_table[cur->hash]; ++ ib1 = READ_ONCE(hwe->ib1); ++ ++ if (FIELD_GET(MTK_FOE_IB1_STATE, ib1) != MTK_FOE_STATE_BIND) { ++ cur->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, cur); ++ continue; ++ } ++ ++ cur_idle = __mtk_foe_entry_idle_time(ppe, ib1); ++ if (cur_idle >= idle) ++ continue; ++ ++ idle = cur_idle; ++ entry->data.ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP; ++ entry->data.ib1 |= hwe->ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; ++ } ++} ++ ++static void + mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + struct mtk_foe_entry *hwe; + struct mtk_foe_entry foe; + + spin_lock_bh(&ppe_lock); ++ ++ if (entry->type == MTK_FLOW_TYPE_L2) { ++ mtk_flow_entry_update_l2(ppe, entry); ++ goto out; ++ } ++ + if (entry->hash == 0xffff) + goto out; + +@@ -419,21 +524,28 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + spin_lock_bh(&ppe_lock); +- hlist_del_init(&entry->list); +- if (entry->hash != 0xffff) { +- ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE; +- ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, +- MTK_FOE_STATE_BIND); +- dma_wmb(); +- } +- entry->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, entry); + spin_unlock_bh(&ppe_lock); + } + ++static int ++mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ entry->type = MTK_FLOW_TYPE_L2; ++ ++ return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node, ++ mtk_flow_l2_ht_params); ++} ++ + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { +- u32 hash = mtk_ppe_hash_entry(&entry->data); ++ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->data.ib1); ++ u32 hash; ++ ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return mtk_foe_entry_commit_l2(ppe, entry); + ++ hash = mtk_ppe_hash_entry(&entry->data); + entry->hash = 0xffff; + spin_lock_bh(&ppe_lock); + hlist_add_head(&entry->list, &ppe->foe_flow[hash / 2]); +@@ -442,18 +554,72 @@ int mtk_foe_entry_commit(struct mtk_ppe + return 0; + } + ++static void ++mtk_foe_entry_commit_subflow(struct mtk_ppe *ppe, struct mtk_flow_entry *entry, ++ u16 hash) ++{ ++ struct mtk_flow_entry *flow_info; ++ struct mtk_foe_entry foe, *hwe; ++ struct mtk_foe_mac_info *l2; ++ u32 ib1_mask = MTK_FOE_IB1_PACKET_TYPE | MTK_FOE_IB1_UDP; ++ int type; ++ ++ flow_info = kzalloc(offsetof(struct mtk_flow_entry, l2_data.end), ++ GFP_ATOMIC); ++ if (!flow_info) ++ return; ++ ++ flow_info->l2_data.base_flow = entry; ++ flow_info->type = MTK_FLOW_TYPE_L2_SUBFLOW; ++ flow_info->hash = hash; ++ hlist_add_head(&flow_info->list, &ppe->foe_flow[hash / 2]); ++ hlist_add_head(&flow_info->l2_data.list, &entry->l2_flows); ++ ++ hwe = &ppe->foe_table[hash]; ++ memcpy(&foe, hwe, sizeof(foe)); ++ foe.ib1 &= ib1_mask; ++ foe.ib1 |= entry->data.ib1 & ~ib1_mask; ++ ++ l2 = mtk_foe_entry_l2(&foe); ++ memcpy(l2, &entry->data.bridge.l2, sizeof(*l2)); ++ ++ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, foe.ib1); ++ if (type == MTK_PPE_PKT_TYPE_IPV4_HNAPT) ++ memcpy(&foe.ipv4.new, &foe.ipv4.orig, sizeof(foe.ipv4.new)); ++ else if (type >= MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T && l2->etype == ETH_P_IP) ++ l2->etype = ETH_P_IPV6; ++ ++ *mtk_foe_entry_ib2(&foe) = entry->data.bridge.ib2; ++ ++ __mtk_foe_entry_commit(ppe, &foe, hash); ++} ++ + void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) + { + struct hlist_head *head = &ppe->foe_flow[hash / 2]; +- struct mtk_flow_entry *entry; + struct mtk_foe_entry *hwe = &ppe->foe_table[hash]; ++ struct mtk_flow_entry *entry; ++ struct mtk_foe_bridge key = {}; ++ struct ethhdr *eh; + bool found = false; +- +- if (hlist_empty(head)) +- return; ++ u8 *tag; + + spin_lock_bh(&ppe_lock); ++ ++ if (FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == MTK_FOE_STATE_BIND) ++ goto out; ++ + hlist_for_each_entry(entry, head, list) { ++ if (entry->type == MTK_FLOW_TYPE_L2_SUBFLOW) { ++ if (unlikely(FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == ++ MTK_FOE_STATE_BIND)) ++ continue; ++ ++ entry->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, entry); ++ continue; ++ } ++ + if (found || !mtk_flow_entry_match(entry, hwe)) { + if (entry->hash != 0xffff) + entry->hash = 0xffff; +@@ -464,21 +630,50 @@ void __mtk_ppe_check_skb(struct mtk_ppe + __mtk_foe_entry_commit(ppe, &entry->data, hash); + found = true; + } ++ ++ if (found) ++ goto out; ++ ++ eh = eth_hdr(skb); ++ ether_addr_copy(key.dest_mac, eh->h_dest); ++ ether_addr_copy(key.src_mac, eh->h_source); ++ tag = skb->data - 2; ++ key.vlan = 0; ++ switch (skb->protocol) { ++#if IS_ENABLED(CONFIG_NET_DSA) ++ case htons(ETH_P_XDSA): ++ if (!netdev_uses_dsa(skb->dev) || ++ skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) ++ goto out; ++ ++ tag += 4; ++ if (get_unaligned_be16(tag) != ETH_P_8021Q) ++ break; ++ ++ fallthrough; ++#endif ++ case htons(ETH_P_8021Q): ++ key.vlan = get_unaligned_be16(tag + 2) & VLAN_VID_MASK; ++ break; ++ default: ++ break; ++ } ++ ++ entry = rhashtable_lookup_fast(&ppe->l2_flows, &key, mtk_flow_l2_ht_params); ++ if (!entry) ++ goto out; ++ ++ mtk_foe_entry_commit_subflow(ppe, entry, hash); ++ ++out: + spin_unlock_bh(&ppe_lock); + } + + int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { +- u16 now = mtk_eth_timestamp(ppe->eth) & MTK_FOE_IB1_BIND_TIMESTAMP; +- u16 timestamp; +- + mtk_flow_entry_update(ppe, entry); +- timestamp = entry->data.ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; + +- if (timestamp > now) +- return MTK_FOE_IB1_BIND_TIMESTAMP + 1 - timestamp + now; +- else +- return now - timestamp; ++ return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); + } + + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, +@@ -492,6 +687,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + if (!ppe) + return NULL; + ++ rhashtable_init(&ppe->l2_flows, &mtk_flow_l2_ht_params); ++ + /* need to allocate a separate device, since it PPE DMA access is + * not coherent. + */ +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -6,6 +6,7 @@ + + #include + #include ++#include + + #define MTK_ETH_PPE_BASE 0xc00 + +@@ -84,19 +85,16 @@ struct mtk_foe_mac_info { + u16 src_mac_lo; + }; + ++/* software-only entry type */ + struct mtk_foe_bridge { +- u32 dest_mac_hi; +- +- u16 src_mac_lo; +- u16 dest_mac_lo; ++ u8 dest_mac[ETH_ALEN]; ++ u8 src_mac[ETH_ALEN]; ++ u16 vlan; + +- u32 src_mac_hi; ++ struct {} key_end; + + u32 ib2; + +- u32 _rsv[5]; +- +- u32 udf_tsid; + struct mtk_foe_mac_info l2; + }; + +@@ -235,13 +233,33 @@ enum { + MTK_PPE_CPU_REASON_INVALID = 0x1f, + }; + ++enum { ++ MTK_FLOW_TYPE_L4, ++ MTK_FLOW_TYPE_L2, ++ MTK_FLOW_TYPE_L2_SUBFLOW, ++}; ++ + struct mtk_flow_entry { ++ union { ++ struct hlist_node list; ++ struct { ++ struct rhash_head l2_node; ++ struct hlist_head l2_flows; ++ }; ++ }; ++ u8 type; ++ s8 wed_index; ++ u16 hash; ++ union { ++ struct mtk_foe_entry data; ++ struct { ++ struct mtk_flow_entry *base_flow; ++ struct hlist_node list; ++ struct {} end; ++ } l2_data; ++ }; + struct rhash_head node; +- struct hlist_node list; + unsigned long cookie; +- struct mtk_foe_entry data; +- u16 hash; +- s8 wed_index; + }; + + struct mtk_ppe { +@@ -256,6 +274,8 @@ struct mtk_ppe { + u16 foe_check_time[MTK_PPE_ENTRIES]; + struct hlist_head foe_flow[MTK_PPE_ENTRIES / 2]; + ++ struct rhashtable l2_flows; ++ + void *acct_table; + }; + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -32,6 +32,8 @@ struct mtk_flow_data { + __be16 src_port; + __be16 dst_port; + ++ u16 vlan_in; ++ + struct { + u16 id; + __be16 proto; +@@ -258,9 +260,45 @@ mtk_flow_offload_replace(struct mtk_eth + return -EOPNOTSUPP; + } + ++ switch (addr_type) { ++ case 0: ++ offload_type = MTK_PPE_PKT_TYPE_BRIDGE; ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { ++ struct flow_match_eth_addrs match; ++ ++ flow_rule_match_eth_addrs(rule, &match); ++ memcpy(data.eth.h_dest, match.key->dst, ETH_ALEN); ++ memcpy(data.eth.h_source, match.key->src, ETH_ALEN); ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { ++ struct flow_match_vlan match; ++ ++ flow_rule_match_vlan(rule, &match); ++ ++ if (match.key->vlan_tpid != cpu_to_be16(ETH_P_8021Q)) ++ return -EOPNOTSUPP; ++ ++ data.vlan_in = match.key->vlan_id; ++ } ++ break; ++ case FLOW_DISSECTOR_KEY_IPV4_ADDRS: ++ offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; ++ break; ++ case FLOW_DISSECTOR_KEY_IPV6_ADDRS: ++ offload_type = MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ + flow_action_for_each(i, act, &rule->action) { + switch (act->id) { + case FLOW_ACTION_MANGLE: ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; + if (act->mangle.htype == FLOW_ACT_MANGLE_HDR_TYPE_ETH) + mtk_flow_offload_mangle_eth(act, &data.eth); + break; +@@ -292,17 +330,6 @@ mtk_flow_offload_replace(struct mtk_eth + } + } + +- switch (addr_type) { +- case FLOW_DISSECTOR_KEY_IPV4_ADDRS: +- offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; +- break; +- case FLOW_DISSECTOR_KEY_IPV6_ADDRS: +- offload_type = MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T; +- break; +- default: +- return -EOPNOTSUPP; +- } +- + if (!is_valid_ether_addr(data.eth.h_source) || + !is_valid_ether_addr(data.eth.h_dest)) + return -EINVAL; +@@ -316,10 +343,13 @@ mtk_flow_offload_replace(struct mtk_eth + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports ports; + ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ + flow_rule_match_ports(rule, &ports); + data.src_port = ports.key->src; + data.dst_port = ports.key->dst; +- } else { ++ } else if (offload_type != MTK_PPE_PKT_TYPE_BRIDGE) { + return -EOPNOTSUPP; + } + +@@ -349,6 +379,9 @@ mtk_flow_offload_replace(struct mtk_eth + if (act->id != FLOW_ACTION_MANGLE) + continue; + ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ + switch (act->mangle.htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_TCP: + case FLOW_ACT_MANGLE_HDR_TYPE_UDP: +@@ -374,6 +407,9 @@ mtk_flow_offload_replace(struct mtk_eth + return err; + } + ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ foe.bridge.vlan = data.vlan_in; ++ + if (data.vlan.num == 1) { + if (data.vlan.proto != htons(ETH_P_8021Q)) + return -EOPNOTSUPP; diff --git a/target/linux/generic/pending-5.15/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch b/target/linux/generic/pending-5.15/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch new file mode 100644 index 0000000000..ebecbfb067 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-00-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch @@ -0,0 +1,327 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 17:59:07 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for coherent + DMA + +It improves performance by eliminating the need for a cache flush on rx and tx +In preparation for supporting WED (Wireless Ethernet Dispatch), also add a +function for disabling coherent DMA at runtime. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -828,7 +829,7 @@ static int mtk_init_fq_dma(struct mtk_et + dma_addr_t dma_addr; + int i; + +- eth->scratch_ring = dma_alloc_coherent(eth->dev, ++ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, + cnt * sizeof(struct mtk_tx_dma), + ð->phy_scratch_ring, + GFP_ATOMIC); +@@ -840,10 +841,10 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(!eth->scratch_head)) + return -ENOMEM; + +- dma_addr = dma_map_single(eth->dev, ++ dma_addr = dma_map_single(eth->dma_dev, + eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE, + DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, dma_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + + phy_ring_tail = eth->phy_scratch_ring + +@@ -897,26 +898,26 @@ static void mtk_tx_unmap(struct mtk_eth + { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { + if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) { +- dma_unmap_single(eth->dev, ++ dma_unmap_single(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } else if (tx_buf->flags & MTK_TX_FLAGS_PAGE0) { +- dma_unmap_page(eth->dev, ++ dma_unmap_page(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } + } else { + if (dma_unmap_len(tx_buf, dma_len0)) { +- dma_unmap_page(eth->dev, ++ dma_unmap_page(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } + + if (dma_unmap_len(tx_buf, dma_len1)) { +- dma_unmap_page(eth->dev, ++ dma_unmap_page(eth->dma_dev, + dma_unmap_addr(tx_buf, dma_addr1), + dma_unmap_len(tx_buf, dma_len1), + DMA_TO_DEVICE); +@@ -994,9 +995,9 @@ static int mtk_tx_map(struct sk_buff *sk + if (skb_vlan_tag_present(skb)) + txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb); + +- mapped_addr = dma_map_single(eth->dev, skb->data, ++ mapped_addr = dma_map_single(eth->dma_dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, mapped_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr))) + return -ENOMEM; + + WRITE_ONCE(itxd->txd1, mapped_addr); +@@ -1035,10 +1036,10 @@ static int mtk_tx_map(struct sk_buff *sk + + + frag_map_size = min(frag_size, MTK_TX_DMA_BUF_LEN); +- mapped_addr = skb_frag_dma_map(eth->dev, frag, offset, ++ mapped_addr = skb_frag_dma_map(eth->dma_dev, frag, offset, + frag_map_size, + DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, mapped_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr))) + goto err_dma; + + if (i == nr_frags - 1 && +@@ -1316,18 +1317,18 @@ static int mtk_poll_rx(struct napi_struc + netdev->stats.rx_dropped++; + goto release_desc; + } +- dma_addr = dma_map_single(eth->dev, ++ dma_addr = dma_map_single(eth->dma_dev, + new_data + NET_SKB_PAD + + eth->ip_align, + ring->buf_size, + DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, dma_addr))) { ++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) { + skb_free_frag(new_data); + netdev->stats.rx_dropped++; + goto release_desc; + } + +- dma_unmap_single(eth->dev, trxd.rxd1, ++ dma_unmap_single(eth->dma_dev, trxd.rxd1, + ring->buf_size, DMA_FROM_DEVICE); + + /* receive data */ +@@ -1600,7 +1601,7 @@ static int mtk_tx_alloc(struct mtk_eth * + if (!ring->buf) + goto no_tx_mem; + +- ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz, ++ ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, + &ring->phys, GFP_ATOMIC); + if (!ring->dma) + goto no_tx_mem; +@@ -1618,7 +1619,7 @@ static int mtk_tx_alloc(struct mtk_eth * + * descriptors in ring->dma_pdma. + */ + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { +- ring->dma_pdma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz, ++ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, + &ring->phys_pdma, + GFP_ATOMIC); + if (!ring->dma_pdma) +@@ -1677,7 +1678,7 @@ static void mtk_tx_clean(struct mtk_eth + } + + if (ring->dma) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + MTK_DMA_SIZE * sizeof(*ring->dma), + ring->dma, + ring->phys); +@@ -1685,7 +1686,7 @@ static void mtk_tx_clean(struct mtk_eth + } + + if (ring->dma_pdma) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + MTK_DMA_SIZE * sizeof(*ring->dma_pdma), + ring->dma_pdma, + ring->phys_pdma); +@@ -1730,18 +1731,18 @@ static int mtk_rx_alloc(struct mtk_eth * + return -ENOMEM; + } + +- ring->dma = dma_alloc_coherent(eth->dev, ++ ring->dma = dma_alloc_coherent(eth->dma_dev, + rx_dma_size * sizeof(*ring->dma), + &ring->phys, GFP_ATOMIC); + if (!ring->dma) + return -ENOMEM; + + for (i = 0; i < rx_dma_size; i++) { +- dma_addr_t dma_addr = dma_map_single(eth->dev, ++ dma_addr_t dma_addr = dma_map_single(eth->dma_dev, + ring->data[i] + NET_SKB_PAD + eth->ip_align, + ring->buf_size, + DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(eth->dev, dma_addr))) ++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + ring->dma[i].rxd1 = (unsigned int)dma_addr; + +@@ -1777,7 +1778,7 @@ static void mtk_rx_clean(struct mtk_eth + continue; + if (!ring->dma[i].rxd1) + continue; +- dma_unmap_single(eth->dev, ++ dma_unmap_single(eth->dma_dev, + ring->dma[i].rxd1, + ring->buf_size, + DMA_FROM_DEVICE); +@@ -1788,7 +1789,7 @@ static void mtk_rx_clean(struct mtk_eth + } + + if (ring->dma) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + ring->dma_size * sizeof(*ring->dma), + ring->dma, + ring->phys); +@@ -2141,7 +2142,7 @@ static void mtk_dma_free(struct mtk_eth + if (eth->netdev[i]) + netdev_reset_queue(eth->netdev[i]); + if (eth->scratch_ring) { +- dma_free_coherent(eth->dev, ++ dma_free_coherent(eth->dma_dev, + MTK_DMA_SIZE * sizeof(struct mtk_tx_dma), + eth->scratch_ring, + eth->phy_scratch_ring); +@@ -2491,6 +2492,8 @@ static void mtk_dim_tx(struct work_struc + + static int mtk_hw_init(struct mtk_eth *eth) + { ++ u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | ++ ETHSYS_DMA_AG_MAP_PPE; + int i, val, ret; + + if (test_and_set_bit(MTK_HW_INIT, ð->state)) +@@ -2503,6 +2506,10 @@ static int mtk_hw_init(struct mtk_eth *e + if (ret) + goto err_disable_pm; + ++ if (eth->ethsys) ++ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, dma_mask, ++ of_dma_is_coherent(eth->dma_dev->of_node) * dma_mask); ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { + ret = device_reset(eth->dev); + if (ret) { +@@ -3056,6 +3063,35 @@ free_netdev: + return err; + } + ++void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) ++{ ++ struct net_device *dev, *tmp; ++ LIST_HEAD(dev_list); ++ int i; ++ ++ rtnl_lock(); ++ ++ for (i = 0; i < MTK_MAC_COUNT; i++) { ++ dev = eth->netdev[i]; ++ ++ if (!dev || !(dev->flags & IFF_UP)) ++ continue; ++ ++ list_add_tail(&dev->close_list, &dev_list); ++ } ++ ++ dev_close_many(&dev_list, false); ++ ++ eth->dma_dev = dma_dev; ++ ++ list_for_each_entry_safe(dev, tmp, &dev_list, close_list) { ++ list_del_init(&dev->close_list); ++ dev_open(dev, NULL); ++ } ++ ++ rtnl_unlock(); ++} ++ + static int mtk_probe(struct platform_device *pdev) + { + struct device_node *mac_np; +@@ -3069,6 +3105,7 @@ static int mtk_probe(struct platform_dev + eth->soc = of_device_get_match_data(&pdev->dev); + + eth->dev = &pdev->dev; ++ eth->dma_dev = &pdev->dev; + eth->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(eth->base)) + return PTR_ERR(eth->base); +@@ -3117,6 +3154,16 @@ static int mtk_probe(struct platform_dev + } + } + ++ if (of_dma_is_coherent(pdev->dev.of_node)) { ++ struct regmap *cci; ++ ++ cci = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, ++ "mediatek,cci-control"); ++ /* enable CPU/bus coherency */ ++ if (!IS_ERR(cci)) ++ regmap_write(cci, 0, 3); ++ } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { + eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), + GFP_KERNEL); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -462,6 +462,12 @@ + #define RSTCTRL_FE BIT(6) + #define RSTCTRL_PPE BIT(31) + ++/* ethernet dma channel agent map */ ++#define ETHSYS_DMA_AG_MAP 0x408 ++#define ETHSYS_DMA_AG_MAP_PDMA BIT(0) ++#define ETHSYS_DMA_AG_MAP_QDMA BIT(1) ++#define ETHSYS_DMA_AG_MAP_PPE BIT(2) ++ + /* SGMII subsystem config registers */ + /* Register to auto-negotiation restart */ + #define SGMSYS_PCS_CONTROL_1 0x0 +@@ -879,6 +885,7 @@ struct mtk_sgmii { + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver + * @dev: The device pointer ++ * @dev: The device pointer used for dma mapping/alloc + * @base: The mapped register i/o base + * @page_lock: Make sure that register operations are atomic + * @tx_irq__lock: Make sure that IRQ register operations are atomic +@@ -922,6 +929,7 @@ struct mtk_sgmii { + + struct mtk_eth { + struct device *dev; ++ struct device *dma_dev; + void __iomem *base; + spinlock_t page_lock; + spinlock_t tx_irq_lock; +@@ -1020,6 +1028,7 @@ int mtk_gmac_rgmii_path_setup(struct mtk + int mtk_eth_offload_init(struct mtk_eth *eth); + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data); ++void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); + + + #endif /* MTK_ETH_H */ diff --git a/target/linux/generic/pending-5.15/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch b/target/linux/generic/pending-5.15/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch new file mode 100644 index 0000000000..d9015d4805 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-01-arm64-dts-mediatek-mt7622-add-support-for-coherent-D.patch @@ -0,0 +1,30 @@ +From: Felix Fietkau +Date: Mon, 7 Feb 2022 10:27:22 +0100 +Subject: [PATCH] arm64: dts: mediatek: mt7622: add support for coherent + DMA + +It improves performance by eliminating the need for a cache flush on rx and tx + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -357,7 +357,7 @@ + }; + + cci_control2: slave-if@5000 { +- compatible = "arm,cci-400-ctrl-if"; ++ compatible = "arm,cci-400-ctrl-if", "syscon"; + interface-type = "ace"; + reg = <0x5000 0x1000>; + }; +@@ -937,6 +937,8 @@ + power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys>; ++ mediatek,cci-control = <&cci_control2>; ++ dma-coherent; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; diff --git a/target/linux/generic/pending-5.15/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch b/target/linux/generic/pending-5.15/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch new file mode 100644 index 0000000000..84642ff146 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-02-net-ethernet-mtk_eth_soc-add-support-for-Wireless-Et.patch @@ -0,0 +1,1679 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 17:56:08 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for Wireless + Ethernet Dispatch (WED) + +The Wireless Ethernet Dispatch subsystem on the MT7622 SoC can be +configured to intercept and handle access to the DMA queues and +PCIe interrupts for a MT7615/MT7915 wireless card. +It can manage the internal WDMA (Wireless DMA) controller, which allows +ethernet packets to be passed from the packet switch engine (PSE) to the +wireless card, bypassing the CPU entirely. +This can be used to implement hardware flow offloading from ethernet to +WLAN. + +Signed-off-by: Felix Fietkau +--- + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed.h + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_debugfs.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ops.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_regs.h + create mode 100644 include/linux/soc/mediatek/mtk_wed.h + +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -7,6 +7,10 @@ config NET_VENDOR_MEDIATEK + + if NET_VENDOR_MEDIATEK + ++config NET_MEDIATEK_SOC_WED ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ def_bool NET_MEDIATEK_SOC != n ++ + config NET_MEDIATEK_SOC + tristate "MediaTek SoC Gigabit Ethernet support" + depends on NET_DSA || !NET_DSA +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -5,4 +5,9 @@ + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o + mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o ++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o ++ifdef CONFIG_DEBUG_FS ++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o ++endif ++obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o + obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -24,6 +24,7 @@ + #include + + #include "mtk_eth_soc.h" ++#include "mtk_wed.h" + + static int mtk_msg_level = -1; + module_param_named(msg_level, mtk_msg_level, int, 0); +@@ -3186,6 +3187,22 @@ static int mtk_probe(struct platform_dev + } + } + ++ for (i = 0;; i++) { ++ struct device_node *np = of_parse_phandle(pdev->dev.of_node, ++ "mediatek,wed", i); ++ static const u32 wdma_regs[] = { ++ MTK_WDMA0_BASE, ++ MTK_WDMA1_BASE ++ }; ++ void __iomem *wdma; ++ ++ if (!np || i >= ARRAY_SIZE(wdma_regs)) ++ break; ++ ++ wdma = eth->base + wdma_regs[i]; ++ mtk_wed_add_hw(np, eth, wdma, i); ++ } ++ + for (i = 0; i < 3; i++) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) + eth->irq[i] = eth->irq[0]; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -295,6 +295,9 @@ + #define MTK_GDM1_TX_GPCNT 0x2438 + #define MTK_STAT_OFFSET 0x40 + ++#define MTK_WDMA0_BASE 0x2800 ++#define MTK_WDMA1_BASE 0x2c00 ++ + /* QDMA descriptor txd4 */ + #define TX_DMA_CHKSUM (0x7 << 29) + #define TX_DMA_TSO BIT(28) +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -0,0 +1,875 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2021 Felix Fietkau */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mtk_eth_soc.h" ++#include "mtk_wed_regs.h" ++#include "mtk_wed.h" ++#include "mtk_ppe.h" ++ ++#define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) ++ ++#define MTK_WED_PKT_SIZE 1900 ++#define MTK_WED_BUF_SIZE 2048 ++#define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) ++ ++#define MTK_WED_TX_RING_SIZE 2048 ++#define MTK_WED_WDMA_RING_SIZE 1024 ++ ++static struct mtk_wed_hw *hw_list[2]; ++static DEFINE_MUTEX(hw_lock); ++ ++static void ++wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) ++{ ++ regmap_update_bits(dev->hw->regs, reg, mask | val, val); ++} ++ ++static void ++wed_set(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ return wed_m32(dev, reg, 0, mask); ++} ++ ++static void ++wed_clr(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ return wed_m32(dev, reg, mask, 0); ++} ++ ++static void ++wdma_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) ++{ ++ wdma_w32(dev, reg, (wdma_r32(dev, reg) & ~mask) | val); ++} ++ ++static void ++wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ wdma_m32(dev, reg, 0, mask); ++} ++ ++static u32 ++mtk_wed_read_reset(struct mtk_wed_device *dev) ++{ ++ return wed_r32(dev, MTK_WED_RESET); ++} ++ ++static void ++mtk_wed_reset(struct mtk_wed_device *dev, u32 mask) ++{ ++ u32 status; ++ ++ wed_w32(dev, MTK_WED_RESET, mask); ++ if (readx_poll_timeout(mtk_wed_read_reset, dev, status, ++ !(status & mask), 0, 1000)) ++ WARN_ON_ONCE(1); ++} ++ ++static struct mtk_wed_hw * ++mtk_wed_assign(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_hw *hw; ++ ++ hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)]; ++ if (!hw || hw->wed_dev) ++ return NULL; ++ ++ hw->wed_dev = dev; ++ return hw; ++} ++ ++static int ++mtk_wed_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ void **page_list; ++ int token = dev->wlan.token_start; ++ int ring_size; ++ int n_pages; ++ int i, page_idx; ++ ++ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); ++ n_pages = ring_size / MTK_WED_BUF_PER_PAGE; ++ ++ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL); ++ if (!page_list) ++ return -ENOMEM; ++ ++ dev->buf_ring.size = ring_size; ++ dev->buf_ring.pages = page_list; ++ ++ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), ++ &desc_phys, GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ dev->buf_ring.desc = desc; ++ dev->buf_ring.desc_phys = desc_phys; ++ ++ for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { ++ dma_addr_t page_phys, buf_phys; ++ struct page *page; ++ void *buf; ++ int s; ++ ++ page = __dev_alloc_pages(GFP_KERNEL, 0); ++ if (!page) ++ return -ENOMEM; ++ ++ page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(dev->hw->dev, page_phys)) { ++ __free_page(page); ++ return -ENOMEM; ++ } ++ ++ page_list[page_idx++] = page; ++ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ ++ buf = page_to_virt(page); ++ buf_phys = page_phys; ++ ++ for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) { ++ u32 txd_size; ++ ++ txd_size = dev->wlan.init_buf(buf, buf_phys, token++); ++ ++ desc->buf0 = buf_phys; ++ desc->buf1 = buf_phys + txd_size; ++ desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, ++ txd_size) | ++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, ++ MTK_WED_BUF_SIZE - txd_size) | ++ MTK_WDMA_DESC_CTRL_LAST_SEG1; ++ desc->info = 0; ++ desc++; ++ ++ buf += MTK_WED_BUF_SIZE; ++ buf_phys += MTK_WED_BUF_SIZE; ++ } ++ ++ dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ } ++ ++ return 0; ++} ++ ++static void ++mtk_wed_free_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_wdma_desc *desc = dev->buf_ring.desc; ++ void **page_list = dev->buf_ring.pages; ++ int page_idx; ++ int i; ++ ++ if (!page_list) ++ return; ++ ++ if (!desc) ++ goto free_pagelist; ++ ++ for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { ++ void *page = page_list[page_idx++]; ++ ++ if (!page) ++ break; ++ ++ dma_unmap_page(dev->hw->dev, desc[i].buf0, ++ PAGE_SIZE, DMA_BIDIRECTIONAL); ++ __free_page(page); ++ } ++ ++ dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc), ++ desc, dev->buf_ring.desc_phys); ++ ++free_pagelist: ++ kfree(page_list); ++} ++ ++static void ++mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring) ++{ ++ if (!ring->desc) ++ return; ++ ++ dma_free_coherent(dev->hw->dev, ring->size * sizeof(*ring->desc), ++ ring->desc, ring->desc_phys); ++} ++ ++static void ++mtk_wed_free_tx_rings(struct mtk_wed_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) ++ mtk_wed_free_ring(dev, &dev->tx_ring[i]); ++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) ++ mtk_wed_free_ring(dev, &dev->tx_wdma[i]); ++} ++ ++static void ++mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en) ++{ ++ u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; ++ ++ if (!dev->hw->num_flows) ++ mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; ++ ++ wed_w32(dev, MTK_WED_EXT_INT_MASK, en ? mask : 0); ++ wed_r32(dev, MTK_WED_EXT_INT_MASK); ++} ++ ++static void ++mtk_wed_stop(struct mtk_wed_device *dev) ++{ ++ regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); ++ mtk_wed_set_ext_int(dev, false); ++ ++ wed_clr(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); ++ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); ++ wdma_w32(dev, MTK_WDMA_INT_MASK, 0); ++ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); ++ ++ wed_clr(dev, MTK_WED_GLO_CFG, ++ MTK_WED_GLO_CFG_TX_DMA_EN | ++ MTK_WED_GLO_CFG_RX_DMA_EN); ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++} ++ ++static void ++mtk_wed_detach(struct mtk_wed_device *dev) ++{ ++ struct device_node *wlan_node = dev->wlan.pci_dev->dev.of_node; ++ struct mtk_wed_hw *hw = dev->hw; ++ ++ mutex_lock(&hw_lock); ++ ++ mtk_wed_stop(dev); ++ ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ ++ mtk_wed_free_buffer(dev); ++ mtk_wed_free_tx_rings(dev); ++ ++ if (of_dma_is_coherent(wlan_node)) ++ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, ++ BIT(hw->index), BIT(hw->index)); ++ ++ if (!hw_list[!hw->index]->wed_dev && ++ hw->eth->dma_dev != hw->eth->dev) ++ mtk_eth_set_dma_device(hw->eth, hw->eth->dev); ++ ++ memset(dev, 0, sizeof(*dev)); ++ module_put(THIS_MODULE); ++ ++ hw->wed_dev = NULL; ++ mutex_unlock(&hw_lock); ++} ++ ++static void ++mtk_wed_hw_init_early(struct mtk_wed_device *dev) ++{ ++ u32 mask, set; ++ u32 offset; ++ ++ mtk_wed_stop(dev); ++ mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ ++ mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE | ++ MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE | ++ MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE; ++ set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) | ++ MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP | ++ MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; ++ wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); ++ ++ wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO_PRERES); ++ ++ offset = dev->hw->index ? 0x04000400 : 0; ++ wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset); ++ wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset); ++ ++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, MTK_PCIE_BASE(dev->hw->index)); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); ++} ++ ++static void ++mtk_wed_hw_init(struct mtk_wed_device *dev) ++{ ++ if (dev->init_done) ++ return; ++ ++ dev->init_done = true; ++ mtk_wed_set_ext_int(dev, false); ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++ dev->buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); ++ ++ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys); ++ ++ wed_w32(dev, MTK_WED_TX_BM_TKID, ++ FIELD_PREP(MTK_WED_TX_BM_TKID_START, ++ dev->wlan.token_start) | ++ FIELD_PREP(MTK_WED_TX_BM_TKID_END, ++ dev->wlan.token_start + dev->wlan.nbuf - 1)); ++ ++ wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); ++ ++ wed_w32(dev, MTK_WED_TX_BM_DYN_THR, ++ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) | ++ MTK_WED_TX_BM_DYN_THR_HI); ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); ++ ++ wed_set(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ ++ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); ++} ++ ++static void ++mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i++) { ++ desc[i].buf0 = 0; ++ desc[i].ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ desc[i].buf1 = 0; ++ desc[i].info = 0; ++ } ++} ++ ++static u32 ++mtk_wed_check_busy(struct mtk_wed_device *dev) ++{ ++ if (wed_r32(dev, MTK_WED_GLO_CFG) & MTK_WED_GLO_CFG_TX_DMA_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_WPDMA_GLO_CFG) & ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_CTRL) & MTK_WED_CTRL_WDMA_INT_AGENT_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_WDMA_GLO_CFG) & ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) ++ return true; ++ ++ if (wdma_r32(dev, MTK_WDMA_GLO_CFG) & ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY) ++ return true; ++ ++ if (wed_r32(dev, MTK_WED_CTRL) & ++ (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY)) ++ return true; ++ ++ return false; ++} ++ ++static int ++mtk_wed_poll_busy(struct mtk_wed_device *dev) ++{ ++ int sleep = 15000; ++ int timeout = 100 * sleep; ++ u32 val; ++ ++ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, ++ timeout, false, dev); ++} ++ ++static void ++mtk_wed_reset_dma(struct mtk_wed_device *dev) ++{ ++ bool busy = false; ++ u32 val; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) { ++ struct mtk_wdma_desc *desc = dev->tx_ring[i].desc; ++ ++ if (!desc) ++ continue; ++ ++ mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE); ++ } ++ ++ if (mtk_wed_poll_busy(dev)) ++ busy = mtk_wed_check_busy(dev); ++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); ++ } else { ++ wed_w32(dev, MTK_WED_RESET_IDX, ++ MTK_WED_RESET_IDX_TX | ++ MTK_WED_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_RESET_IDX, 0); ++ } ++ ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); ++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); ++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); ++ } else { ++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, ++ MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV); ++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0); ++ ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); ++ ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE); ++ } ++ ++ for (i = 0; i < 100; i++) { ++ val = wed_r32(dev, MTK_WED_TX_BM_INTF); ++ if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) ++ break; ++ } ++ ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); ++ ++ if (busy) { ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); ++ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV); ++ } else { ++ wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, ++ MTK_WED_WPDMA_RESET_IDX_TX | ++ MTK_WED_WPDMA_RESET_IDX_RX); ++ wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0); ++ } ++ ++} ++ ++static int ++mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, ++ int size) ++{ ++ ring->desc = dma_alloc_coherent(dev->hw->dev, ++ size * sizeof(*ring->desc), ++ &ring->desc_phys, GFP_KERNEL); ++ if (!ring->desc) ++ return -ENOMEM; ++ ++ ring->size = size; ++ mtk_wed_ring_reset(ring->desc, size); ++ ++ return 0; ++} ++ ++static int ++mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size) ++{ ++ struct mtk_wed_ring *wdma = &dev->tx_wdma[idx]; ++ ++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE)) ++ return -ENOMEM; ++ ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, ++ wdma->desc_phys); ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT, ++ size); ++ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ ++ wed_w32(dev, MTK_WED_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, ++ wdma->desc_phys); ++ wed_w32(dev, MTK_WED_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT, ++ size); ++ ++ return 0; ++} ++ ++static void ++mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask) ++{ ++ u32 wdma_mask; ++ u32 val; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) ++ if (!dev->tx_wdma[i].desc) ++ mtk_wed_wdma_ring_setup(dev, i, 16); ++ ++ wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0)); ++ ++ mtk_wed_hw_init(dev); ++ ++ wed_set(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WPDMA_INT_AGENT_EN | ++ MTK_WED_CTRL_WED_TX_BM_EN | ++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); ++ ++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, MTK_WED_PCIE_INT_TRIGGER_STATUS); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, ++ MTK_WED_WPDMA_INT_TRIGGER_RX_DONE | ++ MTK_WED_WPDMA_INT_TRIGGER_TX_DONE); ++ ++ wed_set(dev, MTK_WED_WPDMA_INT_CTRL, ++ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); ++ ++ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask); ++ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); ++ ++ wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask); ++ wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask); ++ wed_w32(dev, MTK_WED_INT_MASK, irq_mask); ++ ++ wed_set(dev, MTK_WED_GLO_CFG, ++ MTK_WED_GLO_CFG_TX_DMA_EN | ++ MTK_WED_GLO_CFG_RX_DMA_EN); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ ++ mtk_wed_set_ext_int(dev, true); ++ val = dev->wlan.wpdma_phys | ++ MTK_PCIE_MIRROR_MAP_EN | ++ FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index); ++ ++ if (dev->hw->index) ++ val |= BIT(1); ++ val |= BIT(0); ++ regmap_write(dev->hw->mirror, dev->hw->index * 4, val); ++ ++ dev->running = true; ++} ++ ++static int ++mtk_wed_attach(struct mtk_wed_device *dev) ++ __releases(RCU) ++{ ++ struct mtk_wed_hw *hw; ++ int ret = 0; ++ ++ RCU_LOCKDEP_WARN(!rcu_read_lock_held(), ++ "mtk_wed_attach without holding the RCU read lock"); ++ ++ if (pci_domain_nr(dev->wlan.pci_dev->bus) > 1 || ++ !try_module_get(THIS_MODULE)) ++ ret = -ENODEV; ++ ++ rcu_read_unlock(); ++ ++ if (ret) ++ return ret; ++ ++ mutex_lock(&hw_lock); ++ ++ hw = mtk_wed_assign(dev); ++ if (!hw) { ++ module_put(THIS_MODULE); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ dev_info(&dev->wlan.pci_dev->dev, "attaching wed device %d\n", hw->index); ++ ++ dev->hw = hw; ++ dev->dev = hw->dev; ++ dev->irq = hw->irq; ++ dev->wdma_idx = hw->index; ++ ++ if (hw->eth->dma_dev == hw->eth->dev && ++ of_dma_is_coherent(hw->eth->dev->of_node)) ++ mtk_eth_set_dma_device(hw->eth, hw->dev); ++ ++ ret = mtk_wed_buffer_alloc(dev); ++ if (ret) { ++ mtk_wed_detach(dev); ++ goto out; ++ } ++ ++ mtk_wed_hw_init_early(dev); ++ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, BIT(hw->index), 0); ++ ++out: ++ mutex_unlock(&hw_lock); ++ ++ return ret; ++} ++ ++static int ++mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->tx_ring[idx]; ++ ++ /* ++ * Tx ring redirection: ++ * Instead of configuring the WLAN PDMA TX ring directly, the WLAN ++ * driver allocated DMA ring gets configured into WED MTK_WED_RING_TX(n) ++ * registers. ++ * ++ * WED driver posts its own DMA ring as WLAN PDMA TX and configures it ++ * into MTK_WED_WPDMA_RING_TX(n) registers. ++ * It gets filled with packets picked up from WED TX ring and from ++ * WDMA RX. ++ */ ++ ++ BUG_ON(idx > ARRAY_SIZE(dev->tx_ring)); ++ ++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE)) ++ return -ENOMEM; ++ ++ if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE)) ++ return -ENOMEM; ++ ++ ring->reg_base = MTK_WED_RING_TX(idx); ++ ring->wpdma = regs; ++ ++ /* WED -> WPDMA */ ++ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); ++ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_TX_RING_SIZE); ++ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_CPU_IDX, 0); ++ ++ wed_w32(dev, MTK_WED_WPDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, ++ ring->desc_phys); ++ wed_w32(dev, MTK_WED_WPDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, ++ MTK_WED_TX_RING_SIZE); ++ wed_w32(dev, MTK_WED_WPDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0); ++ ++ return 0; ++} ++ ++static int ++mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->txfree_ring; ++ int i; ++ ++ /* ++ * For txfree event handling, the same DMA ring is shared between WED ++ * and WLAN. The WLAN driver accesses the ring index registers through ++ * WED ++ */ ++ ring->reg_base = MTK_WED_RING_RX(1); ++ ring->wpdma = regs; ++ ++ for (i = 0; i < 12; i += 4) { ++ u32 val = readl(regs + i); ++ ++ wed_w32(dev, MTK_WED_RING_RX(1) + i, val); ++ wed_w32(dev, MTK_WED_WPDMA_RING_RX(1) + i, val); ++ } ++ ++ return 0; ++} ++ ++static u32 ++mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) ++{ ++ u32 val; ++ ++ val = wed_r32(dev, MTK_WED_EXT_INT_STATUS); ++ wed_w32(dev, MTK_WED_EXT_INT_STATUS, val); ++ val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK; ++ if (!dev->hw->num_flows) ++ val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; ++ if (val && net_ratelimit()) ++ pr_err("mtk_wed%d: error status=%08x\n", dev->hw->index, val); ++ ++ val = wed_r32(dev, MTK_WED_INT_STATUS); ++ val &= mask; ++ wed_w32(dev, MTK_WED_INT_STATUS, val); /* ACK */ ++ ++ return val; ++} ++ ++static void ++mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) ++{ ++ if (!dev->running) ++ return; ++ ++ mtk_wed_set_ext_int(dev, !!mask); ++ wed_w32(dev, MTK_WED_INT_MASK, mask); ++} ++ ++int mtk_wed_flow_add(int index) ++{ ++ struct mtk_wed_hw *hw = hw_list[index]; ++ int ret; ++ ++ if (!hw || !hw->wed_dev) ++ return -ENODEV; ++ ++ if (hw->num_flows) { ++ hw->num_flows++; ++ return 0; ++ } ++ ++ mutex_lock(&hw_lock); ++ if (!hw->wed_dev) { ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ ret = hw->wed_dev->wlan.offload_enable(hw->wed_dev); ++ if (!ret) ++ hw->num_flows++; ++ mtk_wed_set_ext_int(hw->wed_dev, true); ++ ++out: ++ mutex_unlock(&hw_lock); ++ ++ return ret; ++} ++ ++void mtk_wed_flow_remove(int index) ++{ ++ struct mtk_wed_hw *hw = hw_list[index]; ++ ++ if (!hw) ++ return; ++ ++ if (--hw->num_flows) ++ return; ++ ++ mutex_lock(&hw_lock); ++ if (!hw->wed_dev) ++ goto out; ++ ++ hw->wed_dev->wlan.offload_disable(hw->wed_dev); ++ mtk_wed_set_ext_int(hw->wed_dev, true); ++ ++out: ++ mutex_unlock(&hw_lock); ++} ++ ++void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, ++ void __iomem *wdma, int index) ++{ ++ static const struct mtk_wed_ops wed_ops = { ++ .attach = mtk_wed_attach, ++ .tx_ring_setup = mtk_wed_tx_ring_setup, ++ .txfree_ring_setup = mtk_wed_txfree_ring_setup, ++ .start = mtk_wed_start, ++ .stop = mtk_wed_stop, ++ .reset_dma = mtk_wed_reset_dma, ++ .reg_read = wed_r32, ++ .reg_write = wed_w32, ++ .irq_get = mtk_wed_irq_get, ++ .irq_set_mask = mtk_wed_irq_set_mask, ++ .detach = mtk_wed_detach, ++ }; ++ struct device_node *eth_np = eth->dev->of_node; ++ struct platform_device *pdev; ++ struct mtk_wed_hw *hw; ++ struct regmap *regs; ++ int irq; ++ ++ if (!np) ++ return; ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev) ++ return; ++ ++ get_device(&pdev->dev); ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return; ++ ++ regs = syscon_regmap_lookup_by_phandle(np, NULL); ++ if (!regs) ++ return; ++ ++ rcu_assign_pointer(mtk_soc_wed_ops, &wed_ops); ++ ++ mutex_lock(&hw_lock); ++ ++ if (WARN_ON(hw_list[index])) ++ goto unlock; ++ ++ hw = kzalloc(sizeof(*hw), GFP_KERNEL); ++ hw->node = np; ++ hw->regs = regs; ++ hw->eth = eth; ++ hw->dev = &pdev->dev; ++ hw->wdma = wdma; ++ hw->index = index; ++ hw->irq = irq; ++ hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, ++ "mediatek,pcie-mirror"); ++ hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, ++ "mediatek,hifsys"); ++ if (IS_ERR(hw->mirror) || IS_ERR(hw->hifsys)) { ++ kfree(hw); ++ goto unlock; ++ } ++ ++ if (!index) { ++ regmap_write(hw->mirror, 0, 0); ++ regmap_write(hw->mirror, 4, 0); ++ } ++ mtk_wed_hw_add_debugfs(hw); ++ ++ hw_list[index] = hw; ++ ++unlock: ++ mutex_unlock(&hw_lock); ++} ++ ++void mtk_wed_exit(void) ++{ ++ int i; ++ ++ rcu_assign_pointer(mtk_soc_wed_ops, NULL); ++ ++ synchronize_rcu(); ++ ++ for (i = 0; i < ARRAY_SIZE(hw_list); i++) { ++ struct mtk_wed_hw *hw; ++ ++ hw = hw_list[i]; ++ if (!hw) ++ continue; ++ ++ hw_list[i] = NULL; ++ debugfs_remove(hw->debugfs_dir); ++ put_device(hw->dev); ++ kfree(hw); ++ } ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -0,0 +1,128 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2021 Felix Fietkau */ ++ ++#ifndef __MTK_WED_PRIV_H ++#define __MTK_WED_PRIV_H ++ ++#include ++#include ++#include ++ ++struct mtk_eth; ++ ++struct mtk_wed_hw { ++ struct device_node *node; ++ struct mtk_eth *eth; ++ struct regmap *regs; ++ struct regmap *hifsys; ++ struct device *dev; ++ void __iomem *wdma; ++ struct regmap *mirror; ++ struct dentry *debugfs_dir; ++ struct mtk_wed_device *wed_dev; ++ u32 debugfs_reg; ++ u32 num_flows; ++ char dirname[5]; ++ int irq; ++ int index; ++}; ++ ++ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++static inline void ++wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ regmap_write(dev->hw->regs, reg, val); ++} ++ ++static inline u32 ++wed_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ unsigned int val; ++ ++ regmap_read(dev->hw->regs, reg, &val); ++ ++ return val; ++} ++ ++static inline void ++wdma_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ writel(val, dev->hw->wdma + reg); ++} ++ ++static inline u32 ++wdma_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ return readl(dev->hw->wdma + reg); ++} ++ ++static inline u32 ++wpdma_tx_r32(struct mtk_wed_device *dev, int ring, u32 reg) ++{ ++ if (!dev->tx_ring[ring].wpdma) ++ return 0; ++ ++ return readl(dev->tx_ring[ring].wpdma + reg); ++} ++ ++static inline void ++wpdma_tx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val) ++{ ++ if (!dev->tx_ring[ring].wpdma) ++ return; ++ ++ writel(val, dev->tx_ring[ring].wpdma + reg); ++} ++ ++static inline u32 ++wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg) ++{ ++ if (!dev->txfree_ring.wpdma) ++ return 0; ++ ++ return readl(dev->txfree_ring.wpdma + reg); ++} ++ ++static inline void ++wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val) ++{ ++ if (!dev->txfree_ring.wpdma) ++ return; ++ ++ writel(val, dev->txfree_ring.wpdma + reg); ++} ++ ++void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, ++ void __iomem *wdma, int index); ++void mtk_wed_exit(void); ++int mtk_wed_flow_add(int index); ++void mtk_wed_flow_remove(int index); ++#else ++static inline void ++mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, ++ void __iomem *wdma, int index) ++{ ++} ++static inline void ++mtk_wed_exit(void) ++{ ++} ++static inline int mtk_wed_flow_add(int index) ++{ ++ return -EINVAL; ++} ++static inline void mtk_wed_flow_remove(int index) ++{ ++} ++#endif ++ ++#ifdef CONFIG_DEBUG_FS ++void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw); ++#else ++static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw) ++{ ++} ++#endif ++ ++#endif +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -0,0 +1,175 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2021 Felix Fietkau */ ++ ++#include ++#include "mtk_wed.h" ++#include "mtk_wed_regs.h" ++ ++struct reg_dump { ++ const char *name; ++ u16 offset; ++ u8 type; ++ u8 base; ++}; ++ ++enum { ++ DUMP_TYPE_STRING, ++ DUMP_TYPE_WED, ++ DUMP_TYPE_WDMA, ++ DUMP_TYPE_WPDMA_TX, ++ DUMP_TYPE_WPDMA_TXFREE, ++}; ++ ++#define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } ++#define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ } ++#define DUMP_RING(_prefix, _base, ...) \ ++ { _prefix " BASE", _base, __VA_ARGS__ }, \ ++ { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \ ++ { _prefix " CIDX", _base + 0x8, __VA_ARGS__ }, \ ++ { _prefix " DIDX", _base + 0xc, __VA_ARGS__ } ++ ++#define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED) ++#define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED) ++ ++#define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA) ++#define DUMP_WDMA_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WDMA) ++ ++#define DUMP_WPDMA_TX_RING(_n) DUMP_RING("WPDMA_TX" #_n, 0, DUMP_TYPE_WPDMA_TX, _n) ++#define DUMP_WPDMA_TXFREE_RING DUMP_RING("WPDMA_RX1", 0, DUMP_TYPE_WPDMA_TXFREE) ++ ++static void ++print_reg_val(struct seq_file *s, const char *name, u32 val) ++{ ++ seq_printf(s, "%-32s %08x\n", name, val); ++} ++ ++static void ++dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev, ++ const struct reg_dump *regs, int n_regs) ++{ ++ const struct reg_dump *cur; ++ u32 val; ++ ++ for (cur = regs; cur < ®s[n_regs]; cur++) { ++ switch (cur->type) { ++ case DUMP_TYPE_STRING: ++ seq_printf(s, "%s======== %s:\n", ++ cur > regs ? "\n" : "", ++ cur->name); ++ continue; ++ case DUMP_TYPE_WED: ++ val = wed_r32(dev, cur->offset); ++ break; ++ case DUMP_TYPE_WDMA: ++ val = wdma_r32(dev, cur->offset); ++ break; ++ case DUMP_TYPE_WPDMA_TX: ++ val = wpdma_tx_r32(dev, cur->base, cur->offset); ++ break; ++ case DUMP_TYPE_WPDMA_TXFREE: ++ val = wpdma_txfree_r32(dev, cur->offset); ++ break; ++ } ++ print_reg_val(s, cur->name, val); ++ } ++} ++ ++ ++static int ++wed_txinfo_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WED TX"), ++ DUMP_WED(WED_TX_MIB(0)), ++ DUMP_WED_RING(WED_RING_TX(0)), ++ ++ DUMP_WED(WED_TX_MIB(1)), ++ DUMP_WED_RING(WED_RING_TX(1)), ++ ++ DUMP_STR("WPDMA TX"), ++ DUMP_WED(WED_WPDMA_TX_MIB(0)), ++ DUMP_WED_RING(WED_WPDMA_RING_TX(0)), ++ DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(0)), ++ ++ DUMP_WED(WED_WPDMA_TX_MIB(1)), ++ DUMP_WED_RING(WED_WPDMA_RING_TX(1)), ++ DUMP_WED(WED_WPDMA_TX_COHERENT_MIB(1)), ++ ++ DUMP_STR("WPDMA TX"), ++ DUMP_WPDMA_TX_RING(0), ++ DUMP_WPDMA_TX_RING(1), ++ ++ DUMP_STR("WED WDMA RX"), ++ DUMP_WED(WED_WDMA_RX_MIB(0)), ++ DUMP_WED_RING(WED_WDMA_RING_RX(0)), ++ DUMP_WED(WED_WDMA_RX_THRES(0)), ++ DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(0)), ++ DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(0)), ++ ++ DUMP_WED(WED_WDMA_RX_MIB(1)), ++ DUMP_WED_RING(WED_WDMA_RING_RX(1)), ++ DUMP_WED(WED_WDMA_RX_THRES(1)), ++ DUMP_WED(WED_WDMA_RX_RECYCLE_MIB(1)), ++ DUMP_WED(WED_WDMA_RX_PROCESSED_MIB(1)), ++ ++ DUMP_STR("WDMA RX"), ++ DUMP_WDMA(WDMA_GLO_CFG), ++ DUMP_WDMA_RING(WDMA_RING_RX(0)), ++ DUMP_WDMA_RING(WDMA_RING_RX(1)), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (!dev) ++ return 0; ++ ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_txinfo); ++ ++ ++static int ++mtk_wed_reg_set(void *data, u64 val) ++{ ++ struct mtk_wed_hw *hw = data; ++ ++ regmap_write(hw->regs, hw->debugfs_reg, val); ++ ++ return 0; ++} ++ ++static int ++mtk_wed_reg_get(void *data, u64 *val) ++{ ++ struct mtk_wed_hw *hw = data; ++ unsigned int regval; ++ int ret; ++ ++ ret = regmap_read(hw->regs, hw->debugfs_reg, ®val); ++ if (ret) ++ return ret; ++ ++ *val = regval; ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set, ++ "0x%08llx\n"); ++ ++void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw) ++{ ++ struct dentry *dir; ++ ++ snprintf(hw->dirname, sizeof(hw->dirname), "wed%d", hw->index); ++ dir = debugfs_create_dir(hw->dirname, NULL); ++ if (!dir) ++ return; ++ ++ hw->debugfs_dir = dir; ++ debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); ++ debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); ++ debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_ops.c +@@ -0,0 +1,8 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#include ++#include ++ ++const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; ++EXPORT_SYMBOL_GPL(mtk_soc_wed_ops); +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -0,0 +1,251 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (C) 2020 Felix Fietkau */ ++ ++#ifndef __MTK_WED_REGS_H ++#define __MTK_WED_REGS_H ++ ++#define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0) ++#define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15) ++#define MTK_WDMA_DESC_CTRL_BURST BIT(16) ++#define MTK_WDMA_DESC_CTRL_LEN0 GENMASK(29, 16) ++#define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30) ++#define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31) ++ ++struct mtk_wdma_desc { ++ __le32 buf0; ++ __le32 ctrl; ++ __le32 buf1; ++ __le32 info; ++} __packed __aligned(4); ++ ++#define MTK_WED_RESET 0x008 ++#define MTK_WED_RESET_TX_BM BIT(0) ++#define MTK_WED_RESET_TX_FREE_AGENT BIT(4) ++#define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) ++#define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) ++#define MTK_WED_RESET_WPDMA_INT_AGENT BIT(11) ++#define MTK_WED_RESET_WED_TX_DMA BIT(12) ++#define MTK_WED_RESET_WDMA_RX_DRV BIT(17) ++#define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) ++#define MTK_WED_RESET_WED BIT(31) ++ ++#define MTK_WED_CTRL 0x00c ++#define MTK_WED_CTRL_WPDMA_INT_AGENT_EN BIT(0) ++#define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY BIT(1) ++#define MTK_WED_CTRL_WDMA_INT_AGENT_EN BIT(2) ++#define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3) ++#define MTK_WED_CTRL_WED_TX_BM_EN BIT(8) ++#define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) ++#define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) ++#define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11) ++#define MTK_WED_CTRL_RESERVE_EN BIT(12) ++#define MTK_WED_CTRL_RESERVE_BUSY BIT(13) ++#define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) ++#define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) ++ ++#define MTK_WED_EXT_INT_STATUS 0x020 ++#define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR BIT(0) ++#define MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD BIT(1) ++#define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID BIT(4) ++#define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH BIT(8) ++#define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH BIT(9) ++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH BIT(12) ++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH BIT(13) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN BIT(19) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_BM_DMAD_COHERENT BIT(20) ++#define MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR BIT(21) ++#define MTK_WED_EXT_INT_STATUS_TX_DRV_W_RESP_ERR BIT(22) ++#define MTK_WED_EXT_INT_STATUS_RX_DRV_DMA_RECYCLE BIT(24) ++#define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \ ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \ ++ MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \ ++ MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \ ++ MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \ ++ MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \ ++ MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR | \ ++ MTK_WED_EXT_INT_STATUS_TX_DRV_W_RESP_ERR) ++ ++#define MTK_WED_EXT_INT_MASK 0x028 ++ ++#define MTK_WED_STATUS 0x060 ++#define MTK_WED_STATUS_TX GENMASK(15, 8) ++ ++#define MTK_WED_TX_BM_CTRL 0x080 ++#define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0) ++#define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16) ++#define MTK_WED_TX_BM_CTRL_PAUSE BIT(28) ++ ++#define MTK_WED_TX_BM_BASE 0x084 ++ ++#define MTK_WED_TX_BM_TKID 0x088 ++#define MTK_WED_TX_BM_TKID_START GENMASK(15, 0) ++#define MTK_WED_TX_BM_TKID_END GENMASK(31, 16) ++ ++#define MTK_WED_TX_BM_BUF_LEN 0x08c ++ ++#define MTK_WED_TX_BM_INTF 0x09c ++#define MTK_WED_TX_BM_INTF_TKID GENMASK(15, 0) ++#define MTK_WED_TX_BM_INTF_TKFIFO_FDEP GENMASK(23, 16) ++#define MTK_WED_TX_BM_INTF_TKID_VALID BIT(28) ++#define MTK_WED_TX_BM_INTF_TKID_READ BIT(29) ++ ++#define MTK_WED_TX_BM_DYN_THR 0x0a0 ++#define MTK_WED_TX_BM_DYN_THR_LO GENMASK(6, 0) ++#define MTK_WED_TX_BM_DYN_THR_HI GENMASK(22, 16) ++ ++#define MTK_WED_INT_STATUS 0x200 ++#define MTK_WED_INT_MASK 0x204 ++ ++#define MTK_WED_GLO_CFG 0x208 ++#define MTK_WED_GLO_CFG_TX_DMA_EN BIT(0) ++#define MTK_WED_GLO_CFG_TX_DMA_BUSY BIT(1) ++#define MTK_WED_GLO_CFG_RX_DMA_EN BIT(2) ++#define MTK_WED_GLO_CFG_RX_DMA_BUSY BIT(3) ++#define MTK_WED_GLO_CFG_RX_BT_SIZE GENMASK(5, 4) ++#define MTK_WED_GLO_CFG_TX_WB_DDONE BIT(6) ++#define MTK_WED_GLO_CFG_BIG_ENDIAN BIT(7) ++#define MTK_WED_GLO_CFG_DIS_BT_SIZE_ALIGN BIT(8) ++#define MTK_WED_GLO_CFG_TX_BT_SIZE_LO BIT(9) ++#define MTK_WED_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) ++#define MTK_WED_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) ++#define MTK_WED_GLO_CFG_MI_DEPTH_RD GENMASK(21, 13) ++#define MTK_WED_GLO_CFG_TX_BT_SIZE_HI GENMASK(23, 22) ++#define MTK_WED_GLO_CFG_SW_RESET BIT(24) ++#define MTK_WED_GLO_CFG_FIRST_TOKEN_ONLY BIT(26) ++#define MTK_WED_GLO_CFG_OMIT_RX_INFO BIT(27) ++#define MTK_WED_GLO_CFG_OMIT_TX_INFO BIT(28) ++#define MTK_WED_GLO_CFG_BYTE_SWAP BIT(29) ++#define MTK_WED_GLO_CFG_RX_2B_OFFSET BIT(31) ++ ++#define MTK_WED_RESET_IDX 0x20c ++#define MTK_WED_RESET_IDX_TX GENMASK(3, 0) ++#define MTK_WED_RESET_IDX_RX GENMASK(17, 16) ++ ++#define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) ++ ++#define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10) ++ ++#define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10) ++ ++#define MTK_WED_WPDMA_INT_TRIGGER 0x504 ++#define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) ++#define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) ++ ++#define MTK_WED_WPDMA_GLO_CFG 0x508 ++#define MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN BIT(0) ++#define MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY BIT(1) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN BIT(2) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY BIT(3) ++#define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE GENMASK(5, 4) ++#define MTK_WED_WPDMA_GLO_CFG_TX_WB_DDONE BIT(6) ++#define MTK_WED_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) ++#define MTK_WED_WPDMA_GLO_CFG_DIS_BT_SIZE_ALIGN BIT(8) ++#define MTK_WED_WPDMA_GLO_CFG_TX_BT_SIZE_LO BIT(9) ++#define MTK_WED_WPDMA_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) ++#define MTK_WED_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) ++#define MTK_WED_WPDMA_GLO_CFG_MI_DEPTH_RD GENMASK(21, 13) ++#define MTK_WED_WPDMA_GLO_CFG_TX_BT_SIZE_HI GENMASK(23, 22) ++#define MTK_WED_WPDMA_GLO_CFG_SW_RESET BIT(24) ++#define MTK_WED_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY BIT(26) ++#define MTK_WED_WPDMA_GLO_CFG_OMIT_RX_INFO BIT(27) ++#define MTK_WED_WPDMA_GLO_CFG_OMIT_TX_INFO BIT(28) ++#define MTK_WED_WPDMA_GLO_CFG_BYTE_SWAP BIT(29) ++#define MTK_WED_WPDMA_GLO_CFG_RX_2B_OFFSET BIT(31) ++ ++#define MTK_WED_WPDMA_RESET_IDX 0x50c ++#define MTK_WED_WPDMA_RESET_IDX_TX GENMASK(3, 0) ++#define MTK_WED_WPDMA_RESET_IDX_RX GENMASK(17, 16) ++ ++#define MTK_WED_WPDMA_INT_CTRL 0x520 ++#define MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV BIT(21) ++ ++#define MTK_WED_WPDMA_INT_MASK 0x524 ++ ++#define MTK_WED_PCIE_CFG_BASE 0x560 ++ ++#define MTK_WED_PCIE_INT_TRIGGER 0x570 ++#define MTK_WED_PCIE_INT_TRIGGER_STATUS BIT(16) ++ ++#define MTK_WED_WPDMA_CFG_BASE 0x580 ++ ++#define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) ++#define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) ++ ++#define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) ++#define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) ++#define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) ++#define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) ++ ++#define MTK_WED_WDMA_GLO_CFG 0xa04 ++#define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) ++#define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2) ++#define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3) ++#define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4) ++#define MTK_WED_WDMA_GLO_CFG_TX_WB_DDONE BIT(6) ++#define MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE BIT(13) ++#define MTK_WED_WDMA_GLO_CFG_WCOMPLETE_SEL BIT(16) ++#define MTK_WED_WDMA_GLO_CFG_INIT_PHASE_RXDMA_BYPASS BIT(17) ++#define MTK_WED_WDMA_GLO_CFG_INIT_PHASE_BYPASS BIT(18) ++#define MTK_WED_WDMA_GLO_CFG_FSM_RETURN_IDLE BIT(19) ++#define MTK_WED_WDMA_GLO_CFG_WAIT_COHERENT BIT(20) ++#define MTK_WED_WDMA_GLO_CFG_AXI_W_AFTER_AW BIT(21) ++#define MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY_SINGLE_W BIT(22) ++#define MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY BIT(23) ++#define MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP BIT(24) ++#define MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE BIT(25) ++#define MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE BIT(26) ++#define MTK_WED_WDMA_GLO_CFG_RXDRV_CLKGATE_BYPASS BIT(30) ++ ++#define MTK_WED_WDMA_RESET_IDX 0xa08 ++#define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16) ++#define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24) ++ ++#define MTK_WED_WDMA_INT_TRIGGER 0xa28 ++#define MTK_WED_WDMA_INT_TRIGGER_RX_DONE GENMASK(17, 16) ++ ++#define MTK_WED_WDMA_INT_CTRL 0xa2c ++#define MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL GENMASK(17, 16) ++ ++#define MTK_WED_WDMA_OFFSET0 0xaa4 ++#define MTK_WED_WDMA_OFFSET1 0xaa8 ++ ++#define MTK_WED_WDMA_RX_MIB(_n) (0xae0 + (_n) * 4) ++#define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4) ++#define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4) ++ ++#define MTK_WED_RING_OFS_BASE 0x00 ++#define MTK_WED_RING_OFS_COUNT 0x04 ++#define MTK_WED_RING_OFS_CPU_IDX 0x08 ++#define MTK_WED_RING_OFS_DMA_IDX 0x0c ++ ++#define MTK_WDMA_RING_RX(_n) (0x100 + (_n) * 0x10) ++ ++#define MTK_WDMA_GLO_CFG 0x204 ++#define MTK_WDMA_GLO_CFG_RX_INFO_PRERES GENMASK(28, 26) ++ ++#define MTK_WDMA_RESET_IDX 0x208 ++#define MTK_WDMA_RESET_IDX_TX GENMASK(3, 0) ++#define MTK_WDMA_RESET_IDX_RX GENMASK(17, 16) ++ ++#define MTK_WDMA_INT_MASK 0x228 ++#define MTK_WDMA_INT_MASK_TX_DONE GENMASK(3, 0) ++#define MTK_WDMA_INT_MASK_RX_DONE GENMASK(17, 16) ++#define MTK_WDMA_INT_MASK_TX_DELAY BIT(28) ++#define MTK_WDMA_INT_MASK_TX_COHERENT BIT(29) ++#define MTK_WDMA_INT_MASK_RX_DELAY BIT(30) ++#define MTK_WDMA_INT_MASK_RX_COHERENT BIT(31) ++ ++#define MTK_WDMA_INT_GRP1 0x250 ++#define MTK_WDMA_INT_GRP2 0x254 ++ ++#define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0) ++#define MTK_PCIE_MIRROR_MAP_EN BIT(0) ++#define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1) ++ ++/* DMA channel mapping */ ++#define HIFSYS_DMA_AG_MAP 0x008 ++ ++#endif +--- /dev/null ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -0,0 +1,131 @@ ++#ifndef __MTK_WED_H ++#define __MTK_WED_H ++ ++#include ++#include ++#include ++#include ++ ++#define MTK_WED_TX_QUEUES 2 ++ ++struct mtk_wed_hw; ++struct mtk_wdma_desc; ++ ++struct mtk_wed_ring { ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ int size; ++ ++ u32 reg_base; ++ void __iomem *wpdma; ++}; ++ ++struct mtk_wed_device { ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ const struct mtk_wed_ops *ops; ++ struct device *dev; ++ struct mtk_wed_hw *hw; ++ bool init_done, running; ++ int wdma_idx; ++ int irq; ++ ++ struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES]; ++ struct mtk_wed_ring txfree_ring; ++ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; ++ ++ struct { ++ int size; ++ void **pages; ++ struct mtk_wdma_desc *desc; ++ dma_addr_t desc_phys; ++ } buf_ring; ++ ++ /* filled by driver: */ ++ struct { ++ struct pci_dev *pci_dev; ++ ++ u32 wpdma_phys; ++ ++ u16 token_start; ++ unsigned int nbuf; ++ ++ u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); ++ int (*offload_enable)(struct mtk_wed_device *wed); ++ void (*offload_disable)(struct mtk_wed_device *wed); ++ } wlan; ++#endif ++}; ++ ++struct mtk_wed_ops { ++ int (*attach)(struct mtk_wed_device *dev); ++ int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); ++ int (*txfree_ring_setup)(struct mtk_wed_device *dev, ++ void __iomem *regs); ++ void (*detach)(struct mtk_wed_device *dev); ++ ++ void (*stop)(struct mtk_wed_device *dev); ++ void (*start)(struct mtk_wed_device *dev, u32 irq_mask); ++ void (*reset_dma)(struct mtk_wed_device *dev); ++ ++ u32 (*reg_read)(struct mtk_wed_device *dev, u32 reg); ++ void (*reg_write)(struct mtk_wed_device *dev, u32 reg, u32 val); ++ ++ u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask); ++ void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); ++}; ++ ++extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; ++ ++static inline int ++mtk_wed_device_attach(struct mtk_wed_device *dev) ++{ ++ int ret = -ENODEV; ++ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ rcu_read_lock(); ++ dev->ops = rcu_dereference(mtk_soc_wed_ops); ++ if (dev->ops) ++ ret = dev->ops->attach(dev); ++ else ++ rcu_read_unlock(); ++ ++ if (ret) ++ dev->ops = NULL; ++#endif ++ ++ return ret; ++} ++ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++#define mtk_wed_device_active(_dev) !!(_dev)->ops ++#define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev) ++#define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask) ++#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_txfree_ring_setup(_dev, _regs) \ ++ (_dev)->ops->txfree_ring_setup(_dev, _regs) ++#define mtk_wed_device_reg_read(_dev, _reg) \ ++ (_dev)->ops->reg_read(_dev, _reg) ++#define mtk_wed_device_reg_write(_dev, _reg, _val) \ ++ (_dev)->ops->reg_write(_dev, _reg, _val) ++#define mtk_wed_device_irq_get(_dev, _mask) \ ++ (_dev)->ops->irq_get(_dev, _mask) ++#define mtk_wed_device_irq_set_mask(_dev, _mask) \ ++ (_dev)->ops->irq_set_mask(_dev, _mask) ++#else ++static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) ++{ ++ return false; ++} ++#define mtk_wed_device_detach(_dev) do {} while (0) ++#define mtk_wed_device_start(_dev, _mask) do {} while (0) ++#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_reg_read(_dev, _reg) 0 ++#define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0) ++#define mtk_wed_device_irq_get(_dev, _mask) 0 ++#define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0) ++#endif ++ ++#endif diff --git a/target/linux/generic/pending-5.15/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch b/target/linux/generic/pending-5.15/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch new file mode 100644 index 0000000000..9abb68c356 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch @@ -0,0 +1,269 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 18:29:22 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: implement flow offloading + to WED devices + +This allows hardware flow offloading from Ethernet to WLAN on MT7622 SoC + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -329,6 +329,24 @@ int mtk_foe_entry_set_pppoe(struct mtk_f + return 0; + } + ++int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, ++ int bss, int wcid) ++{ ++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); ++ u32 *ib2 = mtk_foe_entry_ib2(entry); ++ ++ *ib2 &= ~MTK_FOE_IB2_PORT_MG; ++ *ib2 |= MTK_FOE_IB2_WDMA_WINFO; ++ if (wdma_idx) ++ *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX; ++ ++ l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | ++ FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | ++ FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); ++ ++ return 0; ++} ++ + static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry) + { + return !(entry->ib1 & MTK_FOE_IB1_STATIC) && +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -48,9 +48,9 @@ enum { + #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) + #define MTK_FOE_IB2_MULTICAST BIT(8) + +-#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12) +-#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16) +-#define MTK_FOE_IB2_WHNAT_NAT BIT(17) ++#define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) ++#define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) ++#define MTK_FOE_IB2_WDMA_WINFO BIT(17) + + #define MTK_FOE_IB2_PORT_MG GENMASK(17, 12) + +@@ -58,9 +58,9 @@ enum { + + #define MTK_FOE_IB2_DSCP GENMASK(31, 24) + +-#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0) +-#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6) +-#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14) ++#define MTK_FOE_VLAN2_WINFO_BSS GENMASK(5, 0) ++#define MTK_FOE_VLAN2_WINFO_WCID GENMASK(13, 6) ++#define MTK_FOE_VLAN2_WINFO_RING GENMASK(15, 14) + + enum { + MTK_FOE_STATE_INVALID, +@@ -281,6 +281,8 @@ int mtk_foe_entry_set_ipv6_tuple(struct + int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port); + int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); + int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); ++int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, ++ int bss, int wcid); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, + u16 timestamp); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -10,6 +10,7 @@ + #include + #include + #include "mtk_eth_soc.h" ++#include "mtk_wed.h" + + struct mtk_flow_data { + struct ethhdr eth; +@@ -39,6 +40,7 @@ struct mtk_flow_entry { + struct rhash_head node; + unsigned long cookie; + u16 hash; ++ s8 wed_index; + }; + + static const struct rhashtable_params mtk_flow_ht_params = { +@@ -80,6 +82,35 @@ mtk_flow_offload_mangle_eth(const struct + memcpy(dest, src, act->mangle.mask ? 2 : 4); + } + ++static int ++mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info) ++{ ++ struct net_device_path_ctx ctx = { ++ .dev = dev, ++ .daddr = addr, ++ }; ++ struct net_device_path path = {}; ++ ++ if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)) ++ return -1; ++ ++ if (!dev->netdev_ops->ndo_fill_forward_path) ++ return -1; ++ ++ if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path)) ++ return -1; ++ ++ if (path.type != DEV_PATH_MTK_WDMA) ++ return -1; ++ ++ info->wdma_idx = path.mtk_wdma.wdma_idx; ++ info->queue = path.mtk_wdma.queue; ++ info->bss = path.mtk_wdma.bss; ++ info->wcid = path.mtk_wdma.wcid; ++ ++ return 0; ++} ++ + + static int + mtk_flow_mangle_ports(const struct flow_action_entry *act, +@@ -149,10 +180,20 @@ mtk_flow_get_dsa_port(struct net_device + + static int + mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, +- struct net_device *dev) ++ struct net_device *dev, const u8 *dest_mac, ++ int *wed_index) + { ++ struct mtk_wdma_info info = {}; + int pse_port, dsa_port; + ++ if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { ++ mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss, ++ info.wcid); ++ pse_port = 3; ++ *wed_index = info.wdma_idx; ++ goto out; ++ } ++ + dsa_port = mtk_flow_get_dsa_port(&dev); + if (dsa_port >= 0) + mtk_foe_entry_set_dsa(foe, dsa_port); +@@ -164,6 +205,7 @@ mtk_flow_set_output_device(struct mtk_et + else + return -EOPNOTSUPP; + ++out: + mtk_foe_entry_set_pse_port(foe, pse_port); + + return 0; +@@ -179,6 +221,7 @@ mtk_flow_offload_replace(struct mtk_eth + struct net_device *odev = NULL; + struct mtk_flow_entry *entry; + int offload_type = 0; ++ int wed_index = -1; + u16 addr_type = 0; + u32 timestamp; + u8 l4proto = 0; +@@ -329,10 +372,14 @@ mtk_flow_offload_replace(struct mtk_eth + if (data.pppoe.num == 1) + mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); + +- err = mtk_flow_set_output_device(eth, &foe, odev); ++ err = mtk_flow_set_output_device(eth, &foe, odev, data.eth.h_dest, ++ &wed_index); + if (err) + return err; + ++ if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0) ++ return err; ++ + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; +@@ -346,6 +393,7 @@ mtk_flow_offload_replace(struct mtk_eth + } + + entry->hash = hash; ++ entry->wed_index = wed_index; + err = rhashtable_insert_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (err < 0) +@@ -356,6 +404,8 @@ clear_flow: + mtk_foe_entry_clear(ð->ppe, hash); + free: + kfree(entry); ++ if (wed_index >= 0) ++ mtk_wed_flow_remove(wed_index); + return err; + } + +@@ -372,6 +422,8 @@ mtk_flow_offload_destroy(struct mtk_eth + mtk_foe_entry_clear(ð->ppe, entry->hash); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); ++ if (entry->wed_index >= 0) ++ mtk_wed_flow_remove(entry->wed_index); + kfree(entry); + + return 0; +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + struct mtk_eth; + +@@ -27,6 +28,12 @@ struct mtk_wed_hw { + int index; + }; + ++struct mtk_wdma_info { ++ u8 wdma_idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++}; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + static inline void +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -849,6 +849,7 @@ enum net_device_path_type { + DEV_PATH_BRIDGE, + DEV_PATH_PPPOE, + DEV_PATH_DSA, ++ DEV_PATH_MTK_WDMA, + }; + + struct net_device_path { +@@ -874,6 +875,12 @@ struct net_device_path { + int port; + u16 proto; + } dsa; ++ struct { ++ u8 wdma_idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++ } mtk_wdma; + }; + }; + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -761,6 +761,10 @@ int dev_fill_forward_path(const struct n + if (WARN_ON_ONCE(last_dev == ctx.dev)) + return -1; + } ++ ++ if (!ctx.dev) ++ return ret; ++ + path = dev_fwd_path(stack); + if (!path) + return -1; diff --git a/target/linux/generic/pending-5.15/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch b/target/linux/generic/pending-5.15/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch new file mode 100644 index 0000000000..f59a364a73 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-04-arm64-dts-mediatek-mt7622-introduce-nodes-for-Wirele.patch @@ -0,0 +1,62 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 18:36:36 +0100 +Subject: [PATCH] arm64: dts: mediatek: mt7622: introduce nodes for + Wireless Ethernet Dispatch + +Introduce wed0 and wed1 nodes in order to enable offloading forwarding +between ethernet and wireless devices on the mt7622 chipset. + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -893,6 +893,11 @@ + }; + }; + ++ hifsys: syscon@1af00000 { ++ compatible = "mediatek,mt7622-hifsys", "syscon"; ++ reg = <0 0x1af00000 0 0x70>; ++ }; ++ + ethsys: syscon@1b000000 { + compatible = "mediatek,mt7622-ethsys", + "syscon"; +@@ -911,6 +916,26 @@ + #dma-cells = <1>; + }; + ++ pcie_mirror: pcie-mirror@10000400 { ++ compatible = "mediatek,mt7622-pcie-mirror", ++ "syscon"; ++ reg = <0 0x10000400 0 0x10>; ++ }; ++ ++ wed0: wed@1020a000 { ++ compatible = "mediatek,mt7622-wed", ++ "syscon"; ++ reg = <0 0x1020a000 0 0x1000>; ++ interrupts = ; ++ }; ++ ++ wed1: wed@1020b000 { ++ compatible = "mediatek,mt7622-wed", ++ "syscon"; ++ reg = <0 0x1020b000 0 0x1000>; ++ interrupts = ; ++ }; ++ + eth: ethernet@1b100000 { + compatible = "mediatek,mt7622-eth", + "mediatek,mt2701-eth", +@@ -938,6 +963,9 @@ + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys>; + mediatek,cci-control = <&cci_control2>; ++ mediatek,wed = <&wed0>, <&wed1>; ++ mediatek,pcie-mirror = <&pcie_mirror>; ++ mediatek,hifsys = <&hifsys>; + dma-coherent; + #address-cells = <1>; + #size-cells = <0>; diff --git a/target/linux/generic/pending-5.10/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch b/target/linux/generic/pending-5.15/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch similarity index 69% rename from target/linux/generic/pending-5.10/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch rename to target/linux/generic/pending-5.15/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch index 7140c6877e..b2114eb02d 100644 --- a/target/linux/generic/pending-5.10/701-net-ethernet-mtk_eth_soc-add-ipv6-flow-offloading-support.patch +++ b/target/linux/generic/pending-5.15/701-05-net-ethernet-mtk_eth_soc-add-ipv6-flow-offload-suppo.patch @@ -1,8 +1,22 @@ +From: David Bentham +Date: Mon, 21 Feb 2022 15:36:16 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add ipv6 flow offload + support + +Add the missing IPv6 flow offloading support for routing only. +Hardware flow offloading is done by the packet processing engine (PPE) +of the Ethernet MAC and as it doesn't support mangling of IPv6 packets, +IPv6 NAT cannot be supported. + +Signed-off-by: David Bentham +Signed-off-by: Felix Fietkau +--- + --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -7,6 +7,7 @@ - #include +@@ -6,6 +6,7 @@ #include + #include #include +#include #include @@ -20,7 +34,7 @@ }; __be16 src_port; -@@ -64,6 +70,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en +@@ -65,6 +71,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en data->v4.dst_addr, data->dst_port); } @@ -35,7 +49,7 @@ static void mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth) { -@@ -254,6 +268,9 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -299,6 +313,9 @@ mtk_flow_offload_replace(struct mtk_eth case FLOW_DISSECTOR_KEY_IPV4_ADDRS: offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; break; @@ -45,7 +59,7 @@ default: return -EOPNOTSUPP; } -@@ -289,6 +306,17 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -334,6 +351,17 @@ mtk_flow_offload_replace(struct mtk_eth mtk_flow_set_ipv4_addr(&foe, &data, false); } diff --git a/target/linux/generic/pending-5.15/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch b/target/linux/generic/pending-5.15/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch new file mode 100644 index 0000000000..a9fc70533d --- /dev/null +++ b/target/linux/generic/pending-5.15/701-06-net-ethernet-mtk_eth_soc-support-TC_SETUP_BLOCK-for-.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:37:21 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: support TC_SETUP_BLOCK for + PPE offload + +This allows offload entries to be created from user space + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -566,10 +566,13 @@ mtk_eth_setup_tc_block(struct net_device + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data) + { +- if (type == TC_SETUP_FT) ++ switch (type) { ++ case TC_SETUP_BLOCK: ++ case TC_SETUP_FT: + return mtk_eth_setup_tc_block(dev, type_data); +- +- return -EOPNOTSUPP; ++ default: ++ return -EOPNOTSUPP; ++ } + } + + int mtk_eth_offload_init(struct mtk_eth *eth) diff --git a/target/linux/generic/pending-5.15/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch b/target/linux/generic/pending-5.15/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch new file mode 100644 index 0000000000..7c6931d333 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-07-net-ethernet-mtk_eth_soc-allocate-struct-mtk_ppe-sep.patch @@ -0,0 +1,159 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:38:20 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: allocate struct mtk_ppe + separately + +Preparation for adding more data to it, which will increase its size. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2312,7 +2312,7 @@ static int mtk_open(struct net_device *d + if (err) + return err; + +- if (eth->soc->offload_version && mtk_ppe_start(ð->ppe) == 0) ++ if (eth->soc->offload_version && mtk_ppe_start(eth->ppe) == 0) + gdm_config = MTK_GDMA_TO_PPE; + + mtk_gdm_config(eth, gdm_config); +@@ -2386,7 +2386,7 @@ static int mtk_stop(struct net_device *d + mtk_dma_free(eth); + + if (eth->soc->offload_version) +- mtk_ppe_stop(ð->ppe); ++ mtk_ppe_stop(eth->ppe); + + return 0; + } +@@ -3278,10 +3278,11 @@ static int mtk_probe(struct platform_dev + } + + if (eth->soc->offload_version) { +- err = mtk_ppe_init(ð->ppe, eth->dev, +- eth->base + MTK_ETH_PPE_BASE, 2); +- if (err) ++ eth->ppe = mtk_ppe_init(eth->dev, eth->base + MTK_ETH_PPE_BASE, 2); ++ if (!eth->ppe) { ++ err = -ENOMEM; + goto err_free_dev; ++ } + + err = mtk_eth_offload_init(eth); + if (err) +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -982,7 +982,7 @@ struct mtk_eth { + u32 rx_dma_l4_valid; + int ip_align; + +- struct mtk_ppe ppe; ++ struct mtk_ppe *ppe; + struct rhashtable flow_table; + }; + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -384,10 +384,15 @@ int mtk_foe_entry_commit(struct mtk_ppe + return hash; + } + +-int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, ++struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, + int version) + { + struct mtk_foe_entry *foe; ++ struct mtk_ppe *ppe; ++ ++ ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL); ++ if (!ppe) ++ return NULL; + + /* need to allocate a separate device, since it PPE DMA access is + * not coherent. +@@ -399,13 +404,13 @@ int mtk_ppe_init(struct mtk_ppe *ppe, st + foe = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*foe), + &ppe->foe_phys, GFP_KERNEL); + if (!foe) +- return -ENOMEM; ++ return NULL; + + ppe->foe_table = foe; + + mtk_ppe_debugfs_init(ppe); + +- return 0; ++ return ppe; + } + + static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -246,8 +246,7 @@ struct mtk_ppe { + void *acct_table; + }; + +-int mtk_ppe_init(struct mtk_ppe *ppe, struct device *dev, void __iomem *base, +- int version); ++struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, int version); + int mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -414,7 +414,7 @@ mtk_flow_offload_replace(struct mtk_eth + + entry->cookie = f->cookie; + timestamp = mtk_eth_timestamp(eth); +- hash = mtk_foe_entry_commit(ð->ppe, &foe, timestamp); ++ hash = mtk_foe_entry_commit(eth->ppe, &foe, timestamp); + if (hash < 0) { + err = hash; + goto free; +@@ -429,7 +429,7 @@ mtk_flow_offload_replace(struct mtk_eth + + return 0; + clear_flow: +- mtk_foe_entry_clear(ð->ppe, hash); ++ mtk_foe_entry_clear(eth->ppe, hash); + free: + kfree(entry); + if (wed_index >= 0) +@@ -447,7 +447,7 @@ mtk_flow_offload_destroy(struct mtk_eth + if (!entry) + return -ENOENT; + +- mtk_foe_entry_clear(ð->ppe, entry->hash); ++ mtk_foe_entry_clear(eth->ppe, entry->hash); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (entry->wed_index >= 0) +@@ -469,7 +469,7 @@ mtk_flow_offload_stats(struct mtk_eth *e + if (!entry) + return -ENOENT; + +- timestamp = mtk_foe_entry_timestamp(ð->ppe, entry->hash); ++ timestamp = mtk_foe_entry_timestamp(eth->ppe, entry->hash); + if (timestamp < 0) + return -ETIMEDOUT; + +@@ -525,7 +525,7 @@ mtk_eth_setup_tc_block(struct net_device + struct flow_block_cb *block_cb; + flow_setup_cb_t *cb; + +- if (!eth->ppe.foe_table) ++ if (!eth->ppe || !eth->ppe->foe_table) + return -EOPNOTSUPP; + + if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) +@@ -577,7 +577,7 @@ int mtk_eth_setup_tc(struct net_device * + + int mtk_eth_offload_init(struct mtk_eth *eth) + { +- if (!eth->ppe.foe_table) ++ if (!eth->ppe || !eth->ppe->foe_table) + return 0; + + return rhashtable_init(ð->flow_table, &mtk_flow_ht_params); diff --git a/target/linux/generic/pending-5.15/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch b/target/linux/generic/pending-5.15/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch new file mode 100644 index 0000000000..5c726c60a1 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-08-net-ethernet-mtk_eth_soc-rework-hardware-flow-table-.patch @@ -0,0 +1,424 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:39:18 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: rework hardware flow table + management + +The hardware was designed to handle flow detection and creation of flow entries +by itself, relying on the software primarily for filling in egress routing +information. +When there is a hash collision between multiple flows, this allows the hardware +to maintain the entry for the most active flow. +Additionally, the hardware only keeps offloading active for entries with at +least 30 packets per second. + +With this rework, the code no longer creates a hardware entries directly. +Instead, the hardware entry is only created when the PPE reports a matching +unbound flow with the minimum target rate. +In order to reduce CPU overhead, looking for flows belonging to a hash entry +is rate limited to once every 100ms. + +This rework is also used as preparation for emulating bridge offload by +managing L4 offload entries on demand. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + + #include "mtk_eth_soc.h" +@@ -1281,7 +1282,7 @@ static int mtk_poll_rx(struct napi_struc + struct net_device *netdev; + unsigned int pktlen; + dma_addr_t dma_addr; +- u32 hash; ++ u32 hash, reason; + int mac; + + ring = mtk_get_rx_ring(eth); +@@ -1357,6 +1358,11 @@ static int mtk_poll_rx(struct napi_struc + skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); + } + ++ reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4); ++ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) ++ mtk_ppe_check_skb(eth->ppe, skb, ++ trxd.rxd4 & MTK_RXD4_FOE_ENTRY); ++ + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && + (trxd.rxd2 & RX_DMA_VTAG)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), +@@ -3278,7 +3284,7 @@ static int mtk_probe(struct platform_dev + } + + if (eth->soc->offload_version) { +- eth->ppe = mtk_ppe_init(eth->dev, eth->base + MTK_ETH_PPE_BASE, 2); ++ eth->ppe = mtk_ppe_init(eth, eth->base + MTK_ETH_PPE_BASE, 2); + if (!eth->ppe) { + err = -ENOMEM; + goto err_free_dev; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -6,9 +6,12 @@ + #include + #include + #include ++#include "mtk_eth_soc.h" + #include "mtk_ppe.h" + #include "mtk_ppe_regs.h" + ++static DEFINE_SPINLOCK(ppe_lock); ++ + static void ppe_w32(struct mtk_ppe *ppe, u32 reg, u32 val) + { + writel(val, ppe->base + reg); +@@ -41,6 +44,11 @@ static u32 ppe_clear(struct mtk_ppe *ppe + return ppe_m32(ppe, reg, val, 0); + } + ++static u32 mtk_eth_timestamp(struct mtk_eth *eth) ++{ ++ return mtk_r32(eth, 0x0010) & MTK_FOE_IB1_BIND_TIMESTAMP; ++} ++ + static int mtk_ppe_wait_busy(struct mtk_ppe *ppe) + { + int ret; +@@ -353,26 +361,59 @@ static inline bool mtk_foe_entry_usable( + FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1) != MTK_FOE_STATE_BIND; + } + +-int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, +- u16 timestamp) ++static bool ++mtk_flow_entry_match(struct mtk_flow_entry *entry, struct mtk_foe_entry *data) ++{ ++ int type, len; ++ ++ if ((data->ib1 ^ entry->data.ib1) & MTK_FOE_IB1_UDP) ++ return false; ++ ++ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->data.ib1); ++ if (type > MTK_PPE_PKT_TYPE_IPV4_DSLITE) ++ len = offsetof(struct mtk_foe_entry, ipv6._rsv); ++ else ++ len = offsetof(struct mtk_foe_entry, ipv4.ib2); ++ ++ return !memcmp(&entry->data.data, &data->data, len - 4); ++} ++ ++static void ++mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + struct mtk_foe_entry *hwe; +- u32 hash; ++ struct mtk_foe_entry foe; + ++ spin_lock_bh(&ppe_lock); ++ if (entry->hash == 0xffff) ++ goto out; ++ ++ hwe = &ppe->foe_table[entry->hash]; ++ memcpy(&foe, hwe, sizeof(foe)); ++ if (!mtk_flow_entry_match(entry, &foe)) { ++ entry->hash = 0xffff; ++ goto out; ++ } ++ ++ entry->data.ib1 = foe.ib1; ++ ++out: ++ spin_unlock_bh(&ppe_lock); ++} ++ ++static void ++__mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, ++ u16 hash) ++{ ++ struct mtk_foe_entry *hwe; ++ u16 timestamp; ++ ++ timestamp = mtk_eth_timestamp(ppe->eth); + timestamp &= MTK_FOE_IB1_BIND_TIMESTAMP; + entry->ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP; + entry->ib1 |= FIELD_PREP(MTK_FOE_IB1_BIND_TIMESTAMP, timestamp); + +- hash = mtk_ppe_hash_entry(entry); + hwe = &ppe->foe_table[hash]; +- if (!mtk_foe_entry_usable(hwe)) { +- hwe++; +- hash++; +- +- if (!mtk_foe_entry_usable(hwe)) +- return -ENOSPC; +- } +- + memcpy(&hwe->data, &entry->data, sizeof(hwe->data)); + wmb(); + hwe->ib1 = entry->ib1; +@@ -380,13 +421,77 @@ int mtk_foe_entry_commit(struct mtk_ppe + dma_wmb(); + + mtk_ppe_cache_clear(ppe); ++} + +- return hash; ++void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ spin_lock_bh(&ppe_lock); ++ hlist_del_init(&entry->list); ++ if (entry->hash != 0xffff) { ++ ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE; ++ ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, ++ MTK_FOE_STATE_BIND); ++ dma_wmb(); ++ } ++ entry->hash = 0xffff; ++ spin_unlock_bh(&ppe_lock); ++} ++ ++int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ u32 hash = mtk_ppe_hash_entry(&entry->data); ++ ++ entry->hash = 0xffff; ++ spin_lock_bh(&ppe_lock); ++ hlist_add_head(&entry->list, &ppe->foe_flow[hash / 2]); ++ spin_unlock_bh(&ppe_lock); ++ ++ return 0; ++} ++ ++void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) ++{ ++ struct hlist_head *head = &ppe->foe_flow[hash / 2]; ++ struct mtk_flow_entry *entry; ++ struct mtk_foe_entry *hwe = &ppe->foe_table[hash]; ++ bool found = false; ++ ++ if (hlist_empty(head)) ++ return; ++ ++ spin_lock_bh(&ppe_lock); ++ hlist_for_each_entry(entry, head, list) { ++ if (found || !mtk_flow_entry_match(entry, hwe)) { ++ if (entry->hash != 0xffff) ++ entry->hash = 0xffff; ++ continue; ++ } ++ ++ entry->hash = hash; ++ __mtk_foe_entry_commit(ppe, &entry->data, hash); ++ found = true; ++ } ++ spin_unlock_bh(&ppe_lock); ++} ++ ++int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ u16 now = mtk_eth_timestamp(ppe->eth) & MTK_FOE_IB1_BIND_TIMESTAMP; ++ u16 timestamp; ++ ++ mtk_flow_entry_update(ppe, entry); ++ timestamp = entry->data.ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; ++ ++ if (timestamp > now) ++ return MTK_FOE_IB1_BIND_TIMESTAMP + 1 - timestamp + now; ++ else ++ return now - timestamp; + } + +-struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, ++struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, + int version) + { ++ struct device *dev = eth->dev; + struct mtk_foe_entry *foe; + struct mtk_ppe *ppe; + +@@ -398,6 +503,7 @@ struct mtk_ppe *mtk_ppe_init(struct devi + * not coherent. + */ + ppe->base = base; ++ ppe->eth = eth; + ppe->dev = dev; + ppe->version = version; + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -235,7 +235,17 @@ enum { + MTK_PPE_CPU_REASON_INVALID = 0x1f, + }; + ++struct mtk_flow_entry { ++ struct rhash_head node; ++ struct hlist_node list; ++ unsigned long cookie; ++ struct mtk_foe_entry data; ++ u16 hash; ++ s8 wed_index; ++}; ++ + struct mtk_ppe { ++ struct mtk_eth *eth; + struct device *dev; + void __iomem *base; + int version; +@@ -243,18 +253,33 @@ struct mtk_ppe { + struct mtk_foe_entry *foe_table; + dma_addr_t foe_phys; + ++ u16 foe_check_time[MTK_PPE_ENTRIES]; ++ struct hlist_head foe_flow[MTK_PPE_ENTRIES / 2]; ++ + void *acct_table; + }; + +-struct mtk_ppe *mtk_ppe_init(struct device *dev, void __iomem *base, int version); ++struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version); + int mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + ++void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); ++ + static inline void +-mtk_foe_entry_clear(struct mtk_ppe *ppe, u16 hash) ++mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) + { +- ppe->foe_table[hash].ib1 = 0; +- dma_wmb(); ++ u16 now, diff; ++ ++ if (!ppe) ++ return; ++ ++ now = (u16)jiffies; ++ diff = now - ppe->foe_check_time[hash]; ++ if (diff < HZ / 10) ++ return; ++ ++ ppe->foe_check_time[hash] = now; ++ __mtk_ppe_check_skb(ppe, skb, hash); + } + + static inline int +@@ -282,8 +307,9 @@ int mtk_foe_entry_set_vlan(struct mtk_fo + int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); + int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, + int bss, int wcid); +-int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, +- u16 timestamp); ++int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); ++int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); + + #endif +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -42,13 +42,6 @@ struct mtk_flow_data { + } pppoe; + }; + +-struct mtk_flow_entry { +- struct rhash_head node; +- unsigned long cookie; +- u16 hash; +- s8 wed_index; +-}; +- + static const struct rhashtable_params mtk_flow_ht_params = { + .head_offset = offsetof(struct mtk_flow_entry, node), + .key_offset = offsetof(struct mtk_flow_entry, cookie), +@@ -56,12 +49,6 @@ static const struct rhashtable_params mt + .automatic_shrinking = true, + }; + +-static u32 +-mtk_eth_timestamp(struct mtk_eth *eth) +-{ +- return mtk_r32(eth, 0x0010) & MTK_FOE_IB1_BIND_TIMESTAMP; +-} +- + static int + mtk_flow_set_ipv4_addr(struct mtk_foe_entry *foe, struct mtk_flow_data *data, + bool egress) +@@ -237,10 +224,8 @@ mtk_flow_offload_replace(struct mtk_eth + int offload_type = 0; + int wed_index = -1; + u16 addr_type = 0; +- u32 timestamp; + u8 l4proto = 0; + int err = 0; +- int hash; + int i; + + if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) +@@ -413,23 +398,21 @@ mtk_flow_offload_replace(struct mtk_eth + return -ENOMEM; + + entry->cookie = f->cookie; +- timestamp = mtk_eth_timestamp(eth); +- hash = mtk_foe_entry_commit(eth->ppe, &foe, timestamp); +- if (hash < 0) { +- err = hash; ++ memcpy(&entry->data, &foe, sizeof(entry->data)); ++ entry->wed_index = wed_index; ++ ++ if (mtk_foe_entry_commit(eth->ppe, entry) < 0) + goto free; +- } + +- entry->hash = hash; +- entry->wed_index = wed_index; + err = rhashtable_insert_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (err < 0) +- goto clear_flow; ++ goto clear; + + return 0; +-clear_flow: +- mtk_foe_entry_clear(eth->ppe, hash); ++ ++clear: ++ mtk_foe_entry_clear(eth->ppe, entry); + free: + kfree(entry); + if (wed_index >= 0) +@@ -447,7 +430,7 @@ mtk_flow_offload_destroy(struct mtk_eth + if (!entry) + return -ENOENT; + +- mtk_foe_entry_clear(eth->ppe, entry->hash); ++ mtk_foe_entry_clear(eth->ppe, entry); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (entry->wed_index >= 0) +@@ -461,7 +444,6 @@ static int + mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) + { + struct mtk_flow_entry *entry; +- int timestamp; + u32 idle; + + entry = rhashtable_lookup(ð->flow_table, &f->cookie, +@@ -469,11 +451,7 @@ mtk_flow_offload_stats(struct mtk_eth *e + if (!entry) + return -ENOENT; + +- timestamp = mtk_foe_entry_timestamp(eth->ppe, entry->hash); +- if (timestamp < 0) +- return -ETIMEDOUT; +- +- idle = mtk_eth_timestamp(eth) - timestamp; ++ idle = mtk_foe_entry_idle_time(eth->ppe, entry); + f->stats.lastused = jiffies - idle * HZ; + + return 0; diff --git a/target/linux/generic/pending-5.15/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch b/target/linux/generic/pending-5.15/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch new file mode 100644 index 0000000000..2ff0b341f9 --- /dev/null +++ b/target/linux/generic/pending-5.15/701-09-net-ethernet-mtk_eth_soc-remove-bridge-flow-offload-.patch @@ -0,0 +1,44 @@ +From: Felix Fietkau +Date: Mon, 21 Feb 2022 15:55:19 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: remove bridge flow offload + type entry support + +According to MediaTek, this feature is not supported in current hardware + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -84,13 +84,6 @@ static u32 mtk_ppe_hash_entry(struct mtk + u32 hash; + + switch (FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, e->ib1)) { +- case MTK_PPE_PKT_TYPE_BRIDGE: +- hv1 = e->bridge.src_mac_lo; +- hv1 ^= ((e->bridge.src_mac_hi & 0xffff) << 16); +- hv2 = e->bridge.src_mac_hi >> 16; +- hv2 ^= e->bridge.dest_mac_lo; +- hv3 = e->bridge.dest_mac_hi; +- break; + case MTK_PPE_PKT_TYPE_IPV4_ROUTE: + case MTK_PPE_PKT_TYPE_IPV4_HNAPT: + hv1 = e->ipv4.orig.ports; +@@ -572,7 +565,6 @@ int mtk_ppe_start(struct mtk_ppe *ppe) + MTK_PPE_FLOW_CFG_IP4_NAT | + MTK_PPE_FLOW_CFG_IP4_NAPT | + MTK_PPE_FLOW_CFG_IP4_DSLITE | +- MTK_PPE_FLOW_CFG_L2_BRIDGE | + MTK_PPE_FLOW_CFG_IP4_NAT_FRAG; + ppe_w32(ppe, MTK_PPE_FLOW_CFG, val); + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +@@ -32,7 +32,6 @@ static const char *mtk_foe_pkt_type_str( + static const char * const type_str[] = { + [MTK_PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T", + [MTK_PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T", +- [MTK_PPE_PKT_TYPE_BRIDGE] = "L2", + [MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE", + [MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T", + [MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T", diff --git a/target/linux/generic/pending-5.15/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch b/target/linux/generic/pending-5.15/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch new file mode 100644 index 0000000000..67c02d6dbc --- /dev/null +++ b/target/linux/generic/pending-5.15/701-10-net-ethernet-mtk_eth_soc-support-creating-mac-addres.patch @@ -0,0 +1,553 @@ +From: Felix Fietkau +Date: Wed, 23 Feb 2022 10:56:34 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: support creating mac + address based offload entries + +This will be used to implement a limited form of bridge offloading. +Since the hardware does not support flow table entries with just source +and destination MAC address, the driver has to emulate it. + +The hardware automatically creates entries entries for incoming flows, even +when they are bridged instead of routed, and reports when packets for these +flows have reached the minimum PPS rate for offloading. + +After this happens, we look up the L2 flow offload entry based on the MAC +header and fill in the output routing information in the flow table. +The dynamically created per-flow entries are automatically removed when +either the hardware flowtable entry expires, is replaced, or if the offload +rule they belong to is removed + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -6,12 +6,22 @@ + #include + #include + #include ++#include ++#include ++#include + #include "mtk_eth_soc.h" + #include "mtk_ppe.h" + #include "mtk_ppe_regs.h" + + static DEFINE_SPINLOCK(ppe_lock); + ++static const struct rhashtable_params mtk_flow_l2_ht_params = { ++ .head_offset = offsetof(struct mtk_flow_entry, l2_node), ++ .key_offset = offsetof(struct mtk_flow_entry, data.bridge), ++ .key_len = offsetof(struct mtk_foe_bridge, key_end), ++ .automatic_shrinking = true, ++}; ++ + static void ppe_w32(struct mtk_ppe *ppe, u32 reg, u32 val) + { + writel(val, ppe->base + reg); +@@ -123,6 +133,9 @@ mtk_foe_entry_l2(struct mtk_foe_entry *e + { + int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); + ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return &entry->bridge.l2; ++ + if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) + return &entry->ipv6.l2; + +@@ -134,6 +147,9 @@ mtk_foe_entry_ib2(struct mtk_foe_entry * + { + int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); + ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return &entry->bridge.ib2; ++ + if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) + return &entry->ipv6.ib2; + +@@ -168,7 +184,12 @@ int mtk_foe_entry_prepare(struct mtk_foe + if (type == MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T) + entry->ipv6.ports = ports_pad; + +- if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) { ++ ether_addr_copy(entry->bridge.src_mac, src_mac); ++ ether_addr_copy(entry->bridge.dest_mac, dest_mac); ++ entry->bridge.ib2 = val; ++ l2 = &entry->bridge.l2; ++ } else if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) { + entry->ipv6.ib2 = val; + l2 = &entry->ipv6.l2; + } else { +@@ -372,12 +393,96 @@ mtk_flow_entry_match(struct mtk_flow_ent + } + + static void ++__mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ struct hlist_head *head; ++ struct hlist_node *tmp; ++ ++ if (entry->type == MTK_FLOW_TYPE_L2) { ++ rhashtable_remove_fast(&ppe->l2_flows, &entry->l2_node, ++ mtk_flow_l2_ht_params); ++ ++ head = &entry->l2_flows; ++ hlist_for_each_entry_safe(entry, tmp, head, l2_data.list) ++ __mtk_foe_entry_clear(ppe, entry); ++ return; ++ } ++ ++ hlist_del_init(&entry->list); ++ if (entry->hash != 0xffff) { ++ ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE; ++ ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, ++ MTK_FOE_STATE_BIND); ++ dma_wmb(); ++ } ++ entry->hash = 0xffff; ++ ++ if (entry->type != MTK_FLOW_TYPE_L2_SUBFLOW) ++ return; ++ ++ hlist_del_init(&entry->l2_data.list); ++ kfree(entry); ++} ++ ++static int __mtk_foe_entry_idle_time(struct mtk_ppe *ppe, u32 ib1) ++{ ++ u16 timestamp; ++ u16 now; ++ ++ now = mtk_eth_timestamp(ppe->eth) & MTK_FOE_IB1_BIND_TIMESTAMP; ++ timestamp = ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; ++ ++ if (timestamp > now) ++ return MTK_FOE_IB1_BIND_TIMESTAMP + 1 - timestamp + now; ++ else ++ return now - timestamp; ++} ++ ++static void ++mtk_flow_entry_update_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ struct mtk_flow_entry *cur; ++ struct mtk_foe_entry *hwe; ++ struct hlist_node *tmp; ++ int idle; ++ ++ idle = __mtk_foe_entry_idle_time(ppe, entry->data.ib1); ++ hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_data.list) { ++ int cur_idle; ++ u32 ib1; ++ ++ hwe = &ppe->foe_table[cur->hash]; ++ ib1 = READ_ONCE(hwe->ib1); ++ ++ if (FIELD_GET(MTK_FOE_IB1_STATE, ib1) != MTK_FOE_STATE_BIND) { ++ cur->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, cur); ++ continue; ++ } ++ ++ cur_idle = __mtk_foe_entry_idle_time(ppe, ib1); ++ if (cur_idle >= idle) ++ continue; ++ ++ idle = cur_idle; ++ entry->data.ib1 &= ~MTK_FOE_IB1_BIND_TIMESTAMP; ++ entry->data.ib1 |= hwe->ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; ++ } ++} ++ ++static void + mtk_flow_entry_update(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + struct mtk_foe_entry *hwe; + struct mtk_foe_entry foe; + + spin_lock_bh(&ppe_lock); ++ ++ if (entry->type == MTK_FLOW_TYPE_L2) { ++ mtk_flow_entry_update_l2(ppe, entry); ++ goto out; ++ } ++ + if (entry->hash == 0xffff) + goto out; + +@@ -419,21 +524,28 @@ __mtk_foe_entry_commit(struct mtk_ppe *p + void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { + spin_lock_bh(&ppe_lock); +- hlist_del_init(&entry->list); +- if (entry->hash != 0xffff) { +- ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE; +- ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, +- MTK_FOE_STATE_BIND); +- dma_wmb(); +- } +- entry->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, entry); + spin_unlock_bh(&ppe_lock); + } + ++static int ++mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) ++{ ++ entry->type = MTK_FLOW_TYPE_L2; ++ ++ return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node, ++ mtk_flow_l2_ht_params); ++} ++ + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { +- u32 hash = mtk_ppe_hash_entry(&entry->data); ++ int type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->data.ib1); ++ u32 hash; ++ ++ if (type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return mtk_foe_entry_commit_l2(ppe, entry); + ++ hash = mtk_ppe_hash_entry(&entry->data); + entry->hash = 0xffff; + spin_lock_bh(&ppe_lock); + hlist_add_head(&entry->list, &ppe->foe_flow[hash / 2]); +@@ -442,18 +554,72 @@ int mtk_foe_entry_commit(struct mtk_ppe + return 0; + } + ++static void ++mtk_foe_entry_commit_subflow(struct mtk_ppe *ppe, struct mtk_flow_entry *entry, ++ u16 hash) ++{ ++ struct mtk_flow_entry *flow_info; ++ struct mtk_foe_entry foe, *hwe; ++ struct mtk_foe_mac_info *l2; ++ u32 ib1_mask = MTK_FOE_IB1_PACKET_TYPE | MTK_FOE_IB1_UDP; ++ int type; ++ ++ flow_info = kzalloc(offsetof(struct mtk_flow_entry, l2_data.end), ++ GFP_ATOMIC); ++ if (!flow_info) ++ return; ++ ++ flow_info->l2_data.base_flow = entry; ++ flow_info->type = MTK_FLOW_TYPE_L2_SUBFLOW; ++ flow_info->hash = hash; ++ hlist_add_head(&flow_info->list, &ppe->foe_flow[hash / 2]); ++ hlist_add_head(&flow_info->l2_data.list, &entry->l2_flows); ++ ++ hwe = &ppe->foe_table[hash]; ++ memcpy(&foe, hwe, sizeof(foe)); ++ foe.ib1 &= ib1_mask; ++ foe.ib1 |= entry->data.ib1 & ~ib1_mask; ++ ++ l2 = mtk_foe_entry_l2(&foe); ++ memcpy(l2, &entry->data.bridge.l2, sizeof(*l2)); ++ ++ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, foe.ib1); ++ if (type == MTK_PPE_PKT_TYPE_IPV4_HNAPT) ++ memcpy(&foe.ipv4.new, &foe.ipv4.orig, sizeof(foe.ipv4.new)); ++ else if (type >= MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T && l2->etype == ETH_P_IP) ++ l2->etype = ETH_P_IPV6; ++ ++ *mtk_foe_entry_ib2(&foe) = entry->data.bridge.ib2; ++ ++ __mtk_foe_entry_commit(ppe, &foe, hash); ++} ++ + void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) + { + struct hlist_head *head = &ppe->foe_flow[hash / 2]; +- struct mtk_flow_entry *entry; + struct mtk_foe_entry *hwe = &ppe->foe_table[hash]; ++ struct mtk_flow_entry *entry; ++ struct mtk_foe_bridge key = {}; ++ struct ethhdr *eh; + bool found = false; +- +- if (hlist_empty(head)) +- return; ++ u8 *tag; + + spin_lock_bh(&ppe_lock); ++ ++ if (FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == MTK_FOE_STATE_BIND) ++ goto out; ++ + hlist_for_each_entry(entry, head, list) { ++ if (entry->type == MTK_FLOW_TYPE_L2_SUBFLOW) { ++ if (unlikely(FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == ++ MTK_FOE_STATE_BIND)) ++ continue; ++ ++ entry->hash = 0xffff; ++ __mtk_foe_entry_clear(ppe, entry); ++ continue; ++ } ++ + if (found || !mtk_flow_entry_match(entry, hwe)) { + if (entry->hash != 0xffff) + entry->hash = 0xffff; +@@ -464,21 +630,50 @@ void __mtk_ppe_check_skb(struct mtk_ppe + __mtk_foe_entry_commit(ppe, &entry->data, hash); + found = true; + } ++ ++ if (found) ++ goto out; ++ ++ eh = eth_hdr(skb); ++ ether_addr_copy(key.dest_mac, eh->h_dest); ++ ether_addr_copy(key.src_mac, eh->h_source); ++ tag = skb->data - 2; ++ key.vlan = 0; ++ switch (skb->protocol) { ++#if IS_ENABLED(CONFIG_NET_DSA) ++ case htons(ETH_P_XDSA): ++ if (!netdev_uses_dsa(skb->dev) || ++ skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) ++ goto out; ++ ++ tag += 4; ++ if (get_unaligned_be16(tag) != ETH_P_8021Q) ++ break; ++ ++ fallthrough; ++#endif ++ case htons(ETH_P_8021Q): ++ key.vlan = get_unaligned_be16(tag + 2) & VLAN_VID_MASK; ++ break; ++ default: ++ break; ++ } ++ ++ entry = rhashtable_lookup_fast(&ppe->l2_flows, &key, mtk_flow_l2_ht_params); ++ if (!entry) ++ goto out; ++ ++ mtk_foe_entry_commit_subflow(ppe, entry, hash); ++ ++out: + spin_unlock_bh(&ppe_lock); + } + + int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) + { +- u16 now = mtk_eth_timestamp(ppe->eth) & MTK_FOE_IB1_BIND_TIMESTAMP; +- u16 timestamp; +- + mtk_flow_entry_update(ppe, entry); +- timestamp = entry->data.ib1 & MTK_FOE_IB1_BIND_TIMESTAMP; + +- if (timestamp > now) +- return MTK_FOE_IB1_BIND_TIMESTAMP + 1 - timestamp + now; +- else +- return now - timestamp; ++ return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); + } + + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, +@@ -492,6 +687,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + if (!ppe) + return NULL; + ++ rhashtable_init(&ppe->l2_flows, &mtk_flow_l2_ht_params); ++ + /* need to allocate a separate device, since it PPE DMA access is + * not coherent. + */ +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -6,6 +6,7 @@ + + #include + #include ++#include + + #define MTK_ETH_PPE_BASE 0xc00 + +@@ -84,19 +85,16 @@ struct mtk_foe_mac_info { + u16 src_mac_lo; + }; + ++/* software-only entry type */ + struct mtk_foe_bridge { +- u32 dest_mac_hi; +- +- u16 src_mac_lo; +- u16 dest_mac_lo; ++ u8 dest_mac[ETH_ALEN]; ++ u8 src_mac[ETH_ALEN]; ++ u16 vlan; + +- u32 src_mac_hi; ++ struct {} key_end; + + u32 ib2; + +- u32 _rsv[5]; +- +- u32 udf_tsid; + struct mtk_foe_mac_info l2; + }; + +@@ -235,13 +233,33 @@ enum { + MTK_PPE_CPU_REASON_INVALID = 0x1f, + }; + ++enum { ++ MTK_FLOW_TYPE_L4, ++ MTK_FLOW_TYPE_L2, ++ MTK_FLOW_TYPE_L2_SUBFLOW, ++}; ++ + struct mtk_flow_entry { ++ union { ++ struct hlist_node list; ++ struct { ++ struct rhash_head l2_node; ++ struct hlist_head l2_flows; ++ }; ++ }; ++ u8 type; ++ s8 wed_index; ++ u16 hash; ++ union { ++ struct mtk_foe_entry data; ++ struct { ++ struct mtk_flow_entry *base_flow; ++ struct hlist_node list; ++ struct {} end; ++ } l2_data; ++ }; + struct rhash_head node; +- struct hlist_node list; + unsigned long cookie; +- struct mtk_foe_entry data; +- u16 hash; +- s8 wed_index; + }; + + struct mtk_ppe { +@@ -256,6 +274,8 @@ struct mtk_ppe { + u16 foe_check_time[MTK_PPE_ENTRIES]; + struct hlist_head foe_flow[MTK_PPE_ENTRIES / 2]; + ++ struct rhashtable l2_flows; ++ + void *acct_table; + }; + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -31,6 +31,8 @@ struct mtk_flow_data { + __be16 src_port; + __be16 dst_port; + ++ u16 vlan_in; ++ + struct { + u16 id; + __be16 proto; +@@ -260,9 +262,45 @@ mtk_flow_offload_replace(struct mtk_eth + return -EOPNOTSUPP; + } + ++ switch (addr_type) { ++ case 0: ++ offload_type = MTK_PPE_PKT_TYPE_BRIDGE; ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { ++ struct flow_match_eth_addrs match; ++ ++ flow_rule_match_eth_addrs(rule, &match); ++ memcpy(data.eth.h_dest, match.key->dst, ETH_ALEN); ++ memcpy(data.eth.h_source, match.key->src, ETH_ALEN); ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { ++ struct flow_match_vlan match; ++ ++ flow_rule_match_vlan(rule, &match); ++ ++ if (match.key->vlan_tpid != cpu_to_be16(ETH_P_8021Q)) ++ return -EOPNOTSUPP; ++ ++ data.vlan_in = match.key->vlan_id; ++ } ++ break; ++ case FLOW_DISSECTOR_KEY_IPV4_ADDRS: ++ offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; ++ break; ++ case FLOW_DISSECTOR_KEY_IPV6_ADDRS: ++ offload_type = MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ + flow_action_for_each(i, act, &rule->action) { + switch (act->id) { + case FLOW_ACTION_MANGLE: ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; + if (act->mangle.htype == FLOW_ACT_MANGLE_HDR_TYPE_ETH) + mtk_flow_offload_mangle_eth(act, &data.eth); + break; +@@ -294,17 +332,6 @@ mtk_flow_offload_replace(struct mtk_eth + } + } + +- switch (addr_type) { +- case FLOW_DISSECTOR_KEY_IPV4_ADDRS: +- offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT; +- break; +- case FLOW_DISSECTOR_KEY_IPV6_ADDRS: +- offload_type = MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T; +- break; +- default: +- return -EOPNOTSUPP; +- } +- + if (!is_valid_ether_addr(data.eth.h_source) || + !is_valid_ether_addr(data.eth.h_dest)) + return -EINVAL; +@@ -318,10 +345,13 @@ mtk_flow_offload_replace(struct mtk_eth + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports ports; + ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ + flow_rule_match_ports(rule, &ports); + data.src_port = ports.key->src; + data.dst_port = ports.key->dst; +- } else { ++ } else if (offload_type != MTK_PPE_PKT_TYPE_BRIDGE) { + return -EOPNOTSUPP; + } + +@@ -351,6 +381,9 @@ mtk_flow_offload_replace(struct mtk_eth + if (act->id != FLOW_ACTION_MANGLE) + continue; + ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ + switch (act->mangle.htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_TCP: + case FLOW_ACT_MANGLE_HDR_TYPE_UDP: +@@ -376,6 +409,9 @@ mtk_flow_offload_replace(struct mtk_eth + return err; + } + ++ if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) ++ foe.bridge.vlan = data.vlan_in; ++ + if (data.vlan.num == 1) { + if (data.vlan.proto != htons(ETH_P_8021Q)) + return -EOPNOTSUPP; diff --git a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch index d5ce94d74a..4365359e00 100644 --- a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch +++ b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2178,8 +2178,8 @@ static irqreturn_t mtk_handle_irq_rx(int +@@ -2186,8 +2186,8 @@ static irqreturn_t mtk_handle_irq_rx(int eth->rx_events++; if (likely(napi_schedule_prep(ð->rx_napi))) { @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau } return IRQ_HANDLED; -@@ -2191,8 +2191,8 @@ static irqreturn_t mtk_handle_irq_tx(int +@@ -2199,8 +2199,8 @@ static irqreturn_t mtk_handle_irq_tx(int eth->tx_events++; if (likely(napi_schedule_prep(ð->tx_napi))) { @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau } return IRQ_HANDLED; -@@ -3242,6 +3242,8 @@ static int mtk_probe(struct platform_dev +@@ -3313,6 +3313,8 @@ static int mtk_probe(struct platform_dev * for NAPI to work */ init_dummy_netdev(ð->dummy_dev); diff --git a/target/linux/mediatek/patches-5.10/510-net-mediatek-add-flow-offload-for-mt7623.patch b/target/linux/mediatek/patches-5.10/510-net-mediatek-add-flow-offload-for-mt7623.patch index dd2b70aa10..43464b27d5 100644 --- a/target/linux/mediatek/patches-5.10/510-net-mediatek-add-flow-offload-for-mt7623.patch +++ b/target/linux/mediatek/patches-5.10/510-net-mediatek-add-flow-offload-for-mt7623.patch @@ -14,7 +14,7 @@ Signed-off-by: Frank Wunderlich --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3304,6 +3304,7 @@ static const struct mtk_soc_data mt7623_ +@@ -3373,6 +3373,7 @@ static const struct mtk_soc_data mt7623_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, diff --git a/target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch b/target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch deleted file mode 100644 index a0c892d706..0000000000 --- a/target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch +++ /dev/null @@ -1,85 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Sep 2020 18:36:06 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for coherent DMA - -It improves performance by eliminating the need for a cache flush on rx and tx - -Signed-off-by: Felix Fietkau ---- - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -364,7 +364,7 @@ - }; - - cci_control2: slave-if@5000 { -- compatible = "arm,cci-400-ctrl-if"; -+ compatible = "arm,cci-400-ctrl-if", "syscon"; - interface-type = "ace"; - reg = <0x5000 0x1000>; - }; -@@ -977,6 +977,8 @@ - power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys>; -+ mediatek,cci-control = <&cci_control2>; -+ dma-coherent; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2494,6 +2495,13 @@ static int mtk_hw_init(struct mtk_eth *e - if (ret) - goto err_disable_pm; - -+ if (of_dma_is_coherent(eth->dev->of_node)) { -+ u32 mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -+ ETHSYS_DMA_AG_MAP_PPE; -+ -+ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, mask, mask); -+ } -+ - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { - ret = device_reset(eth->dev); - if (ret) { -@@ -3104,6 +3112,16 @@ static int mtk_probe(struct platform_dev - } - } - -+ if (of_dma_is_coherent(pdev->dev.of_node)) { -+ struct regmap *cci; -+ -+ cci = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, -+ "mediatek,cci-control"); -+ /* enable CPU/bus coherency */ -+ if (!IS_ERR(cci)) -+ regmap_write(cci, 0, 3); -+ } -+ - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { - eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), - GFP_KERNEL); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -456,6 +456,12 @@ - #define RSTCTRL_FE BIT(6) - #define RSTCTRL_PPE BIT(31) - -+/* ethernet dma channel agent map */ -+#define ETHSYS_DMA_AG_MAP 0x408 -+#define ETHSYS_DMA_AG_MAP_PDMA BIT(0) -+#define ETHSYS_DMA_AG_MAP_QDMA BIT(1) -+#define ETHSYS_DMA_AG_MAP_PPE BIT(2) -+ - /* SGMII subsystem config registers */ - /* Register to auto-negotiation restart */ - #define SGMSYS_PCS_CONTROL_1 0x0 diff --git a/target/linux/mediatek/patches-5.10/701-v5.17-net-ethernet-mtk_eth_soc-fix-return-values-and-refac.patch b/target/linux/mediatek/patches-5.10/701-v5.17-net-ethernet-mtk_eth_soc-fix-return-values-and-refac.patch index 56b293257e..be9dcfc3ed 100644 --- a/target/linux/mediatek/patches-5.10/701-v5.17-net-ethernet-mtk_eth_soc-fix-return-values-and-refac.patch +++ b/target/linux/mediatek/patches-5.10/701-v5.17-net-ethernet-mtk_eth_soc-fix-return-values-and-refac.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -92,46 +92,53 @@ static int mtk_mdio_busy_wait(struct mtk +@@ -94,46 +94,53 @@ static int mtk_mdio_busy_wait(struct mtk } dev_err(eth->dev, "mdio: MDIO timeout\n"); @@ -103,7 +103,7 @@ Signed-off-by: David S. Miller static int mtk_mdio_write(struct mii_bus *bus, int phy_addr, --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -341,11 +341,17 @@ +@@ -344,11 +344,17 @@ /* PHY Indirect Access Control registers */ #define MTK_PHY_IAC 0x10004 #define PHY_IAC_ACCESS BIT(31) diff --git a/target/linux/mediatek/patches-5.10/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.10/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch index 65e6bd2cbf..289398ce3a 100644 --- a/target/linux/mediatek/patches-5.10/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch +++ b/target/linux/mediatek/patches-5.10/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -104,13 +104,35 @@ static int _mtk_mdio_write(struct mtk_et +@@ -106,13 +106,35 @@ static int _mtk_mdio_write(struct mtk_et if (ret < 0) return ret; @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller ret = mtk_mdio_busy_wait(eth); if (ret < 0) -@@ -127,12 +149,33 @@ static int _mtk_mdio_read(struct mtk_eth +@@ -129,12 +151,33 @@ static int _mtk_mdio_read(struct mtk_eth if (ret < 0) return ret; @@ -103,7 +103,7 @@ Signed-off-by: David S. Miller ret = mtk_mdio_busy_wait(eth); if (ret < 0) -@@ -591,6 +634,7 @@ static int mtk_mdio_init(struct mtk_eth +@@ -593,6 +636,7 @@ static int mtk_mdio_init(struct mtk_eth eth->mii_bus->name = "mdio"; eth->mii_bus->read = mtk_mdio_read; eth->mii_bus->write = mtk_mdio_write; @@ -113,7 +113,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -346,9 +346,12 @@ +@@ -349,9 +349,12 @@ #define PHY_IAC_ADDR_MASK GENMASK(24, 20) #define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x)) #define PHY_IAC_CMD_MASK GENMASK(19, 18) diff --git a/target/linux/mediatek/patches-5.10/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch b/target/linux/mediatek/patches-5.10/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch index 3afbc01017..e9d4188a45 100644 --- a/target/linux/mediatek/patches-5.10/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch +++ b/target/linux/mediatek/patches-5.10/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch @@ -1,6 +1,6 @@ --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -575,6 +575,7 @@ static void mtk_validate(struct phylink_ +@@ -577,6 +577,7 @@ static void mtk_validate(struct phylink_ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { phylink_set(mask, 1000baseT_Full); phylink_set(mask, 1000baseX_Full); diff --git a/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch index ec5f13b4ea..32fc0a9ad5 100644 --- a/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch +++ b/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch @@ -44,18 +44,6 @@ Signed-off-by: Felix Fietkau slot1: pcie@1,0 { reg = <0x0800 0 0 0 0>; -@@ -933,6 +939,11 @@ - }; - }; - -+ hifsys: syscon@1af00000 { -+ compatible = "mediatek,mt7622-hifsys", "syscon"; -+ reg = <0 0x1af00000 0 0x70>; -+ }; -+ - ethsys: syscon@1b000000 { - compatible = "mediatek,mt7622-ethsys", - "syscon"; --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -20,6 +20,7 @@ diff --git a/target/linux/ramips/patches-5.10/700-net-ethernet-mediatek-support-net-labels.patch b/target/linux/ramips/patches-5.10/700-net-ethernet-mediatek-support-net-labels.patch index 9a4971d117..65b61e7720 100644 --- a/target/linux/ramips/patches-5.10/700-net-ethernet-mediatek-support-net-labels.patch +++ b/target/linux/ramips/patches-5.10/700-net-ethernet-mediatek-support-net-labels.patch @@ -14,7 +14,7 @@ Signed-off-by: René van Dorst --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2941,6 +2941,7 @@ static const struct net_device_ops mtk_n +@@ -2949,6 +2949,7 @@ static const struct net_device_ops mtk_n static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { @@ -22,7 +22,7 @@ Signed-off-by: René van Dorst const __be32 *_id = of_get_property(np, "reg", NULL); phy_interface_t phy_mode; struct phylink *phylink; -@@ -3036,6 +3037,9 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -3044,6 +3045,9 @@ static int mtk_add_mac(struct mtk_eth *e else eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; From a92db8abe056bd517ca2cc452786c0325ba6dba7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 27 Mar 2022 11:31:27 +0200 Subject: [PATCH 24/26] kernel: add missing config symbols for 5.15 Signed-off-by: Felix Fietkau --- target/linux/generic/config-5.15 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 3657304904..8dd2afc2fc 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -762,6 +762,7 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_REF_VERIFY is not set # CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BT_AOSPEXT is not set # CONFIG_BT_ATH3K is not set # CONFIG_BT_BNEP is not set CONFIG_BT_BNEP_MC_FILTER=y @@ -2291,6 +2292,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_PICOLCD is not set # CONFIG_HID_PID is not set # CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PLAYSTATION is not set # CONFIG_HID_PRIMAX is not set # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_REDRAGON is not set @@ -2299,6 +2301,7 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HID_ROCCAT is not set # CONFIG_HID_SAITEK is not set # CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SEMITEK is not set # CONFIG_HID_SENSOR_HUB is not set # CONFIG_HID_SMARTJOYPLUS is not set # CONFIG_HID_SONY is not set @@ -5298,6 +5301,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_BH1780 is not set # CONFIG_SENSORS_CORETEMP is not set # CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_CORSAIR_PSU is not set # CONFIG_SENSORS_DELL_SMM is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_DRIVETEMP is not set From ade563ba84496406243b3699a27b3de7e08399e7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 27 Mar 2022 12:54:03 +0200 Subject: [PATCH 25/26] mediatek: add patches for 5.15 and kernel config for mt7622 Signed-off-by: Felix Fietkau --- .../drivers/leds/leds-ubnt-ledbar.c | 0 .../drivers/mtd/mtk-snand/Kconfig | 0 .../drivers/mtd/mtk-snand/Makefile | 0 .../drivers/mtd/mtk-snand/mtk-snand-def.h | 0 .../drivers/mtd/mtk-snand/mtk-snand-ecc.c | 0 .../drivers/mtd/mtk-snand/mtk-snand-ids.c | 0 .../drivers/mtd/mtk-snand/mtk-snand-mtd.c | 0 .../drivers/mtd/mtk-snand/mtk-snand-os.c | 0 .../drivers/mtd/mtk-snand/mtk-snand-os.h | 0 .../drivers/mtd/mtk-snand/mtk-snand.c | 0 .../drivers/mtd/mtk-snand/mtk-snand.h | 0 .../drivers/net/phy/mtk/mt753x/Kconfig | 0 .../drivers/net/phy/mtk/mt753x/Makefile | 0 .../drivers/net/phy/mtk/mt753x/mt7530.c | 0 .../drivers/net/phy/mtk/mt753x/mt7530.h | 0 .../drivers/net/phy/mtk/mt753x/mt7531.c | 0 .../drivers/net/phy/mtk/mt753x/mt7531.h | 0 .../drivers/net/phy/mtk/mt753x/mt753x.h | 0 .../net/phy/mtk/mt753x/mt753x_common.c | 0 .../drivers/net/phy/mtk/mt753x/mt753x_mdio.c | 0 .../drivers/net/phy/mtk/mt753x/mt753x_nl.c | 0 .../drivers/net/phy/mtk/mt753x/mt753x_nl.h | 0 .../drivers/net/phy/mtk/mt753x/mt753x_regs.h | 0 .../net/phy/mtk/mt753x/mt753x_swconfig.c | 0 .../net/phy/mtk/mt753x/mt753x_swconfig.h | 0 .../drivers/net/phy/mtk/mt753x/mt753x_vlan.c | 0 .../drivers/net/phy/mtk/mt753x/mt753x_vlan.h | 0 .../drivers/net/phy/rtk/Makefile | 0 .../drivers/net/phy/rtk/modules.builtin | 0 .../drivers/net/phy/rtk/rtl8367c/acl.c | 0 .../drivers/net/phy/rtk/rtl8367c/cpu.c | 0 .../drivers/net/phy/rtk/rtl8367c/dot1x.c | 0 .../drivers/net/phy/rtk/rtl8367c/eee.c | 0 .../drivers/net/phy/rtk/rtl8367c/i2c.c | 0 .../drivers/net/phy/rtk/rtl8367c/igmp.c | 0 .../net/phy/rtk/rtl8367c/include/acl.h | 0 .../net/phy/rtk/rtl8367c/include/cpu.h | 0 .../net/phy/rtk/rtl8367c/include/dot1x.h | 0 .../net/phy/rtk/rtl8367c/include/eee.h | 0 .../net/phy/rtk/rtl8367c/include/i2c.h | 0 .../net/phy/rtk/rtl8367c/include/igmp.h | 0 .../net/phy/rtk/rtl8367c/include/interrupt.h | 0 .../drivers/net/phy/rtk/rtl8367c/include/l2.h | 0 .../net/phy/rtk/rtl8367c/include/leaky.h | 0 .../net/phy/rtk/rtl8367c/include/led.h | 0 .../net/phy/rtk/rtl8367c/include/mirror.h | 0 .../net/phy/rtk/rtl8367c/include/oam.h | 0 .../net/phy/rtk/rtl8367c/include/port.h | 0 .../net/phy/rtk/rtl8367c/include/ptp.h | 0 .../net/phy/rtk/rtl8367c/include/qos.h | 0 .../net/phy/rtk/rtl8367c/include/rate.h | 0 .../net/phy/rtk/rtl8367c/include/rldp.h | 0 .../net/phy/rtk/rtl8367c/include/rtk_error.h | 0 .../net/phy/rtk/rtl8367c/include/rtk_hal.h | 0 .../net/phy/rtk/rtl8367c/include/rtk_switch.h | 0 .../net/phy/rtk/rtl8367c/include/rtk_types.h | 0 .../rtk/rtl8367c/include/rtl8367c_asicdrv.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_acl.h | 0 .../include/rtl8367c_asicdrv_cputag.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_dot1x.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_eav.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_eee.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_fc.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_green.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_hsb.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_i2c.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_igmp.h | 0 .../include/rtl8367c_asicdrv_inbwctrl.h | 0 .../include/rtl8367c_asicdrv_interrupt.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_led.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_lut.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_meter.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_mib.h | 0 .../include/rtl8367c_asicdrv_mirror.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_misc.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_oam.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_phy.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_port.h | 0 .../include/rtl8367c_asicdrv_portIsolation.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_qos.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_rldp.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_rma.h | 0 .../include/rtl8367c_asicdrv_scheduling.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_storm.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_svlan.h | 0 .../include/rtl8367c_asicdrv_trunking.h | 0 .../rtl8367c_asicdrv_unknownMulticast.h | 0 .../rtl8367c/include/rtl8367c_asicdrv_vlan.h | 0 .../phy/rtk/rtl8367c/include/rtl8367c_base.h | 0 .../phy/rtk/rtl8367c/include/rtl8367c_reg.h | 0 .../net/phy/rtk/rtl8367c/include/smi.h | 0 .../net/phy/rtk/rtl8367c/include/stat.h | 0 .../net/phy/rtk/rtl8367c/include/storm.h | 0 .../net/phy/rtk/rtl8367c/include/svlan.h | 0 .../net/phy/rtk/rtl8367c/include/trap.h | 0 .../net/phy/rtk/rtl8367c/include/trunk.h | 0 .../net/phy/rtk/rtl8367c/include/vlan.h | 0 .../drivers/net/phy/rtk/rtl8367c/interrupt.c | 0 .../drivers/net/phy/rtk/rtl8367c/l2.c | 0 .../drivers/net/phy/rtk/rtl8367c/leaky.c | 0 .../drivers/net/phy/rtk/rtl8367c/led.c | 0 .../drivers/net/phy/rtk/rtl8367c/mirror.c | 0 .../drivers/net/phy/rtk/rtl8367c/oam.c | 0 .../drivers/net/phy/rtk/rtl8367c/port.c | 0 .../drivers/net/phy/rtk/rtl8367c/ptp.c | 0 .../drivers/net/phy/rtk/rtl8367c/qos.c | 0 .../drivers/net/phy/rtk/rtl8367c/rate.c | 0 .../drivers/net/phy/rtk/rtl8367c/rldp.c | 0 .../drivers/net/phy/rtk/rtl8367c/rtk_hal.c | 0 .../drivers/net/phy/rtk/rtl8367c/rtk_switch.c | 0 .../net/phy/rtk/rtl8367c/rtl8367c_asicdrv.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c | 0 .../rtk/rtl8367c/rtl8367c_asicdrv_cputag.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_dot1x.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_eee.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_i2c.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c | 0 .../rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c | 0 .../rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_meter.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c | 0 .../rtk/rtl8367c/rtl8367c_asicdrv_mirror.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_misc.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_oam.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c | 0 .../rtl8367c/rtl8367c_asicdrv_portIsolation.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_rldp.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_rma.c | 0 .../rtl8367c/rtl8367c_asicdrv_scheduling.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_storm.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c | 0 .../rtk/rtl8367c/rtl8367c_asicdrv_trunking.c | 0 .../rtl8367c_asicdrv_unknownMulticast.c | 0 .../phy/rtk/rtl8367c/rtl8367c_asicdrv_vlan.c | 0 .../drivers/net/phy/rtk/rtl8367c/smi.c | 0 .../drivers/net/phy/rtk/rtl8367c/stat.c | 0 .../drivers/net/phy/rtk/rtl8367c/storm.c | 0 .../drivers/net/phy/rtk/rtl8367c/svlan.c | 0 .../drivers/net/phy/rtk/rtl8367c/trap.c | 0 .../drivers/net/phy/rtk/rtl8367c/trunk.c | 0 .../drivers/net/phy/rtk/rtl8367c/vlan.c | 0 .../drivers/net/phy/rtk/rtl8367s.c | 0 .../drivers/net/phy/rtk/rtl8367s_dbg.c | 0 .../drivers/net/phy/rtk/rtl8367s_mdio.c | 0 target/linux/mediatek/mt7622/config-5.15 | 455 ++++++++++++++++++ .../100-dts-update-mt7622-rfb1.patch | 119 +++++ .../101-dts-update-mt7629-rfb.patch | 60 +++ .../105-dts-mt7622-enable-pstore.patch | 25 + .../110-dts-fix-bpi2-console.patch | 10 + .../111-dts-fix-bpi64-console.patch | 11 + .../112-dts-fix-bpi64-lan-names.patch | 37 ++ .../113-dts-fix-bpi64-leds-and-buttons.patch | 56 +++ .../114-dts-bpi64-disable-rtc.patch | 21 + .../115-dts-bpi64-add-snand-support.patch | 41 ++ .../130-dts-mt7629-add-snand-support.patch | 77 +++ .../131-dts-mt7622-add-snand-support.patch | 81 ++++ ...dts-fix-wmac-support-for-mt7622-rfb1.patch | 18 + ...s-mt7623-eip97-inside-secure-support.patch | 23 + .../160-dts-mt7623-bpi-r2-earlycon.patch | 11 + ...1-dts-mt7623-bpi-r2-mmc-device-order.patch | 11 + .../162-dts-mt7623-bpi-r2-led-aliases.patch | 29 ++ ...163-dts-mt7623-bpi-r2-ethernet-alias.patch | 10 + ...arm-dts-mt7623-add-musb-device-nodes.patch | 69 +++ ...80-dts-mt7622-bpi-r64-add-mt7531-irq.patch | 13 + ...-phy-phy-mtk-tphy-Add-hifsys-support.patch | 66 +++ .../330-mtk-snand-bmt-support.patch | 36 ++ .../331-mt7622-rfb1-enable-bmt.patch | 11 + .../360-mtd-add-mtk-snand-driver.patch | 21 + ...ypto-add-eip97-inside-secure-support.patch | 27 ++ ...01-crypto-fix-eip97-cache-incoherent.patch | 26 + .../patches-5.15/410-bt-mtk-serial-fix.patch | 33 ++ ...or-add-support-for-Winbond-W25Q512JV.patch | 28 ++ .../500-gsw-rtl8367s-mt7622-support.patch | 25 + ...mediatek-add-flow-offload-for-mt7623.patch | 24 + ...ek-Split-PCIe-node-for-MT2712-and-MT.patch | 332 +++++++++++++ ...ert-PERST-for-100ms-for-power-and-cl.patch | 34 ++ ...s-mediatek-add-mt7622-pcie-slot-node.patch | 28 ++ ...dts-mediatek-Update-mt7629-PCIe-node.patch | 203 ++++++++ ...diatek-fix-clearing-interrupt-status.patch | 23 + ...pers-to-extract-clause-45-regad-and-.patch | 53 ++ ..._eth_soc-implement-Clause-45-MDIO-ac.patch | 128 +++++ ...ernet-mtk_eth_soc-announce-2500baseT.patch | 10 + ...ediatek-add-support-for-coherent-DMA.patch | 82 ++++ .../721-dts-mt7622-mediatek-fix-300mhz.patch | 27 ++ .../patches-5.15/800-ubnt-ledbar-driver.patch | 29 ++ ...mt7622-bpi-r64-aliases-for-dtoverlay.patch | 65 +++ .../910-dts-mt7622-bpi-r64-wifi-eeprom.patch | 31 ++ 195 files changed, 2519 insertions(+) rename target/linux/mediatek/{files-5.10 => files}/drivers/leds/leds-ubnt-ledbar.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/Kconfig (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/Makefile (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand-def.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand-ecc.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand-ids.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand-mtd.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand-os.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand-os.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/mtd/mtk-snand/mtk-snand.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/Kconfig (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/Makefile (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt7530.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt7530.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt7531.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt7531.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_common.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_mdio.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_nl.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_nl.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_regs.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_vlan.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/mtk/mt753x/mt753x_vlan.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/Makefile (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/modules.builtin (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/acl.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/cpu.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/dot1x.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/eee.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/i2c.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/igmp.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/acl.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/cpu.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/dot1x.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/eee.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/i2c.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/igmp.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/interrupt.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/l2.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/leaky.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/led.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/mirror.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/oam.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/port.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/ptp.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/qos.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rate.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rldp.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtk_hal.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_acl.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_dot1x.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eav.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eee.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_fc.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_hsb.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_i2c.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_igmp.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_inbwctrl.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_interrupt.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_led.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_lut.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_meter.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mib.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mirror.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_misc.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_oam.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_phy.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_port.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_portIsolation.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rldp.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rma.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_scheduling.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_storm.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_svlan.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_trunking.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_vlan.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/smi.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/stat.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/storm.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/svlan.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/trap.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/trunk.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/include/vlan.h (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/interrupt.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/l2.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/leaky.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/led.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/mirror.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/oam.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/port.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/ptp.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/qos.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rate.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rldp.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtk_hal.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtk_switch.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_dot1x.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eee.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_i2c.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_meter.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mirror.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_misc.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_oam.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_portIsolation.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rldp.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rma.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_storm.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_trunking.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_vlan.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/smi.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/stat.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/storm.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/svlan.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/trap.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/trunk.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367c/vlan.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367s.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367s_dbg.c (100%) rename target/linux/mediatek/{files-5.10 => files}/drivers/net/phy/rtk/rtl8367s_mdio.c (100%) create mode 100644 target/linux/mediatek/mt7622/config-5.15 create mode 100644 target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch create mode 100644 target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch create mode 100644 target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch create mode 100644 target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch create mode 100644 target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch create mode 100644 target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch create mode 100644 target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch create mode 100644 target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch create mode 100644 target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch create mode 100644 target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch create mode 100644 target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch create mode 100644 target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch create mode 100644 target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch create mode 100644 target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch create mode 100644 target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch create mode 100644 target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch create mode 100644 target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch create mode 100644 target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch create mode 100644 target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch create mode 100644 target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch create mode 100644 target/linux/mediatek/patches-5.15/330-mtk-snand-bmt-support.patch create mode 100644 target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch create mode 100644 target/linux/mediatek/patches-5.15/360-mtd-add-mtk-snand-driver.patch create mode 100644 target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch create mode 100644 target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch create mode 100644 target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch create mode 100644 target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch create mode 100644 target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch create mode 100644 target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch create mode 100644 target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch create mode 100644 target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch create mode 100644 target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch create mode 100644 target/linux/mediatek/patches-5.15/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch create mode 100644 target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch create mode 100644 target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch create mode 100644 target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch create mode 100644 target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch create mode 100644 target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch create mode 100644 target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch create mode 100644 target/linux/mediatek/patches-5.15/800-ubnt-ledbar-driver.patch create mode 100644 target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch create mode 100644 target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch diff --git a/target/linux/mediatek/files-5.10/drivers/leds/leds-ubnt-ledbar.c b/target/linux/mediatek/files/drivers/leds/leds-ubnt-ledbar.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/leds/leds-ubnt-ledbar.c rename to target/linux/mediatek/files/drivers/leds/leds-ubnt-ledbar.c diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/Kconfig b/target/linux/mediatek/files/drivers/mtd/mtk-snand/Kconfig similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/Kconfig rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/Kconfig diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/Makefile b/target/linux/mediatek/files/drivers/mtd/mtk-snand/Makefile similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/Makefile rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/Makefile diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-def.h b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-def.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-def.h rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-def.h diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-ecc.c b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-ecc.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-ecc.c rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-ecc.c diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-ids.c b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-ids.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-ids.c rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-ids.c diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-mtd.c b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-mtd.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-mtd.c rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-mtd.c diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-os.c b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-os.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-os.c rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-os.c diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-os.h b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-os.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-os.h rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand-os.h diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand.c b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand.c rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand.c diff --git a/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand.h b/target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand.h rename to target/linux/mediatek/files/drivers/mtd/mtk-snand/mtk-snand.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/Kconfig b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Kconfig similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/Kconfig rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Kconfig diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/Makefile b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Makefile similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/Makefile rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Makefile diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7530.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7530.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7530.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7530.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7531.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7531.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt7531.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_common.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_common.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_common.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_common.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_mdio.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_nl.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_nl.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_nl.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_regs.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_regs.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_regs.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_regs.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_vlan.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_vlan.c rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_vlan.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/mtk/mt753x/mt753x_vlan.h rename to target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/Makefile b/target/linux/mediatek/files/drivers/net/phy/rtk/Makefile similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/Makefile rename to target/linux/mediatek/files/drivers/net/phy/rtk/Makefile diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/modules.builtin b/target/linux/mediatek/files/drivers/net/phy/rtk/modules.builtin similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/modules.builtin rename to target/linux/mediatek/files/drivers/net/phy/rtk/modules.builtin diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/acl.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/acl.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/acl.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/acl.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/cpu.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/cpu.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/cpu.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/cpu.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/dot1x.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/dot1x.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/dot1x.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/dot1x.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/eee.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/eee.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/eee.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/eee.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/i2c.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/i2c.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/i2c.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/i2c.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/igmp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/igmp.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/igmp.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/igmp.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/acl.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/acl.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/acl.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/acl.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/cpu.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/cpu.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/cpu.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/cpu.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/dot1x.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/dot1x.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/dot1x.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/dot1x.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/eee.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/eee.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/eee.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/eee.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/i2c.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/i2c.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/i2c.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/i2c.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/igmp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/igmp.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/igmp.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/igmp.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/interrupt.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/interrupt.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/interrupt.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/interrupt.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/l2.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/l2.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/l2.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/l2.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/leaky.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/leaky.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/leaky.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/leaky.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/led.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/led.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/led.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/led.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/mirror.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/mirror.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/mirror.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/mirror.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/oam.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/oam.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/oam.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/oam.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/port.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/port.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/port.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/port.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/ptp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/ptp.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/ptp.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/ptp.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/qos.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/qos.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/qos.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/qos.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rate.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rate.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rate.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rate.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rldp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rldp.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rldp.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rldp.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_hal.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_hal.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_hal.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_hal.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_acl.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_acl.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_acl.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_acl.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_dot1x.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_dot1x.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_dot1x.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_dot1x.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eav.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eav.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eav.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eav.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eee.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eee.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eee.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_eee.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_fc.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_fc.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_fc.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_fc.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_hsb.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_hsb.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_hsb.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_hsb.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_i2c.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_i2c.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_i2c.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_i2c.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_igmp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_igmp.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_igmp.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_igmp.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_inbwctrl.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_inbwctrl.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_inbwctrl.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_inbwctrl.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_interrupt.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_interrupt.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_interrupt.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_interrupt.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_led.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_led.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_led.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_led.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_lut.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_lut.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_lut.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_lut.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_meter.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_meter.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_meter.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_meter.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mib.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mib.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mib.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mib.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mirror.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mirror.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mirror.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_mirror.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_misc.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_misc.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_misc.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_misc.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_oam.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_oam.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_oam.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_oam.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_phy.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_phy.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_phy.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_phy.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_port.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_port.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_port.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_port.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_portIsolation.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_portIsolation.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_portIsolation.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_portIsolation.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rldp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rldp.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rldp.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rldp.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rma.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rma.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rma.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_rma.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_scheduling.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_scheduling.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_scheduling.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_scheduling.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_storm.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_storm.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_storm.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_storm.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_svlan.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_svlan.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_svlan.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_svlan.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_trunking.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_trunking.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_trunking.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_trunking.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_vlan.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_vlan.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_vlan.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_vlan.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/smi.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/smi.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/smi.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/smi.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/stat.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/stat.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/stat.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/stat.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/storm.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/storm.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/storm.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/storm.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/svlan.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/svlan.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/svlan.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/svlan.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/trap.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/trap.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/trap.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/trap.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/trunk.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/trunk.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/trunk.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/trunk.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/vlan.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/vlan.h similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/include/vlan.h rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/vlan.h diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/interrupt.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/interrupt.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/interrupt.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/interrupt.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/l2.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/l2.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/l2.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/l2.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/leaky.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/leaky.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/leaky.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/leaky.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/led.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/led.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/led.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/led.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/mirror.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/mirror.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/mirror.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/mirror.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/oam.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/oam.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/oam.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/oam.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/port.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/port.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/port.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/port.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/ptp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/ptp.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/ptp.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/ptp.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/qos.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/qos.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/qos.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/qos.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rate.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rate.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rate.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rate.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rldp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rldp.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rldp.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rldp.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtk_hal.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_hal.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtk_hal.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_hal.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtk_switch.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_switch.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtk_switch.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_switch.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_dot1x.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_dot1x.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_dot1x.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_dot1x.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eee.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eee.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eee.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eee.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_i2c.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_i2c.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_i2c.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_i2c.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_meter.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_meter.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_meter.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_meter.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mirror.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mirror.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mirror.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mirror.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_misc.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_misc.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_misc.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_misc.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_oam.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_oam.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_oam.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_oam.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_portIsolation.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_portIsolation.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_portIsolation.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_portIsolation.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rldp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rldp.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rldp.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rldp.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rma.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rma.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rma.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_rma.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_storm.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_storm.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_storm.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_storm.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_trunking.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_trunking.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_trunking.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_trunking.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_vlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_vlan.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_vlan.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_vlan.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/smi.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/smi.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/smi.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/stat.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/stat.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/stat.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/stat.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/storm.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/storm.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/storm.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/storm.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/svlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/svlan.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/svlan.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/svlan.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/trap.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/trap.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/trap.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/trap.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/trunk.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/trunk.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/trunk.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/trunk.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/vlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/vlan.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/vlan.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/vlan.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367s.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367s.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367s_dbg.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_dbg.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367s_dbg.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_dbg.c diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367s_mdio.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_mdio.c similarity index 100% rename from target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367s_mdio.c rename to target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_mdio.c diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 new file mode 100644 index 0000000000..1e56202f95 --- /dev/null +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -0,0 +1,455 @@ +CONFIG_64BIT=y +CONFIG_AF_UNIX_OOB=y +# CONFIG_AHCI_MTK is not set +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_CNP is not set +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_MODULE_PLTS=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +# CONFIG_ARM64_PTR_AUTH is not set +# CONFIG_ARM64_SVE is not set +# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARMV8_DEPRECATED is not set +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +CONFIG_ARM_MEDIATEK_CPUFREQ=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ATA=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BINARY_PRINTF=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BLOCK_COMPAT=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MEDIATEK=y +CONFIG_COMMON_CLK_MT2712=y +# CONFIG_COMMON_CLK_MT2712_BDPSYS is not set +# CONFIG_COMMON_CLK_MT2712_IMGSYS is not set +# CONFIG_COMMON_CLK_MT2712_JPGDECSYS is not set +# CONFIG_COMMON_CLK_MT2712_MFGCFG is not set +# CONFIG_COMMON_CLK_MT2712_MMSYS is not set +# CONFIG_COMMON_CLK_MT2712_VDECSYS is not set +# CONFIG_COMMON_CLK_MT2712_VENCSYS is not set +# CONFIG_COMMON_CLK_MT6779 is not set +# CONFIG_COMMON_CLK_MT6797 is not set +CONFIG_COMMON_CLK_MT7622=y +CONFIG_COMMON_CLK_MT7622_AUDSYS=y +CONFIG_COMMON_CLK_MT7622_ETHSYS=y +CONFIG_COMMON_CLK_MT7622_HIFSYS=y +# CONFIG_COMMON_CLK_MT8173 is not set +CONFIG_COMMON_CLK_MT8183=y +# CONFIG_COMMON_CLK_MT8183_AUDIOSYS is not set +# CONFIG_COMMON_CLK_MT8183_CAMSYS is not set +# CONFIG_COMMON_CLK_MT8183_IMGSYS is not set +# CONFIG_COMMON_CLK_MT8183_IPU_ADL is not set +# CONFIG_COMMON_CLK_MT8183_IPU_CONN is not set +# CONFIG_COMMON_CLK_MT8183_IPU_CORE0 is not set +# CONFIG_COMMON_CLK_MT8183_IPU_CORE1 is not set +# CONFIG_COMMON_CLK_MT8183_MFGCFG is not set +# CONFIG_COMMON_CLK_MT8183_MMSYS is not set +# CONFIG_COMMON_CLK_MT8183_VDECSYS is not set +# CONFIG_COMMON_CLK_MT8183_VENCSYS is not set +CONFIG_COMMON_CLK_MT8516=y +# CONFIG_COMMON_CLK_MT8516_AUDSYS is not set +CONFIG_COMPAT=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +# CONFIG_CPUFREQ_DT is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRC16=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECC=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_MISC=y +CONFIG_DIMLIB=y +CONFIG_DMADEVICES=y +CONFIG_DMATEST=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +CONFIG_DMA_OF=y +CONFIG_DMA_REMAP=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EINT_MTK=y +CONFIG_EXT4_FS=y +CONFIG_F2FS_FS=y +CONFIG_FIT_PARTITION=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_CDEV=y +CONFIG_GRO_CELLS=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MTK=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MT65XX=y +CONFIG_ICPLUS_PHY=y +CONFIG_IIO=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IO_URING=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JUMP_LABEL=y +CONFIG_LEDS_UBNT_LEDBAR=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LTO_NONE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEDIATEK_GE_PHY=y +CONFIG_MEDIATEK_MT6577_AUXADC=y +CONFIG_MEDIATEK_WATCHDOG=y +CONFIG_MEMFD_CREATE=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MTK=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_MTK_CMDQ is not set +# CONFIG_MTK_CQDMA is not set +CONFIG_MTK_EFUSE=y +CONFIG_MTK_HSDMA=y +CONFIG_MTK_INFRACFG=y +CONFIG_MTK_PMIC_WRAP=y +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +CONFIG_MTK_SPI_NAND=y +CONFIG_MTK_THERMAL=y +CONFIG_MTK_TIMER=y +# CONFIG_MTK_UART_APDMA is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_WED=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SOCK_MSG=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_MEDIATEK=y +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=2 +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_PADATA=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DEBUG=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PERF_EVENTS=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MTK_TPHY=y +# CONFIG_PHY_MTK_UFS is not set +# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6797 is not set +CONFIG_PINCTRL_MT7622=y +# CONFIG_PINCTRL_MT8173 is not set +# CONFIG_PINCTRL_MT8183 is not set +CONFIG_PINCTRL_MT8516=y +CONFIG_PINCTRL_MTK=y +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_V2=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PRINTK_TIME=y +CONFIG_PSTORE=y +# CONFIG_PSTORE_BLK is not set +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_DEFLATE_COMPRESS=y +CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_MTK_DISP is not set +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REALTEK_PHY=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_MT6380=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_MT7622=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTL8367S_GSW=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_MT65XX=y +CONFIG_SPI_MTK_NOR=y +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UCLAMP_TASK is not set +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y +# CONFIG_USB_XHCI_PLATFORM is not set +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_SYSFS=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch new file mode 100644 index 0000000000..7224a9882c --- /dev/null +++ b/target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch @@ -0,0 +1,119 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -1,7 +1,6 @@ + /* +- * Copyright (c) 2017 MediaTek Inc. +- * Author: Ming Huang +- * Sean Wang ++ * Copyright (c) 2018 MediaTek Inc. ++ * Author: Ryder Lee + * + * SPDX-License-Identifier: (GPL-2.0 OR MIT) + */ +@@ -23,7 +22,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; +- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; ++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; + }; + + cpus { +@@ -40,23 +39,22 @@ + + gpio-keys { + compatible = "gpio-keys"; +- poll-interval = <100>; + + factory { + label = "factory"; + linux,code = ; +- gpios = <&pio 0 0>; ++ gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; +- gpios = <&pio 102 0>; ++ gpios = <&pio 102 GPIO_ACTIVE_LOW>; + }; + }; + + memory { +- reg = <0 0x40000000 0 0x20000000>; ++ reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { +@@ -132,22 +130,22 @@ + + port@0 { + reg = <0>; +- label = "lan0"; ++ label = "lan1"; + }; + + port@1 { + reg = <1>; +- label = "lan1"; ++ label = "lan2"; + }; + + port@2 { + reg = <2>; +- label = "lan2"; ++ label = "lan3"; + }; + + port@3 { + reg = <3>; +- label = "lan3"; ++ label = "lan4"; + }; + + port@4 { +@@ -236,15 +234,28 @@ + + &pcie { + pinctrl-names = "default"; +- pinctrl-0 = <&pcie0_pins>; ++ pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; + status = "okay"; + + pcie@0,0 { + status = "okay"; + }; ++ ++ pcie@1,0 { ++ status = "okay"; ++ }; + }; + + &pio { ++ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and ++ * SATA functions. i.e. output-high: PCIe, output-low: SATA ++ */ ++ asm_sel { ++ gpio-hog; ++ gpios = <90 GPIO_ACTIVE_HIGH>; ++ output-high; ++ }; ++ + /* eMMC is shared pin with parallel NAND */ + emmc_pins_default: emmc-pins-default { + mux { +@@ -521,11 +532,11 @@ + }; + + &sata { +- status = "okay"; ++ status = "disabled"; + }; + + &sata_phy { +- status = "okay"; ++ status = "disabled"; + }; + + &spi0 { diff --git a/target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch b/target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch new file mode 100644 index 0000000000..254b5f9eb7 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch @@ -0,0 +1,60 @@ +--- a/arch/arm/boot/dts/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mt7629-rfb.dts +@@ -18,6 +18,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; ++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8"; + }; + + gpio-keys { +@@ -70,6 +71,10 @@ + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; ++ ++ nvmem-cells = <&macaddr_factory_2a>; ++ nvmem-cell-names = "mac-address"; ++ + fixed-link { + speed = <2500>; + full-duplex; +@@ -82,6 +87,9 @@ + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; ++ ++ nvmem-cells = <&macaddr_factory_24>; ++ nvmem-cell-names = "mac-address"; + }; + + mdio: mdio-bus { +@@ -133,8 +141,9 @@ + }; + + partition@b0000 { +- label = "kernel"; ++ label = "firmware"; + reg = <0xb0000 0xb50000>; ++ compatible = "denx,fit"; + }; + }; + }; +@@ -272,3 +281,17 @@ + pinctrl-0 = <&watchdog_pins>; + status = "okay"; + }; ++ ++&factory { ++ compatible = "nvmem-cells"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr_factory_24: macaddr@24 { ++ reg = <0x24 0x6>; ++ }; ++ ++ macaddr_factory_2a: macaddr@2a { ++ reg = <0x2a 0x6>; ++ }; ++}; diff --git a/target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch b/target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch new file mode 100644 index 0000000000..6ef56f8584 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch @@ -0,0 +1,25 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -111,7 +111,7 @@ + }; + + psci { +- compatible = "arm,psci-0.2"; ++ compatible = "arm,psci-1.0"; + method = "smc"; + }; + +@@ -127,6 +127,13 @@ + #size-cells = <2>; + ranges; + ++ /* 64 KiB reserved for ramoops/pstore */ ++ ramoops@0x42ff0000 { ++ compatible = "ramoops"; ++ reg = <0 0x42ff0000 0 0x10000>; ++ record-size = <0x1000>; ++ }; ++ + /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch new file mode 100644 index 0000000000..8dc53d2985 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -19,6 +19,7 @@ + + chosen { + stdout-path = "serial2:115200n8"; ++ bootargs = "console=ttyS2,115200n8 console=tty1"; + }; + + connector { diff --git a/target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch b/target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch new file mode 100644 index 0000000000..07a2eae245 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch @@ -0,0 +1,11 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -22,7 +22,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; +- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; ++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; + }; + + cpus { diff --git a/target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch new file mode 100644 index 0000000000..6ce85efde9 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch @@ -0,0 +1,37 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -18,6 +18,7 @@ + + aliases { + serial0 = &uart0; ++ ethernet0 = &gmac0; + }; + + chosen { +@@ -160,22 +161,22 @@ + + port@1 { + reg = <1>; +- label = "lan0"; ++ label = "lan1"; + }; + + port@2 { + reg = <2>; +- label = "lan1"; ++ label = "lan2"; + }; + + port@3 { + reg = <3>; +- label = "lan2"; ++ label = "lan3"; + }; + + port@4 { + reg = <4>; +- label = "lan3"; ++ label = "lan4"; + }; + + port@6 { diff --git a/target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch b/target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch new file mode 100644 index 0000000000..f88dbc7195 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch @@ -0,0 +1,56 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -19,6 +19,10 @@ + aliases { + serial0 = &uart0; + ethernet0 = &gmac0; ++ led-boot = &led_system_green; ++ led-failsafe = &led_system_blue; ++ led-running = &led_system_green; ++ led-upgrade = &led_system_blue; + }; + + chosen { +@@ -42,8 +46,8 @@ + compatible = "gpio-keys"; + + factory { +- label = "factory"; +- linux,code = ; ++ label = "reset"; ++ linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + +@@ -57,17 +61,25 @@ + leds { + compatible = "gpio-leds"; + +- green { +- label = "bpi-r64:pio:green"; +- gpios = <&pio 89 GPIO_ACTIVE_HIGH>; ++ led_system_blue: blue { ++ label = "bpi-r64:pio:blue"; ++ gpios = <&pio 85 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + +- red { +- label = "bpi-r64:pio:red"; +- gpios = <&pio 88 GPIO_ACTIVE_HIGH>; ++ led_system_green: green { ++ label = "bpi-r64:pio:green"; ++ gpios = <&pio 89 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; ++ ++/* ++ * red { ++ * label = "bpi-r64:pio:red"; ++ * gpios = <&pio 88 GPIO_ACTIVE_HIGH>; ++ * default-state = "off"; ++ * }; ++ */ + }; + + memory { diff --git a/target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch new file mode 100644 index 0000000000..1f41142aac --- /dev/null +++ b/target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch @@ -0,0 +1,21 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -564,12 +564,16 @@ + status = "okay"; + }; + ++&rtc { ++ status = "disabled"; ++}; ++ + &sata { +- status = "disable"; ++ status = "disabled"; + }; + + &sata_phy { +- status = "disable"; ++ status = "disabled"; + }; + + &spi0 { diff --git a/target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch b/target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch new file mode 100644 index 0000000000..39d81bd5d5 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch @@ -0,0 +1,41 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -259,14 +259,32 @@ + status = "disabled"; + }; + +-&nor_flash { ++&snand { + pinctrl-names = "default"; +- pinctrl-0 = <&spi_nor_pins>; +- status = "disabled"; ++ pinctrl-0 = <&serial_nand_pins>; ++ mediatek,quad-spi; ++ status = "okay"; ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x80000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "fip"; ++ reg = <0x80000 0x200000>; ++ read-only; ++ }; + +- flash@0 { +- compatible = "jedec,spi-nor"; +- reg = <0>; ++ partition@280000 { ++ label = "ubi"; ++ reg = <0x280000 0x7d80000>; ++ }; + }; + }; + diff --git a/target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch new file mode 100644 index 0000000000..e7c5d9b167 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch @@ -0,0 +1,77 @@ +From c813fbe806257c574240770ef716fbee19f7dbfa Mon Sep 17 00:00:00 2001 +From: Xiangsheng Hou +Date: Thu, 6 Jun 2019 16:29:04 +0800 +Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629 + +Signed-off-by: Xiangsheng Hou +--- + arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++ + 3 files changed, 79 insertions(+) + +--- a/arch/arm/boot/dts/mt7629.dtsi ++++ b/arch/arm/boot/dts/mt7629.dtsi +@@ -272,6 +272,22 @@ + status = "disabled"; + }; + ++ snand: snfi@1100d000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial_nand_pins>; ++ compatible = "mediatek,mt7629-snand"; ++ reg = <0x1100d000 0x1000>, <0x1100e000 0x1000>; ++ reg-names = "nfi", "ecc"; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_NFI_PD>, ++ <&pericfg CLK_PERI_SNFI_PD>, ++ <&pericfg CLK_PERI_NFIECC_PD>; ++ clock-names = "nfi_clk", "pad_clk", "ecc_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + spi: spi@1100a000 { + compatible = "mediatek,mt7629-spi", + "mediatek,mt7622-spi"; +--- a/arch/arm/boot/dts/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mt7629-rfb.dts +@@ -254,6 +254,38 @@ + }; + }; + ++&snand { ++ status = "okay"; ++ mediatek,quad-spi; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "Bootloader"; ++ reg = <0x00000 0x0100000>; ++ read-only; ++ }; ++ ++ partition@100000 { ++ label = "Config"; ++ reg = <0x100000 0x0040000>; ++ }; ++ ++ partition@140000 { ++ label = "factory"; ++ reg = <0x140000 0x0080000>; ++ }; ++ ++ partition@1c0000 { ++ label = "firmware"; ++ reg = <0x1c0000 0x1000000>; ++ }; ++ }; ++}; ++ + &spi { + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; diff --git a/target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch new file mode 100644 index 0000000000..b8050b3592 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch @@ -0,0 +1,81 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -561,6 +561,20 @@ + status = "disabled"; + }; + ++ snand: snfi@1100d000 { ++ compatible = "mediatek,mt7622-snand"; ++ reg = <0 0x1100d000 0 0x1000>, <0 0x1100e000 0 0x1000>; ++ reg-names = "nfi", "ecc"; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_NFI_PD>, ++ <&pericfg CLK_PERI_SNFI_PD>, ++ <&pericfg CLK_PERI_NFIECC_PD>; ++ clock-names = "nfi_clk", "pad_clk", "ecc_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + nor_flash: spi@11014000 { + compatible = "mediatek,mt7622-nor", + "mediatek,mt8173-nor"; +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -539,6 +539,55 @@ + status = "disabled"; + }; + ++&snand { ++ mediatek,quad-spi; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial_nand_pins>; ++ status = "okay"; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "Preloader"; ++ reg = <0x00000 0x0080000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "ATF"; ++ reg = <0x80000 0x0040000>; ++ }; ++ ++ partition@c0000 { ++ label = "Bootloader"; ++ reg = <0xc0000 0x0080000>; ++ }; ++ ++ partition@140000 { ++ label = "Config"; ++ reg = <0x140000 0x0080000>; ++ }; ++ ++ partition@1c0000 { ++ label = "Factory"; ++ reg = <0x1c0000 0x0100000>; ++ }; ++ ++ partition@200000 { ++ label = "firmware"; ++ reg = <0x2c0000 0x2000000>; ++ }; ++ ++ partition@2200000 { ++ label = "User_data"; ++ reg = <0x22c0000 0x4000000>; ++ }; ++ }; ++}; ++ + &spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spic0_pins>; diff --git a/target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch new file mode 100644 index 0000000000..b65c4a2805 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch @@ -0,0 +1,18 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -571,7 +571,7 @@ + reg = <0x140000 0x0080000>; + }; + +- partition@1c0000 { ++ factory: partition@1c0000 { + label = "Factory"; + reg = <0x1c0000 0x0100000>; + }; +@@ -631,5 +631,6 @@ + &wmac { + pinctrl-names = "default"; + pinctrl-0 = <&wmac_pins>; ++ mediatek,mtd-eeprom = <&factory 0x0000>; + status = "okay"; + }; diff --git a/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch new file mode 100644 index 0000000000..a443404fff --- /dev/null +++ b/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch @@ -0,0 +1,23 @@ +--- a/arch/arm/boot/dts/mt7623.dtsi ++++ b/arch/arm/boot/dts/mt7623.dtsi +@@ -951,17 +951,14 @@ + }; + + crypto: crypto@1b240000 { +- compatible = "mediatek,eip97-crypto"; ++ compatible = "inside-secure,safexcel-eip97"; + reg = <0 0x1b240000 0 0x20000>; + interrupts = , + , + , +- , +- ; ++ ; ++ interrupt-names = "ring0", "ring1", "ring2", "ring3"; + clocks = <ðsys CLK_ETHSYS_CRYPTO>; +- clock-names = "cryp"; +- power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; +- status = "disabled"; + }; + + bdpsys: syscon@1c000000 { diff --git a/target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch b/target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch new file mode 100644 index 0000000000..091cffc3c0 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -19,7 +19,7 @@ + + chosen { + stdout-path = "serial2:115200n8"; +- bootargs = "console=ttyS2,115200n8 console=tty1"; ++ bootargs = "earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; + }; + + connector { diff --git a/target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch b/target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch new file mode 100644 index 0000000000..d1bafc1526 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -15,6 +15,8 @@ + + aliases { + serial2 = &uart2; ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; + }; + + chosen { diff --git a/target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch b/target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch new file mode 100644 index 0000000000..f6745add5b --- /dev/null +++ b/target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch @@ -0,0 +1,29 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -17,6 +17,10 @@ + serial2 = &uart2; + mmc0 = &mmc0; + mmc1 = &mmc1; ++ led-boot = &led_system_green; ++ led-failsafe = &led_system_blue; ++ led-running = &led_system_green; ++ led-upgrade = &led_system_blue; + }; + + chosen { +@@ -112,13 +116,13 @@ + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_a>; + +- blue { ++ led_system_blue: blue { + label = "bpi-r2:pio:blue"; + gpios = <&pio 240 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + +- green { ++ led_system_green: green { + label = "bpi-r2:pio:green"; + gpios = <&pio 241 GPIO_ACTIVE_LOW>; + default-state = "off"; diff --git a/target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch b/target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch new file mode 100644 index 0000000000..b1dd75a414 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -15,6 +15,7 @@ + + aliases { + serial2 = &uart2; ++ ethernet0 = &gmac0; + mmc0 = &mmc0; + mmc1 = &mmc1; + led-boot = &led_system_green; diff --git a/target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch b/target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch new file mode 100644 index 0000000000..ba1d1fe202 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch @@ -0,0 +1,69 @@ +From 21d106f15262f5a2ef7531636e0703ee61c33c61 Mon Sep 17 00:00:00 2001 +From: Sungbo Eo +Date: Sun, 8 Aug 2021 21:38:40 +0900 +Subject: [PATCH 2/2] arm: dts: mt7623: add musb device nodes + +MT7623 has an musb controller that is compatible with the one from MT2701. + +Signed-off-by: Sungbo Eo +--- + arch/arm/boot/dts/mt7623.dtsi | 34 ++++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/mt7623a.dtsi | 4 ++++ + 2 files changed, 38 insertions(+) + +--- a/arch/arm/boot/dts/mt7623.dtsi ++++ b/arch/arm/boot/dts/mt7623.dtsi +@@ -585,6 +585,40 @@ + status = "disabled"; + }; + ++ usb0: usb@11200000 { ++ compatible = "mediatek,mt7623-musb", ++ "mediatek,mtk-musb"; ++ reg = <0 0x11200000 0 0x1000>; ++ interrupts = ; ++ interrupt-names = "mc"; ++ phys = <&u2port2 PHY_TYPE_USB2>; ++ dr_mode = "otg"; ++ clocks = <&pericfg CLK_PERI_USB0>, ++ <&pericfg CLK_PERI_USB0_MCU>, ++ <&pericfg CLK_PERI_USB_SLV>; ++ clock-names = "main","mcu","univpll"; ++ power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>; ++ status = "disabled"; ++ }; ++ ++ u2phy1: t-phy@11210000 { ++ compatible = "mediatek,mt7623-tphy", ++ "mediatek,generic-tphy-v1"; ++ reg = <0 0x11210000 0 0x0800>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ u2port2: usb-phy@11210800 { ++ reg = <0 0x11210800 0 0x0100>; ++ clocks = <&topckgen CLK_TOP_USB_PHY48M>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ status = "okay"; ++ }; ++ }; ++ + audsys: clock-controller@11220000 { + compatible = "mediatek,mt7623-audsys", + "mediatek,mt2701-audsys", +--- a/arch/arm/boot/dts/mt7623a.dtsi ++++ b/arch/arm/boot/dts/mt7623a.dtsi +@@ -35,6 +35,10 @@ + clock-names = "ethif"; + }; + ++&usb0 { ++ power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; ++}; ++ + &usb1 { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; + }; diff --git a/target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch b/target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch new file mode 100644 index 0000000000..80ceb490d4 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch @@ -0,0 +1,13 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -160,6 +160,10 @@ + switch@0 { + compatible = "mediatek,mt7531"; + reg = <0>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&pio>; ++ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 54 0>; + + ports { diff --git a/target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch new file mode 100644 index 0000000000..860728f02d --- /dev/null +++ b/target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch @@ -0,0 +1,66 @@ +From 28f9a5e2a3f5441ab5594669ed82da11e32277a9 Mon Sep 17 00:00:00 2001 +From: Kristian Evensen +Date: Mon, 30 Apr 2018 14:38:01 +0200 +Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support + +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -18,6 +18,8 @@ + #include + #include + #include ++#include ++#include + + /* version V1 sub-banks offset base address */ + /* banks shared by multiple phys */ +@@ -311,6 +313,9 @@ + + #define TPHY_CLKS_CNT 2 + ++#define HIF_SYSCFG1 0x14 ++#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20) ++ + enum mtk_phy_version { + MTK_PHY_V1 = 1, + MTK_PHY_V2, +@@ -377,6 +382,7 @@ struct mtk_tphy { + void __iomem *sif_base; /* only shared sif */ + const struct mtk_phy_pdata *pdata; + struct mtk_phy_instance **phys; ++ struct regmap *hif; + int nphys; + int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ + int src_coef; /* coefficient for slew rate calibrate */ +@@ -730,6 +736,10 @@ static void pcie_phy_instance_init(struc + if (tphy->pdata->version != MTK_PHY_V1) + return; + ++ if (tphy->hif) ++ regmap_update_bits(tphy->hif, HIF_SYSCFG1, ++ HIF_SYSCFG1_PHY2_MASK, 0); ++ + tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0); + tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H); + tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2); +@@ -1436,6 +1446,16 @@ static int mtk_tphy_probe(struct platfor + &tphy->src_coef); + } + ++ if (of_find_property(np, "mediatek,phy-switch", NULL)) { ++ tphy->hif = syscon_regmap_lookup_by_phandle(np, ++ "mediatek,phy-switch"); ++ if (IS_ERR(tphy->hif)) { ++ dev_err(&pdev->dev, ++ "missing \"mediatek,phy-switch\" phandle\n"); ++ return PTR_ERR(tphy->hif); ++ } ++ } ++ + port = 0; + for_each_child_of_node(np, child_np) { + struct mtk_phy_instance *instance; diff --git a/target/linux/mediatek/patches-5.15/330-mtk-snand-bmt-support.patch b/target/linux/mediatek/patches-5.15/330-mtk-snand-bmt-support.patch new file mode 100644 index 0000000000..318c8b2873 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/330-mtk-snand-bmt-support.patch @@ -0,0 +1,36 @@ +--- a/drivers/mtd/mtk-snand/mtk-snand-mtd.c ++++ b/drivers/mtd/mtk-snand/mtk-snand-mtd.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -612,6 +613,8 @@ static int mtk_snand_probe(struct platfo + mtd->_block_isbad = mtk_snand_mtd_block_isbad; + mtd->_block_markbad = mtk_snand_mtd_block_markbad; + ++ mtk_bmt_attach(mtd); ++ + ret = mtd_device_register(mtd, NULL, 0); + if (ret) { + dev_err(msm->pdev.dev, "failed to register mtd partition\n"); +@@ -623,6 +626,7 @@ static int mtk_snand_probe(struct platfo + return 0; + + errout4: ++ mtk_bmt_detach(mtd); + devm_kfree(msm->pdev.dev, msm->page_cache); + + errout3: +@@ -650,6 +654,8 @@ static int mtk_snand_remove(struct platf + if (ret) + return ret; + ++ mtk_bmt_detach(mtd); ++ + mtk_snand_cleanup(msm->snf); + + if (msm->irq >= 0) diff --git a/target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch new file mode 100644 index 0000000000..03c0771bcf --- /dev/null +++ b/target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch @@ -0,0 +1,11 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -545,6 +545,8 @@ + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; + ++ mediatek,bmt-v2; ++ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; diff --git a/target/linux/mediatek/patches-5.15/360-mtd-add-mtk-snand-driver.patch b/target/linux/mediatek/patches-5.15/360-mtd-add-mtk-snand-driver.patch new file mode 100644 index 0000000000..149215c113 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/360-mtd-add-mtk-snand-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -241,6 +241,8 @@ source "drivers/mtd/ubi/Kconfig" + + source "drivers/mtd/hyperbus/Kconfig" + ++source "drivers/mtd/mtk-snand/Kconfig" ++ + source "drivers/mtd/composite/Kconfig" + + endif # MTD +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -34,5 +34,7 @@ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-$(CONFIG_MTD_UBI) += ubi/ + obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ + ++obj-$(CONFIG_MTK_SPI_NAND) += mtk-snand/ ++ + # Composite drivers must be loaded last + obj-y += composite/ diff --git a/target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch new file mode 100644 index 0000000000..25ca9485e4 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch @@ -0,0 +1,27 @@ +--- a/drivers/crypto/inside-secure/safexcel.c ++++ b/drivers/crypto/inside-secure/safexcel.c +@@ -600,6 +600,14 @@ static int safexcel_hw_init(struct safex + val |= EIP197_MST_CTRL_TX_MAX_CMD(5); + writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); + } ++ /* ++ * Set maximum number of TX commands to 2^4 = 16 for EIP97 HW2.1/HW2.3 ++ */ ++ else { ++ val = 0; ++ val |= EIP97_MST_CTRL_TX_MAX_CMD(4); ++ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); ++ } + + /* Configure wr/rd cache values */ + writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) | +--- a/drivers/crypto/inside-secure/safexcel.h ++++ b/drivers/crypto/inside-secure/safexcel.h +@@ -315,6 +315,7 @@ + #define EIP197_MST_CTRL_RD_CACHE(n) (((n) & 0xf) << 0) + #define EIP197_MST_CTRL_WD_CACHE(n) (((n) & 0xf) << 4) + #define EIP197_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 20) ++#define EIP97_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 4) + #define EIP197_MST_CTRL_BYTE_SWAP BIT(24) + #define EIP197_MST_CTRL_NO_BYTE_SWAP BIT(25) + #define EIP197_MST_CTRL_BYTE_SWAP_BITS GENMASK(25, 24) diff --git a/target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch new file mode 100644 index 0000000000..186c66f687 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch @@ -0,0 +1,26 @@ +--- a/drivers/crypto/inside-secure/safexcel.h ++++ b/drivers/crypto/inside-secure/safexcel.h +@@ -737,6 +737,9 @@ enum safexcel_eip_version { + /* Priority we use for advertising our algorithms */ + #define SAFEXCEL_CRA_PRIORITY 300 + ++/* System cache line size */ ++#define SYSTEM_CACHELINE_SIZE 64 ++ + /* SM3 digest result for zero length message */ + #define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ + "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ +--- a/drivers/crypto/inside-secure/safexcel_hash.c ++++ b/drivers/crypto/inside-secure/safexcel_hash.c +@@ -55,9 +55,9 @@ struct safexcel_ahash_req { + u8 block_sz; /* block size, only set once */ + u8 digest_sz; /* output digest size, only set once */ + __le32 state[SHA3_512_BLOCK_SIZE / +- sizeof(__le32)] __aligned(sizeof(__le32)); ++ sizeof(__le32)] __aligned(SYSTEM_CACHELINE_SIZE); + +- u64 len; ++ u64 len __aligned(SYSTEM_CACHELINE_SIZE); + u64 processed; + + u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); diff --git a/target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch new file mode 100644 index 0000000000..f5e027ae09 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch @@ -0,0 +1,33 @@ +--- a/drivers/tty/serial/8250/8250.h ++++ b/drivers/tty/serial/8250/8250.h +@@ -83,6 +83,7 @@ struct serial8250_config { + #define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks: + * STOP PARITY EPAR SPAR WLEN5 WLEN6 + */ ++#define UART_CAP_NMOD (1 << 18) /* UART doesn't do termios */ + + #define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */ + #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -288,7 +288,7 @@ static const struct serial8250_config ua + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, +- .flags = UART_CAP_FIFO, ++ .flags = UART_CAP_FIFO | UART_CAP_NMOD, + }, + [PORT_NPCM] = { + .name = "Nuvoton 16550", +@@ -2746,6 +2746,11 @@ serial8250_do_set_termios(struct uart_po + unsigned long flags; + unsigned int baud, quot, frac = 0; + ++ if (up->capabilities & UART_CAP_NMOD) { ++ termios->c_cflag = 0; ++ return; ++ } ++ + if (up->capabilities & UART_CAP_MINI) { + termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); + if ((termios->c_cflag & CSIZE) == CS5 || diff --git a/target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch b/target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch new file mode 100644 index 0000000000..cc9e9c55e3 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch @@ -0,0 +1,28 @@ +From: David Bauer +To: linux-mtd@lists.infradead.org +Subject: [PATCH] mtd: spi-nor: add support for Winbond W25Q512JV +Date: Sat, 13 Feb 2021 16:10:47 +0100 + +The Winbond W25Q512JV is a 512mb SPI-NOR chip. It supports 4K +sectors as well as block protection and Dual-/Quad-read. + +Tested on: Ubiquiti UniFi 6 LR + +Signed-off-by: David Bauer +--- + drivers/mtd/spi-nor/winbond.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/spi-nor/winbond.c ++++ b/drivers/mtd/spi-nor/winbond.c +@@ -98,6 +98,10 @@ static const struct flash_info winbond_p + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "w25q512jv", INFO(0xef4020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ | ++ SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | ++ SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP) }, + { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, + { "w25q512jvq", INFO(0xef4020, 0, 64 * 1024, 1024, diff --git a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch new file mode 100644 index 0000000000..aec8f327f1 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -366,6 +366,12 @@ config ROCKCHIP_PHY + help + Currently supports the integrated Ethernet PHY. + ++config RTL8367S_GSW ++ tristate "rtl8367 Gigabit Switch support for mt7622" ++ depends on NET_VENDOR_MEDIATEK ++ help ++ This driver supports rtl8367s in mt7622 ++ + config SMSC_PHY + tristate "SMSC PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -93,6 +93,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o ++obj-$(CONFIG_RTL8367S_GSW) += rtk/ + obj-$(CONFIG_SMSC_PHY) += smsc.o + obj-$(CONFIG_STE10XP) += ste10Xp.o + obj-$(CONFIG_TERANETICS_PHY) += teranetics.o diff --git a/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch b/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch new file mode 100644 index 0000000000..8c506e41cc --- /dev/null +++ b/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch @@ -0,0 +1,24 @@ +From 4823778b116c08e9c55dbc5b5042223289ea6a0c Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 31 Mar 2021 15:34:37 +0200 +Subject: [PATCH] net: mediatek: add flow offload for mt7623 + +mt7623 uses offload version 2 too + +tested on Bananapi-R2 + +Signed-off-by: Frank Wunderlich +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3364,6 +3364,7 @@ static const struct mtk_soc_data mt2701_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, ++ .offload_version = 2, + }; + + static const struct mtk_soc_data mt7621_data = { diff --git a/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch b/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch new file mode 100644 index 0000000000..a1f744f5da --- /dev/null +++ b/target/linux/mediatek/patches-5.15/600-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch @@ -0,0 +1,332 @@ +From: Chuanjia Liu +Date: Mon, 23 Aug 2021 11:27:59 +0800 +Subject: [PATCH] arm64: dts: mediatek: Split PCIe node for MT2712 and MT7622 + +There are two independent PCIe controllers in MT2712 and MT7622 +platform. Each of them should contain an independent MSI domain. + +In old dts architecture, MSI domain will be inherited from the root +bridge, and all of the devices will share the same MSI domain. +Hence that, the PCIe devices will not work properly if the irq number +which required is more than 32. + +Split the PCIe node for MT2712 and MT7622 platform to comply with +the hardware design and fix MSI issue. + +Signed-off-by: Chuanjia Liu +Acked-by: Ryder Lee +Link: https://lore.kernel.org/r/20210823032800.1660-6-chuanjia.liu@mediatek.com +Signed-off-by: Matthias Brugger +--- + +--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +@@ -915,64 +915,67 @@ + }; + }; + +- pcie: pcie@11700000 { ++ pcie1: pcie@112ff000 { + compatible = "mediatek,mt2712-pcie"; + device_type = "pci"; +- reg = <0 0x11700000 0 0x1000>, +- <0 0x112ff000 0 0x1000>; +- reg-names = "port0", "port1"; ++ reg = <0 0x112ff000 0 0x1000>; ++ reg-names = "port1"; ++ linux,pci-domain = <1>; + #address-cells = <3>; + #size-cells = <2>; +- interrupts = , +- ; +- clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, +- <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, +- <&pericfg CLK_PERI_PCIE0>, ++ interrupts = ; ++ interrupt-names = "pcie_irq"; ++ clocks = <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, + <&pericfg CLK_PERI_PCIE1>; +- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1"; +- phys = <&u3port0 PHY_TYPE_PCIE>, <&u3port1 PHY_TYPE_PCIE>; +- phy-names = "pcie-phy0", "pcie-phy1"; ++ clock-names = "sys_ck1", "ahb_ck1"; ++ phys = <&u3port1 PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy1"; + bus-range = <0x00 0xff>; +- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; ++ ranges = <0x82000000 0 0x11400000 0x0 0x11400000 0 0x300000>; ++ status = "disabled"; + +- pcie0: pcie@0,0 { +- device_type = "pci"; +- status = "disabled"; +- reg = <0x0000 0 0 0 0>; +- #address-cells = <3>; +- #size-cells = <2>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc1 0>, ++ <0 0 0 2 &pcie_intc1 1>, ++ <0 0 0 3 &pcie_intc1 2>, ++ <0 0 0 4 &pcie_intc1 3>; ++ pcie_intc1: interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; + #interrupt-cells = <1>; +- ranges; +- interrupt-map-mask = <0 0 0 7>; +- interrupt-map = <0 0 0 1 &pcie_intc0 0>, +- <0 0 0 2 &pcie_intc0 1>, +- <0 0 0 3 &pcie_intc0 2>, +- <0 0 0 4 &pcie_intc0 3>; +- pcie_intc0: interrupt-controller { +- interrupt-controller; +- #address-cells = <0>; +- #interrupt-cells = <1>; +- }; + }; ++ }; ++ ++ pcie0: pcie@11700000 { ++ compatible = "mediatek,mt2712-pcie"; ++ device_type = "pci"; ++ reg = <0 0x11700000 0 0x1000>; ++ reg-names = "port0"; ++ linux,pci-domain = <0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ interrupts = ; ++ interrupt-names = "pcie_irq"; ++ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, ++ <&pericfg CLK_PERI_PCIE0>; ++ clock-names = "sys_ck0", "ahb_ck0"; ++ phys = <&u3port0 PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy0"; ++ bus-range = <0x00 0xff>; ++ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; ++ status = "disabled"; + +- pcie1: pcie@1,0 { +- device_type = "pci"; +- status = "disabled"; +- reg = <0x0800 0 0 0 0>; +- #address-cells = <3>; +- #size-cells = <2>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc0 0>, ++ <0 0 0 2 &pcie_intc0 1>, ++ <0 0 0 3 &pcie_intc0 2>, ++ <0 0 0 4 &pcie_intc0 3>; ++ pcie_intc0: interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; + #interrupt-cells = <1>; +- ranges; +- interrupt-map-mask = <0 0 0 7>; +- interrupt-map = <0 0 0 1 &pcie_intc1 0>, +- <0 0 0 2 &pcie_intc1 1>, +- <0 0 0 3 &pcie_intc1 2>, +- <0 0 0 4 &pcie_intc1 3>; +- pcie_intc1: interrupt-controller { +- interrupt-controller; +- #address-cells = <0>; +- #interrupt-cells = <1>; +- }; + }; + }; + +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -292,18 +292,16 @@ + }; + }; + +-&pcie { ++&pcie0 { + pinctrl-names = "default"; +- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; ++ pinctrl-0 = <&pcie0_pins>; + status = "okay"; ++}; + +- pcie@0,0 { +- status = "okay"; +- }; +- +- pcie@1,0 { +- status = "okay"; +- }; ++&pcie1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie1_pins>; ++ status = "okay"; + }; + + &pio { +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -232,18 +232,16 @@ + }; + }; + +-&pcie { ++&pcie0 { + pinctrl-names = "default"; +- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; ++ pinctrl-0 = <&pcie0_pins>; + status = "okay"; ++}; + +- pcie@0,0 { +- status = "okay"; +- }; +- +- pcie@1,0 { +- status = "okay"; +- }; ++&pcie1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie1_pins>; ++ status = "okay"; + }; + + &pio { +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -802,75 +802,83 @@ + #reset-cells = <1>; + }; + +- pcie: pcie@1a140000 { ++ pciecfg: pciecfg@1a140000 { ++ compatible = "mediatek,generic-pciecfg", "syscon"; ++ reg = <0 0x1a140000 0 0x1000>; ++ }; ++ ++ pcie0: pcie@1a143000 { + compatible = "mediatek,mt7622-pcie"; + device_type = "pci"; +- reg = <0 0x1a140000 0 0x1000>, +- <0 0x1a143000 0 0x1000>, +- <0 0x1a145000 0 0x1000>; +- reg-names = "subsys", "port0", "port1"; ++ reg = <0 0x1a143000 0 0x1000>; ++ reg-names = "port0"; ++ linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; +- interrupts = , +- ; ++ interrupts = ; ++ interrupt-names = "pcie_irq"; + clocks = <&pciesys CLK_PCIE_P0_MAC_EN>, +- <&pciesys CLK_PCIE_P1_MAC_EN>, +- <&pciesys CLK_PCIE_P0_AHB_EN>, + <&pciesys CLK_PCIE_P0_AHB_EN>, + <&pciesys CLK_PCIE_P0_AUX_EN>, +- <&pciesys CLK_PCIE_P1_AUX_EN>, + <&pciesys CLK_PCIE_P0_AXI_EN>, +- <&pciesys CLK_PCIE_P1_AXI_EN>, + <&pciesys CLK_PCIE_P0_OBFF_EN>, +- <&pciesys CLK_PCIE_P1_OBFF_EN>, +- <&pciesys CLK_PCIE_P0_PIPE_EN>, +- <&pciesys CLK_PCIE_P1_PIPE_EN>; +- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1", +- "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1", +- "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1"; ++ <&pciesys CLK_PCIE_P0_PIPE_EN>; ++ clock-names = "sys_ck0", "ahb_ck0", "aux_ck0", ++ "axi_ck0", "obff_ck0", "pipe_ck0"; ++ + power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; + bus-range = <0x00 0xff>; +- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; ++ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; + status = "disabled"; + +- pcie0: pcie@0,0 { +- reg = <0x0000 0 0 0 0>; +- #address-cells = <3>; +- #size-cells = <2>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc0 0>, ++ <0 0 0 2 &pcie_intc0 1>, ++ <0 0 0 3 &pcie_intc0 2>, ++ <0 0 0 4 &pcie_intc0 3>; ++ pcie_intc0: interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; + #interrupt-cells = <1>; +- ranges; +- status = "disabled"; +- +- interrupt-map-mask = <0 0 0 7>; +- interrupt-map = <0 0 0 1 &pcie_intc0 0>, +- <0 0 0 2 &pcie_intc0 1>, +- <0 0 0 3 &pcie_intc0 2>, +- <0 0 0 4 &pcie_intc0 3>; +- pcie_intc0: interrupt-controller { +- interrupt-controller; +- #address-cells = <0>; +- #interrupt-cells = <1>; +- }; + }; ++ }; + +- pcie1: pcie@1,0 { +- reg = <0x0800 0 0 0 0>; +- #address-cells = <3>; +- #size-cells = <2>; +- #interrupt-cells = <1>; +- ranges; +- status = "disabled"; ++ pcie1: pcie@1a145000 { ++ compatible = "mediatek,mt7622-pcie"; ++ device_type = "pci"; ++ reg = <0 0x1a145000 0 0x1000>; ++ reg-names = "port1"; ++ linux,pci-domain = <1>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ interrupts = ; ++ interrupt-names = "pcie_irq"; ++ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, ++ /* designer has connect RC1 with p0_ahb clock */ ++ <&pciesys CLK_PCIE_P0_AHB_EN>, ++ <&pciesys CLK_PCIE_P1_AUX_EN>, ++ <&pciesys CLK_PCIE_P1_AXI_EN>, ++ <&pciesys CLK_PCIE_P1_OBFF_EN>, ++ <&pciesys CLK_PCIE_P1_PIPE_EN>; ++ clock-names = "sys_ck1", "ahb_ck1", "aux_ck1", ++ "axi_ck1", "obff_ck1", "pipe_ck1"; ++ ++ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; ++ bus-range = <0x00 0xff>; ++ ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; ++ status = "disabled"; + +- interrupt-map-mask = <0 0 0 7>; +- interrupt-map = <0 0 0 1 &pcie_intc1 0>, +- <0 0 0 2 &pcie_intc1 1>, +- <0 0 0 3 &pcie_intc1 2>, +- <0 0 0 4 &pcie_intc1 3>; +- pcie_intc1: interrupt-controller { +- interrupt-controller; +- #address-cells = <0>; +- #interrupt-cells = <1>; +- }; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc1 0>, ++ <0 0 0 2 &pcie_intc1 1>, ++ <0 0 0 3 &pcie_intc1 2>, ++ <0 0 0 4 &pcie_intc1 3>; ++ pcie_intc1: interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; + }; + }; + diff --git a/target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch b/target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch new file mode 100644 index 0000000000..ff48227210 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch @@ -0,0 +1,34 @@ +From: qizhong cheng +Date: Mon, 27 Dec 2021 21:31:10 +0800 +Subject: [PATCH] PCI: mediatek: Assert PERST# for 100ms for power and clock to + stabilize +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Described in PCIe CEM specification sections 2.2 (PERST# Signal) and +2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should +be delayed 100ms (TPVPERL) for the power and clock to become stable. + +Link: https://lore.kernel.org/r/20211227133110.14500-1-qizhong.cheng@mediatek.com +Signed-off-by: qizhong cheng +Signed-off-by: Lorenzo Pieralisi +Acked-by: Pali Rohár +--- + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -702,6 +702,13 @@ static int mtk_pcie_startup_port_v2(stru + */ + writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL); + ++ /* ++ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and ++ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should ++ * be delayed 100ms (TPVPERL) for the power and clock to become stable. ++ */ ++ msleep(100); ++ + /* De-assert PHY, PE, PIPE, MAC and configuration reset */ + val = readl(port->base + PCIE_RST_CTRL); + val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | diff --git a/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch b/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch new file mode 100644 index 0000000000..25a5eb87c7 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch @@ -0,0 +1,28 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -842,6 +842,12 @@ + #address-cells = <0>; + #interrupt-cells = <1>; + }; ++ ++ slot0: pcie@0,0 { ++ reg = <0x0000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ }; + }; + + pcie1: pcie@1a145000 { +@@ -880,6 +886,12 @@ + #address-cells = <0>; + #interrupt-cells = <1>; + }; ++ ++ slot1: pcie@1,0 { ++ reg = <0x0800 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ }; + }; + + sata: sata@1a200000 { diff --git a/target/linux/mediatek/patches-5.15/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch b/target/linux/mediatek/patches-5.15/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch new file mode 100644 index 0000000000..8ce4638357 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch @@ -0,0 +1,203 @@ +From patchwork Thu May 28 06:16:48 2020 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Chuanjia Liu +X-Patchwork-Id: 11574797 +Return-Path: + +Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org + [172.30.200.123]) + by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30A5E1392 + for ; + Thu, 28 May 2020 06:29:05 +0000 (UTC) +Received: from bombadil.infradead.org (bombadil.infradead.org + [198.137.202.133]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by mail.kernel.org (Postfix) with ESMTPS id 08B6320721 + for ; + Thu, 28 May 2020 06:29:05 +0000 (UTC) +Authentication-Results: mail.kernel.org; + dkim=pass (2048-bit key) header.d=lists.infradead.org + header.i=@lists.infradead.org header.b="auhxDafY"; + dkim=fail reason="signature verification failed" (1024-bit key) + header.d=mediatek.com header.i=@mediatek.com header.b="Kj09Arxb" +DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 08B6320721 +Authentication-Results: mail.kernel.org; + dmarc=fail (p=none dis=none) header.from=mediatek.com +Authentication-Results: mail.kernel.org; + spf=none + smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=lists.infradead.org; s=bombadil.20170209; h=Sender: + Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: + List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: + Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: + Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: + List-Owner; bh=+QPxF1vlOH7StIZYuXJa3V40x8QVDxCLF9AFXHblB9M=; b=auhxDafYBeaUZO + aYp2KVO8Aie0v4tYtRwBon7hF+x55JwD78SAxQR2RsSvrlOo9cMYYby+ToUWflVUWQ60FapAl+w+l + nkEjIOrLBErHwxNOcsD8T5kjyCBMqlz4OMAQYUDNJ3fSugRlGhOtxkjCGd9ebB8N2Rvu6/U8P1A9n + P15mEQoc+RLonR1+9mBgwTEXErjsraxkimTD4Txsp4IvMs3UdsMkP+r3OT5S/p+Uj6O9ES0h7xIon + aL79KaVqRLHrfZxnrVwuGiecAiTp8qLy9clHuJU32NA6ZcXH1OnWipKApgp8Ck7ys80WPKaMrat9B + XuskJ63w13DZAbCVvuGQ==; +Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) + id 1jeC2J-00014n-M9; Thu, 28 May 2020 06:29:03 +0000 +Received: from mailgw02.mediatek.com ([216.200.240.185]) + by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) + id 1jeC2H-00013t-Li; Thu, 28 May 2020 06:29:03 +0000 +X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527 +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=mediatek.com; + s=dk; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; + bh=CIwcBFK1x0LbOjDt1BG6/knHFxDHRiqj8ov/jWEZDBY=; + b=Kj09ArxbnLVTc9bpaVPT3jQrIVjhL87sSYyVF9dFypS976k78Ce9gZd0f4K3zAZbYZHYoQtuyOQ9TOeufQfgD+Cr+j5VR7pTdO2E1iXHFs/eQAz5gAjvjlK01z1JiunrLnn9dvIr6c1gEkjQHny0VpuZ1duxx79jwYusg/Nw6Wc=; +X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527 +Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by + mailgw02.mediatek.com + (envelope-from ) + (musrelay.mediatek.com ESMTP with TLS) + with ESMTP id 899663677; Wed, 27 May 2020 22:29:21 -0800 +Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by + MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id + 15.0.1497.2; Wed, 27 May 2020 23:18:50 -0700 +Received: from mtkcas07.mediatek.inc (172.21.101.84) by + mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id + 15.0.1497.2; Thu, 28 May 2020 14:18:54 +0800 +Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc + (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend + Transport; Thu, 28 May 2020 14:18:52 +0800 +From: +To: , , +Subject: [PATCH v2 4/4] ARM: dts: mediatek: Update mt7629 PCIe node +Date: Thu, 28 May 2020 14:16:48 +0800 +Message-ID: <20200528061648.32078-5-chuanjia.liu@mediatek.com> +X-Mailer: git-send-email 2.18.0 +In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com> +References: <20200528061648.32078-1-chuanjia.liu@mediatek.com> +MIME-Version: 1.0 +X-MTK: N +X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 +X-CRM114-CacheID: sfid-20200527_232901_719172_E5A99C62 +X-CRM114-Status: GOOD ( 11.61 ) +X-Spam-Score: -0.2 (/) +X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: + Content analysis details: (-0.2 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -0.0 SPF_PASS SPF: sender matches SPF record + 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record + 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64 + encoding + -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from + author's domain + 0.1 DKIM_SIGNED Message has a DKIM or DK signature, + not necessarily + valid + -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature + -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from + envelope-from domain + 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay + lines +X-BeenThere: linux-mediatek@lists.infradead.org +X-Mailman-Version: 2.1.29 +Precedence: list +List-Id: +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com, + srv_heupstream@mediatek.com, "chuanjia.liu" , + linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, + jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org, + yong.wu@mediatek.com, bhelgaas@google.com, + linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk +Sender: "Linux-mediatek" +Errors-To: + linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org + +From: "chuanjia.liu" + +Remove unused property and add pciecfg node. + +Signed-off-by: chuanjia.liu +--- + arch/arm/boot/dts/mt7629-rfb.dts | 3 ++- + arch/arm/boot/dts/mt7629.dtsi | 23 +++++++++++++---------- + 2 files changed, 15 insertions(+), 11 deletions(-) + +--- a/arch/arm/boot/dts/mt7629-rfb.dts ++++ b/arch/arm/boot/dts/mt7629-rfb.dts +@@ -149,9 +149,10 @@ + }; + }; + +-&pcie { ++&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; ++ status = "okay"; + }; + + &pciephy1 { +--- a/arch/arm/boot/dts/mt7629.dtsi ++++ b/arch/arm/boot/dts/mt7629.dtsi +@@ -377,16 +377,21 @@ + #reset-cells = <1>; + }; + +- pcie: pcie@1a140000 { ++ pciecfg: pciecfg@1a140000 { ++ compatible = "mediatek,mt7629-pciecfg", "syscon"; ++ reg = <0x1a140000 0x1000>; ++ }; ++ ++ pcie1: pcie@1a145000 { + compatible = "mediatek,mt7629-pcie"; + device_type = "pci"; +- reg = <0x1a140000 0x1000>, +- <0x1a145000 0x1000>; +- reg-names = "subsys","port1"; ++ reg = <0x1a145000 0x1000>; ++ reg-names = "port1"; ++ mediatek,pcie-cfg = <&pciecfg>; + #address-cells = <3>; + #size-cells = <2>; +- interrupts = , +- ; ++ interrupts = ; ++ interrupt-names = "pcie_irq"; + clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, + <&pciesys CLK_PCIE_P0_AHB_EN>, + <&pciesys CLK_PCIE_P1_AUX_EN>, +@@ -407,21 +412,19 @@ + power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; + bus-range = <0x00 0xff>; + ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>; ++ status = "disabled"; + +- pcie1: pcie@1,0 { +- device_type = "pci"; ++ slot1: pcie@1,0 { + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; +- num-lanes = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc1 0>, + <0 0 0 2 &pcie_intc1 1>, + <0 0 0 3 &pcie_intc1 2>, + <0 0 0 4 &pcie_intc1 3>; +- + pcie_intc1: interrupt-controller { + interrupt-controller; + #address-cells = <0>; diff --git a/target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch b/target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch new file mode 100644 index 0000000000..2bebfddf5c --- /dev/null +++ b/target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Fri, 4 Sep 2020 18:33:27 +0200 +Subject: [PATCH] pcie-mediatek: fix clearing interrupt status + +Clearing the status needs to happen after running the handler, otherwise +we will get an extra spurious interrupt after the cause has been cleared + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -614,9 +614,9 @@ static void mtk_pcie_intr_handler(struct + if (status & INTX_MASK) { + for_each_set_bit_from(bit, &status, PCI_NUM_INTX + INTX_SHIFT) { + /* Clear the INTx */ +- writel(1 << bit, port->base + PCIE_INT_STATUS); + generic_handle_domain_irq(port->irq_domain, + bit - INTX_SHIFT); ++ writel(1 << bit, port->base + PCIE_INT_STATUS); + } + } + diff --git a/target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch b/target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch new file mode 100644 index 0000000000..da33aaa72f --- /dev/null +++ b/target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch @@ -0,0 +1,53 @@ +From c6af53f038aa32cec12e8a305ba07c7ef168f1b0 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 4 Jan 2022 12:07:00 +0000 +Subject: [PATCH 2/3] net: mdio: add helpers to extract clause 45 regad and + devad fields + +Add a couple of helpers and definitions to extract the clause 45 regad +and devad fields from the regnum passed into MDIO drivers. + +Tested-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + include/linux/mdio.h | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -7,6 +7,7 @@ + #define __LINUX_MDIO_H__ + + #include ++#include + #include + + /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit +@@ -14,6 +15,7 @@ + */ + #define MII_ADDR_C45 (1<<30) + #define MII_DEVADDR_C45_SHIFT 16 ++#define MII_DEVADDR_C45_MASK GENMASK(20, 16) + #define MII_REGADDR_C45_MASK GENMASK(15, 0) + + struct gpio_desc; +@@ -355,6 +357,16 @@ static inline u32 mdiobus_c45_addr(int d + return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum; + } + ++static inline u16 mdiobus_c45_regad(u32 regnum) ++{ ++ return FIELD_GET(MII_REGADDR_C45_MASK, regnum); ++} ++ ++static inline u16 mdiobus_c45_devad(u32 regnum) ++{ ++ return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); ++} ++ + static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, + u16 regnum) + { diff --git a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch new file mode 100644 index 0000000000..289398ce3a --- /dev/null +++ b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch @@ -0,0 +1,128 @@ +From e2e7f6e29c99a1c6afc0e0aa4b9ea80302d28720 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 4 Jan 2022 12:07:46 +0000 +Subject: [PATCH 3/3] net: ethernet: mtk_eth_soc: implement Clause 45 MDIO + access + +Implement read and write access to IEEE 802.3 Clause 45 Ethernet +phy registers while making use of new mdiobus_c45_regad and +mdiobus_c45_devad helpers. + +Tested on the Ubiquiti UniFi 6 LR access point featuring +MediaTek MT7622BV WiSoC with Aquantia AQR112C. + +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 70 +++++++++++++++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + + 2 files changed, 60 insertions(+), 13 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -106,13 +106,35 @@ static int _mtk_mdio_write(struct mtk_et + if (ret < 0) + return ret; + +- mtk_w32(eth, PHY_IAC_ACCESS | +- PHY_IAC_START_C22 | +- PHY_IAC_CMD_WRITE | +- PHY_IAC_REG(phy_reg) | +- PHY_IAC_ADDR(phy_addr) | +- PHY_IAC_DATA(write_data), +- MTK_PHY_IAC); ++ if (phy_reg & MII_ADDR_C45) { ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C45 | ++ PHY_IAC_CMD_C45_ADDR | ++ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | ++ PHY_IAC_ADDR(phy_addr) | ++ PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)), ++ MTK_PHY_IAC); ++ ++ ret = mtk_mdio_busy_wait(eth); ++ if (ret < 0) ++ return ret; ++ ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C45 | ++ PHY_IAC_CMD_WRITE | ++ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | ++ PHY_IAC_ADDR(phy_addr) | ++ PHY_IAC_DATA(write_data), ++ MTK_PHY_IAC); ++ } else { ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C22 | ++ PHY_IAC_CMD_WRITE | ++ PHY_IAC_REG(phy_reg) | ++ PHY_IAC_ADDR(phy_addr) | ++ PHY_IAC_DATA(write_data), ++ MTK_PHY_IAC); ++ } + + ret = mtk_mdio_busy_wait(eth); + if (ret < 0) +@@ -129,12 +151,33 @@ static int _mtk_mdio_read(struct mtk_eth + if (ret < 0) + return ret; + +- mtk_w32(eth, PHY_IAC_ACCESS | +- PHY_IAC_START_C22 | +- PHY_IAC_CMD_C22_READ | +- PHY_IAC_REG(phy_reg) | +- PHY_IAC_ADDR(phy_addr), +- MTK_PHY_IAC); ++ if (phy_reg & MII_ADDR_C45) { ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C45 | ++ PHY_IAC_CMD_C45_ADDR | ++ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | ++ PHY_IAC_ADDR(phy_addr) | ++ PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)), ++ MTK_PHY_IAC); ++ ++ ret = mtk_mdio_busy_wait(eth); ++ if (ret < 0) ++ return ret; ++ ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C45 | ++ PHY_IAC_CMD_C45_READ | ++ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | ++ PHY_IAC_ADDR(phy_addr), ++ MTK_PHY_IAC); ++ } else { ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C22 | ++ PHY_IAC_CMD_C22_READ | ++ PHY_IAC_REG(phy_reg) | ++ PHY_IAC_ADDR(phy_addr), ++ MTK_PHY_IAC); ++ } + + ret = mtk_mdio_busy_wait(eth); + if (ret < 0) +@@ -593,6 +636,7 @@ static int mtk_mdio_init(struct mtk_eth + eth->mii_bus->name = "mdio"; + eth->mii_bus->read = mtk_mdio_read; + eth->mii_bus->write = mtk_mdio_write; ++ eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45; + eth->mii_bus->priv = eth; + eth->mii_bus->parent = eth->dev; + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -349,9 +349,12 @@ + #define PHY_IAC_ADDR_MASK GENMASK(24, 20) + #define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x)) + #define PHY_IAC_CMD_MASK GENMASK(19, 18) ++#define PHY_IAC_CMD_C45_ADDR FIELD_PREP(PHY_IAC_CMD_MASK, 0) + #define PHY_IAC_CMD_WRITE FIELD_PREP(PHY_IAC_CMD_MASK, 1) + #define PHY_IAC_CMD_C22_READ FIELD_PREP(PHY_IAC_CMD_MASK, 2) ++#define PHY_IAC_CMD_C45_READ FIELD_PREP(PHY_IAC_CMD_MASK, 3) + #define PHY_IAC_START_MASK GENMASK(17, 16) ++#define PHY_IAC_START_C45 FIELD_PREP(PHY_IAC_START_MASK, 0) + #define PHY_IAC_START_C22 FIELD_PREP(PHY_IAC_START_MASK, 1) + #define PHY_IAC_DATA_MASK GENMASK(15, 0) + #define PHY_IAC_DATA(x) FIELD_PREP(PHY_IAC_DATA_MASK, (x)) diff --git a/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch b/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch new file mode 100644 index 0000000000..e9d4188a45 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -577,6 +577,7 @@ static void mtk_validate(struct phylink_ + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); ++ phylink_set(mask, 2500baseT_Full); + phylink_set(mask, 2500baseX_Full); + } + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) { diff --git a/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch new file mode 100644 index 0000000000..571a5f7d48 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch @@ -0,0 +1,82 @@ +From: Felix Fietkau +Date: Fri, 4 Sep 2020 18:42:42 +0200 +Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA + +It improves performance by eliminating the need for a cache flush for DMA on +attached devices + +Signed-off-by: Felix Fietkau +--- + +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -830,6 +830,9 @@ + bus-range = <0x00 0xff>; + ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; + status = "disabled"; ++ dma-coherent; ++ mediatek,hifsys = <&hifsys>; ++ mediatek,cci-control = <&cci_control2>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; +@@ -874,6 +877,9 @@ + bus-range = <0x00 0xff>; + ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; + status = "disabled"; ++ dma-coherent; ++ mediatek,hifsys = <&hifsys>; ++ mediatek,cci-control = <&cci_control2>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -139,6 +140,11 @@ + #define PCIE_LINK_STATUS_V2 0x804 + #define PCIE_PORT_LINKUP_V2 BIT(10) + ++/* DMA channel mapping */ ++#define HIFSYS_DMA_AG_MAP 0x008 ++#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0) ++#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1) ++ + struct mtk_pcie_port; + + /** +@@ -1053,6 +1059,27 @@ static int mtk_pcie_setup(struct mtk_pci + struct mtk_pcie_port *port, *tmp; + int err, slot; + ++ if (of_dma_is_coherent(node)) { ++ struct regmap *con; ++ u32 mask; ++ ++ con = syscon_regmap_lookup_by_phandle(node, ++ "mediatek,cci-control"); ++ /* enable CPU/bus coherency */ ++ if (!IS_ERR(con)) ++ regmap_write(con, 0, 3); ++ ++ con = syscon_regmap_lookup_by_phandle(node, ++ "mediatek,hifsys"); ++ if (IS_ERR(con)) { ++ dev_err(dev, "missing hifsys node\n"); ++ return PTR_ERR(con); ++ } ++ ++ mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1; ++ regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask); ++ } ++ + slot = of_get_pci_domain_nr(dev->of_node); + if (slot < 0) { + for_each_available_child_of_node(node, child) { diff --git a/target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch b/target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch new file mode 100644 index 0000000000..f9a5fdbd0d --- /dev/null +++ b/target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch @@ -0,0 +1,27 @@ +From: Jip de Beer +Date: Sun, 9 Jan 2022 13:14:04 +0100 +Subject: [PATCH] mediatek mt7622: fix 300mhz typo in dts + +The lowest frequency should be 300MHz, since that is the label +assigned to the OPP in the mt7622.dtsi device tree, while there is one +missing zero in the actual value. + +To be clear, the lowest frequency should be 300MHz instead of 30MHz. + +As mentioned @dangowrt on the OpenWrt forum there is no benefit in +leaving 30MHz as the lowest frequency. + +Signed-off-by: Jip de Beer +Signed-off-by: Fritz D. Ansel +--- +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -24,7 +24,7 @@ + compatible = "operating-points-v2"; + opp-shared; + opp-300000000 { +- opp-hz = /bits/ 64 <30000000>; ++ opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <950000>; + }; + diff --git a/target/linux/mediatek/patches-5.15/800-ubnt-ledbar-driver.patch b/target/linux/mediatek/patches-5.15/800-ubnt-ledbar-driver.patch new file mode 100644 index 0000000000..146e6ae2f5 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/800-ubnt-ledbar-driver.patch @@ -0,0 +1,29 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -876,6 +876,16 @@ source "drivers/leds/blink/Kconfig" + comment "Flash and Torch LED drivers" + source "drivers/leds/flash/Kconfig" + ++config LEDS_UBNT_LEDBAR ++ tristate "LED support for Ubiquiti UniFi 6 LR" ++ depends on LEDS_CLASS && I2C && OF ++ help ++ This option enables support for the Ubiquiti LEDBAR ++ LED driver. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called leds-ubnt-ledbar. ++ + comment "LED Triggers" + source "drivers/leds/trigger/Kconfig" + +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -87,6 +87,7 @@ obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds + obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o + obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o + obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o ++obj-$(CONFIG_LEDS_UBNT_LEDBAR) += leds-ubnt-ledbar.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o diff --git a/target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch new file mode 100644 index 0000000000..987513eb45 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch @@ -0,0 +1,65 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -308,7 +308,7 @@ + /* Attention: GPIO 90 is used to switch between PCIe@1,0 and + * SATA functions. i.e. output-high: PCIe, output-low: SATA + */ +- asm_sel { ++ asmsel: asm_sel { + gpio-hog; + gpios = <90 GPIO_ACTIVE_HIGH>; + output-high; +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-sata.dts +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ ++ ++#include ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; ++ ++ fragment@0 { ++ target = <&asmsel>; ++ __overlay__ { ++ gpios = <90 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&sata>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sata_phy>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-pcie1.dts +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ ++ ++#include ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; ++ ++ fragment@0 { ++ target = <&asmsel>; ++ __overlay__ { ++ gpios = <90 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; diff --git a/target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch new file mode 100644 index 0000000000..72211af588 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch @@ -0,0 +1,31 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -635,5 +635,28 @@ + }; + + &wmac { ++ mediatek,eeprom-data = <0x22760500 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x44000020 0x0 0x10002000 ++ 0x4400 0x4000000 0x0 0x0 ++ 0x200000b3 0x40b6c3c3 0x26000000 0x41c42600 ++ 0x41c4 0x26000000 0xc0c52600 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0xc6c6 ++ 0xc3c3c2c1 0xc300c3 0x818181 0x83c1c182 ++ 0x83838382 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x84002e00 0x90000087 0x8a000000 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0xb000009 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x0 ++ 0x0 0x0 0x0 0x7707>; ++ + status = "okay"; + }; From 1562e430d44fb474a9a1f03845d59855172aded4 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 27 Mar 2022 05:41:54 +0100 Subject: [PATCH 26/26] generic: 5.15: add more missing Kconfig symbols Add a bunch of missing new Kconfig symbols to generic/config-5.15. Signed-off-by: Daniel Golle --- target/linux/generic/config-5.15 | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 8dd2afc2fc..68addb1fca 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -1411,9 +1411,11 @@ CONFIG_DEVPORT=y # CONFIG_DLHL60D is not set # CONFIG_DLM is not set # CONFIG_DM9000 is not set +# CONFIG_DMABUF_DEBUG is not set # CONFIG_DMABUF_HEAPS is not set # CONFIG_DMABUF_MOVE_NOTIFY is not set # CONFIG_DMABUF_SELFTESTS is not set +# CONFIG_DMABUF_SYSFS_STATS is not set # CONFIG_DMADEVICES is not set # CONFIG_DMADEVICES_DEBUG is not set # CONFIG_DMARD06 is not set @@ -1480,6 +1482,7 @@ CONFIG_DQL=y # CONFIG_DRM_AMD_DC_HDCP is not set # CONFIG_DRM_AMD_DC_SI is not set # CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX7625 is not set # CONFIG_DRM_ANALOGIX_ANX78XX is not set # CONFIG_DRM_ARCPGU is not set # CONFIG_DRM_ARMADA is not set @@ -1487,6 +1490,7 @@ CONFIG_DQL=y # CONFIG_DRM_BOCHS is not set # CONFIG_DRM_CDNS_DSI is not set # CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set # CONFIG_DRM_CHRONTEL_CH7033 is not set # CONFIG_DRM_CIRRUS_QEMU is not set # CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set @@ -1504,6 +1508,7 @@ CONFIG_DQL=y # CONFIG_DRM_FSL_DCU is not set # CONFIG_DRM_GM12U320 is not set # CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_GUD is not set # CONFIG_DRM_HDLCD is not set # CONFIG_DRM_HISI_HIBMC is not set # CONFIG_DRM_HISI_KIRIN is not set @@ -1513,12 +1518,15 @@ CONFIG_DQL=y # CONFIG_DRM_I2C_NXP_TDA998X is not set # CONFIG_DRM_I2C_SIL164 is not set # CONFIG_DRM_I915 is not set +# CONFIG_DRM_ITE_IT66121 is not set # CONFIG_DRM_KOMEDA is not set # CONFIG_DRM_LEGACY is not set # CONFIG_DRM_LIB_RANDOM is not set # CONFIG_DRM_LIMA is not set # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set # CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set # CONFIG_DRM_LVDS_CODEC is not set # CONFIG_DRM_LVDS_ENCODER is not set # CONFIG_DRM_MALI_DISPLAY is not set @@ -1530,17 +1538,21 @@ CONFIG_DQL=y # CONFIG_DRM_NWL_MIPI_DSI is not set # CONFIG_DRM_NXP_PTN3460 is not set # CONFIG_DRM_OMAP is not set +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set # CONFIG_DRM_PANEL_ARM_VERSATILE is not set # CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set # CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set # CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_DSI_CM is not set # CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set # CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set # CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set # CONFIG_DRM_PANEL_ILITEK_IL9322 is not set # CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set # CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set # CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_KHADAS_TS050 is not set # CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set # CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set # CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829 is not set @@ -1550,6 +1562,7 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set # CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set # CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set # CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set @@ -1560,6 +1573,8 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set # CONFIG_DRM_PANEL_ROCKTECH_JH057N00900 is not set # CONFIG_DRM_PANEL_RONBO_RB070D30 is not set +# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set +# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set # CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set @@ -1567,6 +1582,7 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set # CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set # CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set # CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set @@ -1577,11 +1593,13 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set # CONFIG_DRM_PANEL_SONY_ACX424AKP is not set # CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_TDO_TL070WSH30 is not set # CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set # CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set # CONFIG_DRM_PANEL_TPO_TPG110 is not set # CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set # CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set # CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set # CONFIG_DRM_PANFROST is not set # CONFIG_DRM_PARADE_PS8622 is not set @@ -1596,6 +1614,7 @@ CONFIG_DQL=y # CONFIG_DRM_SII9234 is not set # CONFIG_DRM_SIL_SII8620 is not set # CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_SIMPLEDRM is not set # CONFIG_DRM_STI is not set # CONFIG_DRM_STM is not set # CONFIG_DRM_SUN4I is not set @@ -1603,6 +1622,7 @@ CONFIG_DQL=y # CONFIG_DRM_TIDSS is not set # CONFIG_DRM_TILCDC is not set # CONFIG_DRM_TINYDRM is not set +# CONFIG_DRM_TI_SN65DSI83 is not set # CONFIG_DRM_TI_SN65DSI86 is not set # CONFIG_DRM_TI_TFP410 is not set # CONFIG_DRM_TI_TPD12S015 is not set @@ -1852,6 +1872,7 @@ CONFIG_EXT4_USE_FOR_EXT2=y # CONFIG_EXTCON_QCOM_SPMI_MISC is not set # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USBC_TUSB320 is not set # CONFIG_EXTCON_USB_GPIO is not set CONFIG_EXTRA_FIRMWARE="" CONFIG_EXTRA_TARGETS="" @@ -3768,6 +3789,7 @@ CONFIG_MTD_SPLIT_SUPPORT=y # CONFIG_MTD_UBI_GLUEBI is not set # CONFIG_MTD_UIMAGE_SPLIT is not set # CONFIG_MTD_VIRT_CONCAT is not set +# CONFIG_MTD_NAND_ECC_SW_HAMMING is not set # CONFIG_MTD_NAND_MTK_BMT is not set # CONFIG_MTK_DEVAPC is not set # CONFIG_MTK_MMC is not set @@ -4890,6 +4912,7 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_MPQ7920 is not set # CONFIG_REGULATOR_MT6311 is not set # CONFIG_REGULATOR_MT6315 is not set +# CONFIG_REGULATOR_MT6359 is not set # CONFIG_REGULATOR_PCA9450 is not set # CONFIG_REGULATOR_PF8X00 is not set # CONFIG_REGULATOR_PFUZE100 is not set @@ -5289,6 +5312,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_APDS990X is not set # CONFIG_SENSORS_APPLESMC is not set +# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set # CONFIG_SENSORS_AS370 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ASC7621 is not set @@ -5412,6 +5436,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_NPCM7XX is not set # CONFIG_SENSORS_NSA320 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NZXT_KRAKEN2 is not set # CONFIG_SENSORS_OCC_P8_I2C is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -6436,7 +6461,9 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_HP600 is not set # CONFIG_TOUCHSCREEN_HP7XX is not set # CONFIG_TOUCHSCREEN_HTCPEN is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set # CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_IPAQ_MICRO is not set @@ -6447,6 +6474,7 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_MC13783 is not set # CONFIG_TOUCHSCREEN_MCS5000 is not set # CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MSG2638 is not set # CONFIG_TOUCHSCREEN_MIGOR is not set # CONFIG_TOUCHSCREEN_MK712 is not set # CONFIG_TOUCHSCREEN_MMS114 is not set