From fd71ef34b75c81646d17d21d80dc3a5b5e2e6bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 7 Oct 2021 11:29:52 +0200 Subject: [PATCH 01/59] kernel: backport bgmac upstream commits from 5.15 / for 5.16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- ...ndle-deferred-probe-error-due-to-ma.patch} | 3 +- ...platform-handle-mac-address-deferral.patch | 36 ++++++++ ...-0001-net-bgmac-improve-handling-PHY.patch | 84 +++++++++++++++++++ ...t-bgmac-support-MDIO-described-in-DT.patch | 54 ++++++++++++ .../hack-5.10/773-bgmac-add-srab-switch.patch | 2 +- 5 files changed, 177 insertions(+), 2 deletions(-) rename target/linux/{bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch => generic/backport-5.10/783-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch} (95%) create mode 100644 target/linux/generic/backport-5.10/783-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch create mode 100644 target/linux/generic/backport-5.10/784-v5.16-0001-net-bgmac-improve-handling-PHY.patch create mode 100644 target/linux/generic/backport-5.10/784-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch diff --git a/target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch b/target/linux/generic/backport-5.10/783-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch similarity index 95% rename from target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch rename to target/linux/generic/backport-5.10/783-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch index 628d7cddf2..6e7f20634f 100644 --- a/target/linux/bcm53xx/patches-5.10/099-net-bcma-handle-deferred-probe.patch +++ b/target/linux/generic/backport-5.10/783-v5.15-0001-net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch @@ -1,7 +1,8 @@ From 029497e66bdc762e001880e4c85a91f35a54b1e2 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 19 Sep 2021 13:57:25 +0200 -Subject: net: bgmac-bcma: handle deferred probe error due to mac-address +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 diff --git a/target/linux/generic/backport-5.10/783-v5.15-0002-net-bgmac-platform-handle-mac-address-deferral.patch b/target/linux/generic/backport-5.10/783-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.10/783-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.10/784-v5.16-0001-net-bgmac-improve-handling-PHY.patch b/target/linux/generic/backport-5.10/784-v5.16-0001-net-bgmac-improve-handling-PHY.patch new file mode 100644 index 0000000000..6788a2ec35 --- /dev/null +++ b/target/linux/generic/backport-5.10/784-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.10/784-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch b/target/linux/generic/backport-5.10/784-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.10/784-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/hack-5.10/773-bgmac-add-srab-switch.patch b/target/linux/generic/hack-5.10/773-bgmac-add-srab-switch.patch index 5a7e38516c..bc377bdd82 100644 --- a/target/linux/generic/hack-5.10/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/hack-5.10/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; From b2cfed48f62622efa8577372942bbc268afe4677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 4 Oct 2021 07:12:36 +0200 Subject: [PATCH 02/59] Revert "swconfig: fix Broadcom b53 support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8f9cd1af0f9c325a902dbd0e79e12015372e6bb0. That commit was meant to add a single EXPORT_SYMBOL_GPL() but it actually also added few .of_match_table-s. One commit should handle one thing and should not introduce unrelated changes. Regarding actual changes: 1. EXPORT_SYMBOL_GPL is not required as we don't build swconfig drivers as modules. 2. PHY drivers must not have .of_match_table. That is allowed for MDIO drivers. This could work for some time (although is didn't for me on bcm53xx) but does not with kernel 5.10. It causes a soft lockup and upstream developers confirmed it's an unsupported design. Link: https://lore.kernel.org/netdev/2b1dc053-8c9a-e3e4-b450-eecdfca3fe16@gmail.com/t/#mf80e472f35ee23f7a75cbf5b1e101a17ab3a64a3 Cc: Tobias Schramm Signed-off-by: Rafał Miłecki --- .../files/drivers/net/phy/b53/b53_mdio.c | 32 ------------------- .../generic/files/drivers/net/phy/swconfig.c | 1 - 2 files changed, 33 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c b/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c index 98cdbffe73..6ec23a49a3 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c @@ -361,26 +361,6 @@ static int b53_phy_read_status(struct phy_device *phydev) return 0; } -static const struct of_device_id b53_of_match_1[] = { - { .compatible = "brcm,bcm5325" }, - { .compatible = "brcm,bcm5395" }, - { .compatible = "brcm,bcm5397" }, - { .compatible = "brcm,bcm5398" }, - { /* sentinel */ }, -}; - -static const struct of_device_id b53_of_match_2[] = { - { .compatible = "brcm,bcm53115" }, - { .compatible = "brcm,bcm53125" }, - { .compatible = "brcm,bcm53128" }, - { /* sentinel */ }, -}; - -static const struct of_device_id b53_of_match_3[] = { - { .compatible = "brcm,bcm5365" }, - { /* sentinel */ }, -}; - /* BCM5325, BCM539x */ static struct phy_driver b53_phy_driver_id1 = { .phy_id = 0x0143bc00, @@ -392,10 +372,6 @@ static struct phy_driver b53_phy_driver_id1 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, - .mdiodrv.driver = { - .name = "bcm539x", - .of_match_table = b53_of_match_1, - }, }; /* BCM53125, BCM53128 */ @@ -409,10 +385,6 @@ static struct phy_driver b53_phy_driver_id2 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, - .mdiodrv.driver = { - .name = "bcm531xx", - .of_match_table = b53_of_match_2, - }, }; /* BCM5365 */ @@ -426,10 +398,6 @@ static struct phy_driver b53_phy_driver_id3 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, - .mdiodrv.driver = { - .name = "bcm5365", - .of_match_table = b53_of_match_3, - }, }; int __init b53_phy_driver_register(void) diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c index a734e57608..f506daaf91 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -1222,7 +1222,6 @@ switch_generic_set_link(struct switch_dev *dev, int port, return 0; } -EXPORT_SYMBOL_GPL(switch_generic_set_link); static int __init swconfig_init(void) From 2e4193f3cfa23f6c85f479ef10bf779406538f3c Mon Sep 17 00:00:00 2001 From: Matthew Hagan Date: Sun, 26 Sep 2021 11:23:27 +0000 Subject: [PATCH 03/59] kernel: 5.10: dsa: don't set skb->offload_fwd_mark when not offloading bridge Add Vladimir Oltean's "net: dsa: don't set skb->offload_fwd_mark when not offloading the bridge" This covers cases where packets received by an upstream switch must be forwarded back on the same port, which skb->offload_fwd_mark normally prevents. Signed-off-by: Matthew Hagan --- ...t-skb-offload_fwd_mark-when-not-offl.patch | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 target/linux/generic/backport-5.10/794-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch diff --git a/target/linux/generic/backport-5.10/794-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch b/target/linux/generic/backport-5.10/794-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.10/794-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; + } From e4e410733f3b0cad09d3a235eec0b04f4068c331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 7 Oct 2021 15:00:52 +0200 Subject: [PATCH 04/59] kernel: export switch_generic_set_link() symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes: ERROR: "switch_generic_set_link" [drivers/net/phy/b53/b53_common.ko] undefined! At some point all packages for swconfig drivers were dropped and targets were meant to have them built into kernels. It seems b53 (re-)gained its kmod-switch-bcm53xx however and b53 needs to be built as module. Fixes: b2cfed48f626 ("Revert "swconfig: fix Broadcom b53 support"") Signed-off-by: Rafał Miłecki --- target/linux/generic/files/drivers/net/phy/swconfig.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c index f506daaf91..a734e57608 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -1222,6 +1222,7 @@ switch_generic_set_link(struct switch_dev *dev, int port, return 0; } +EXPORT_SYMBOL_GPL(switch_generic_set_link); static int __init swconfig_init(void) From c2222f74c8eff592032473ab2d29d5e8febace63 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 4 Oct 2021 18:48:30 -0700 Subject: [PATCH 05/59] tools/meson: update to 0.59.2 Update install procedure based on upstream feedback. Normally, meson is to be installed with pip. But as pip is not mandated by the build system, it cannot be used. Upstream provides a nice script to pack meson automatically. Moved src/ to files/. No need to copy to BUILD_DIR. Signed-off-by: Rosen Penev --- include/meson.mk | 3 +-- tools/meson/Makefile | 9 ++++++--- tools/meson/{src => files}/openwrt-cross.txt.in | 0 tools/meson/{src => files}/openwrt-native.txt.in | 0 4 files changed, 7 insertions(+), 5 deletions(-) rename tools/meson/{src => files}/openwrt-cross.txt.in (100%) rename tools/meson/{src => files}/openwrt-native.txt.in (100%) diff --git a/include/meson.mk b/include/meson.mk index 01d0ce0280..9862f0e662 100644 --- a/include/meson.mk +++ b/include/meson.mk @@ -19,7 +19,6 @@ # # Host packages are built in the same fashion, just use these vars instead: # -# HOST_BUILD_DEPENDS:=meson/host # MESON_HOST_ARGS+=-Dfoo -Dbar=baz # MESON_HOST_VARS+=FOO=bar @@ -57,7 +56,7 @@ MESON_CPU:="$(CPU_TYPE)$(if $(CPU_SUBTYPE),+$(CPU_SUBTYPE))" endif define Meson - $(2) $(STAGING_DIR_HOST)/bin/$(PYTHON) $(MESON_DIR)/meson.py $(1) + $(2) $(STAGING_DIR_HOST)/bin/meson $(1) endef define Meson/CreateNativeFile diff --git a/tools/meson/Makefile b/tools/meson/Makefile index bae89654a5..0cf0efba47 100644 --- a/tools/meson/Makefile +++ b/tools/meson/Makefile @@ -1,11 +1,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=meson -PKG_VERSION:=0.59.1 +PKG_VERSION:=0.59.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/mesonbuild/meson/releases/download/$(PKG_VERSION) -PKG_HASH:=db586a451650d46bbe10984a87b79d9bcdc1caebf38d8e189f8848f8d502356d +PKG_HASH:=13dee549a7ba758b7e33ce7719f28d1d337a98d10d378a4779ccc996f5a2fc49 PKG_MAINTAINER:=Andre Heider PKG_LICENSE:=Apache-2.0 @@ -20,8 +20,11 @@ define Host/Compile endef define Host/Install + $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin + $(HOST_BUILD_DIR)/packaging/create_zipapp.py $(HOST_BUILD_DIR) --interpreter $(STAGING_DIR_HOST)/bin/$(PYTHON) --outfile $(STAGING_DIR_HOST)/bin/meson $(INSTALL_DIR) $(STAGING_DIR_HOST)/lib/meson - $(CP) $(HOST_BUILD_DIR)/* $(STAGING_DIR_HOST)/lib/meson/ + $(INSTALL_CONF) files/openwrt-cross.txt.in $(STAGING_DIR_HOST)/lib/meson/ + $(INSTALL_CONF) files/openwrt-native.txt.in $(STAGING_DIR_HOST)/lib/meson/ endef define Host/Clean diff --git a/tools/meson/src/openwrt-cross.txt.in b/tools/meson/files/openwrt-cross.txt.in similarity index 100% rename from tools/meson/src/openwrt-cross.txt.in rename to tools/meson/files/openwrt-cross.txt.in diff --git a/tools/meson/src/openwrt-native.txt.in b/tools/meson/files/openwrt-native.txt.in similarity index 100% rename from tools/meson/src/openwrt-native.txt.in rename to tools/meson/files/openwrt-native.txt.in From 72bfc35f8fc5ade55f4c66cb8d171b93e1358b15 Mon Sep 17 00:00:00 2001 From: Ronny Kotzschmar Date: Thu, 7 Oct 2021 15:28:13 +0200 Subject: [PATCH 06/59] umdns: add missing syscalls to seccomp filter The 'mmap', 'mmap2', 'munmap' syscalls are missing. Found with 'utrace /usr/sbin/umdns'. Signed-off-by: Ronny Kotzschmar --- package/network/services/umdns/files/umdns.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package/network/services/umdns/files/umdns.json b/package/network/services/umdns/files/umdns.json index 5533b7c512..aa9f49fa32 100644 --- a/package/network/services/umdns/files/umdns.json +++ b/package/network/services/umdns/files/umdns.json @@ -20,6 +20,9 @@ "fstat", "getsockname", "ioctl", + "mmap", + "mmap2", + "munmap", "open", "openat", "pipe", From 44f694ba1bca1417d24e851c637c284f9f78c06d Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 21 Oct 2020 15:04:17 +0100 Subject: [PATCH 07/59] build: select procd-ujail if !SMALL_FLASH Add procd-ujail to DEFAULT_PACKAGES if not building for space-constraint (FEATURES:=small_flash) targets. Signed-off-by: Daniel Golle --- include/target.mk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/target.mk b/include/target.mk index 7526224972..eac2d164c3 100644 --- a/include/target.mk +++ b/include/target.mk @@ -33,6 +33,11 @@ else DEFAULT_PACKAGES+=busybox procd endif +# include ujail on systems with enough storage +ifeq ($(CONFIG_SMALL_FLASH),) +DEFAULT_PACKAGES+=procd-ujail +endif + # For the basic set DEFAULT_PACKAGES.basic:= # For nas targets From a7f794cd2aa104fdbd4c6e38f9b76373bf9b96e1 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 6 Nov 2020 02:10:28 +0000 Subject: [PATCH 08/59] build: select procd-seccomp if kernel support is present Install ld-preload hooks allowing to add seccomp filters for arbitrary services if kernel support for seccomp is present. Signed-off-by: Daniel Golle --- include/target.mk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/target.mk b/include/target.mk index eac2d164c3..03192d3ebe 100644 --- a/include/target.mk +++ b/include/target.mk @@ -38,6 +38,11 @@ ifeq ($(CONFIG_SMALL_FLASH),) DEFAULT_PACKAGES+=procd-ujail endif +# include seccomp ld-preload hooks if kernel supports it +ifneq ($(CONFIG_KERNEL_SECCOMP),) +DEFAULT_PACKAGES+=procd-seccomp +endif + # For the basic set DEFAULT_PACKAGES.basic:= # For nas targets From f887c93be7edf87b2af2b2db3481473e0f6df832 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 6 Oct 2021 19:28:08 -1000 Subject: [PATCH 09/59] config: pack toolchain per default on buildbots The toolchain can be used for accelerated CI builds. This commit enabled the packing of it by default on buildbots. Signed-off-by: Paul Spooren --- target/toolchain/Config.in | 1 + 1 file changed, 1 insertion(+) diff --git a/target/toolchain/Config.in b/target/toolchain/Config.in index 5a6ecefebb..02c486b320 100644 --- a/target/toolchain/Config.in +++ b/target/toolchain/Config.in @@ -1,6 +1,7 @@ config MAKE_TOOLCHAIN bool "Package the OpenWrt-based Toolchain" depends on !EXTERNAL_TOOLCHAIN + default BUILDBOT help Package the created toolchain as a tarball under the bin/ directory as OpenWrt-Toolchain-$(BOARD)-for-$(ARCH)$(ARCH_SUFFIX)-gcc-$(GCCV)$(DIR_SUFFIX). From e88ac0bbd1099cc7844ad0efe891b9fb5f0e34e2 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Sun, 5 Sep 2021 15:13:10 +0200 Subject: [PATCH 10/59] realtek: Correct TX ring size in ethernet driver This enlarges the size of the TX ring buffer, which prevents warnings when the buffer runs out of space. Signed-off-by: Birger Koblitz --- .../realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index ce3574b902..7c3d7c544b 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -37,8 +37,7 @@ extern struct rtl83xx_soc_info soc_info; #define MAX_RXLEN 100 #define MAX_ENTRIES (200 * 8) #define TXRINGS 2 -// BUG: TXRINGLEN can be 160 -#define TXRINGLEN 16 +#define TXRINGLEN 160 #define NOTIFY_EVENTS 10 #define NOTIFY_BLOCKS 10 #define TX_EN 0x8 From ca04e2dfd02a711cb0b3ce401bd120bd3da3b973 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Sun, 5 Sep 2021 18:38:43 +0200 Subject: [PATCH 11/59] realtek: Remove storm control and attack warnings Remove the storm control and attack warnings from the IRQ handler of the Ethernet driver. There was no consequence to the detection and the kernel can also handle at least the attacks itself. Signed-off-by: Birger Koblitz --- .../drivers/net/ethernet/rtl838x_eth.c | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index 7c3d7c544b..f91126deb5 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -49,11 +49,6 @@ extern struct rtl83xx_soc_info soc_info; #define RING_BUFFER 1600 -#define RTL838X_STORM_CTRL_PORT_BC_EXCEED (0x470C) -#define RTL838X_STORM_CTRL_PORT_MC_EXCEED (0x4710) -#define RTL838X_STORM_CTRL_PORT_UC_EXCEED (0x4714) -#define RTL838X_ATK_PRVNT_STS (0x5B1C) - struct p_hdr { uint8_t *buf; uint16_t reserved; @@ -407,29 +402,9 @@ static irqreturn_t rtl83xx_net_irq(int irq, void *dev_id) struct net_device *dev = dev_id; struct rtl838x_eth_priv *priv = netdev_priv(dev); u32 status = sw_r32(priv->r->dma_if_intr_sts); - bool triggered = false; - u32 atk = sw_r32(RTL838X_ATK_PRVNT_STS); int i; - u32 storm_uc = sw_r32(RTL838X_STORM_CTRL_PORT_UC_EXCEED); - u32 storm_mc = sw_r32(RTL838X_STORM_CTRL_PORT_MC_EXCEED); - u32 storm_bc = sw_r32(RTL838X_STORM_CTRL_PORT_BC_EXCEED); pr_debug("IRQ: %08x\n", status); - if (storm_uc || storm_mc || storm_bc) { - pr_warn("Storm control UC: %08x, MC: %08x, BC: %08x\n", - storm_uc, storm_mc, storm_bc); - - sw_w32(storm_uc, RTL838X_STORM_CTRL_PORT_UC_EXCEED); - sw_w32(storm_mc, RTL838X_STORM_CTRL_PORT_MC_EXCEED); - sw_w32(storm_bc, RTL838X_STORM_CTRL_PORT_BC_EXCEED); - - triggered = true; - } - - if (atk) { - pr_debug("Attack prevention triggered: %08x\n", atk); - sw_w32(atk, RTL838X_ATK_PRVNT_STS); - } spin_lock(&priv->lock); /* Ignore TX interrupt */ From 9eab76c84e311605e8cc197a0bc4bd53340678c3 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Sun, 5 Sep 2021 20:03:59 +0200 Subject: [PATCH 12/59] realtek: Improve TX CPU-Tag usage On RTL83xx enable learning of the MAC source address of the CPU port from outgoing packets. Add documentation on bit fields. On RTL93xx enable port-mask usage and the use of internal priority, these SoCs automatically learn the MAC. Signed-off-by: Birger Koblitz --- .../drivers/net/ethernet/rtl838x_eth.c | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index f91126deb5..4711efbcdc 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -89,14 +89,14 @@ struct notify_b { u32 reserved2[8]; }; -void rtl838x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +static void rtl838x_create_tx_header(struct p_hdr *h, int dest_port, int prio) { prio &= 0x7; if (dest_port > 0) { // cpu_tag[0] is reserved on the RTL83XX SoCs - h->cpu_tag[1] = 0x0400; - h->cpu_tag[2] = 0x0200; + h->cpu_tag[1] = 0x0401; // BIT 10: RTL8380_CPU_TAG, BIT0: L2LEARNING on + h->cpu_tag[2] = 0x0200; // Set only AS_DPM, to enable DPM settings below h->cpu_tag[3] = 0x0000; h->cpu_tag[4] = BIT(dest_port) >> 16; h->cpu_tag[5] = BIT(dest_port) & 0xffff; @@ -106,14 +106,15 @@ void rtl838x_create_tx_header(struct p_hdr *h, int dest_port, int prio) } } -void rtl839x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +static void rtl839x_create_tx_header(struct p_hdr *h, int dest_port, int prio) { prio &= 0x7; if (dest_port > 0) { // cpu_tag[0] is reserved on the RTL83XX SoCs - h->cpu_tag[1] = 0x0100; + h->cpu_tag[1] = 0x0100; // RTL8390_CPU_TAG marker h->cpu_tag[2] = h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0; + // h->cpu_tag[1] |= BIT(1) | BIT(0); // Bypass filter 1/2 if (dest_port >= 32) { dest_port -= 32; h->cpu_tag[2] = BIT(dest_port) >> 16; @@ -122,35 +123,43 @@ void rtl839x_create_tx_header(struct p_hdr *h, int dest_port, int prio) h->cpu_tag[4] = BIT(dest_port) >> 16; h->cpu_tag[5] = BIT(dest_port) & 0xffff; } - h->cpu_tag[6] |= BIT(21); // Enable destination port mask use + h->cpu_tag[2] |= BIT(20); // Enable destination port mask use + h->cpu_tag[2] |= BIT(23); // Enable L2 Learning // Set internal priority and AS_PRIO if (prio >= 0) h->cpu_tag[1] |= prio | BIT(3); } } -void rtl930x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +static void rtl930x_create_tx_header(struct p_hdr *h, int dest_port, int prio) { - h->cpu_tag[0] = 0x8000; - h->cpu_tag[1] = 0; // TODO: Fill port and prio - h->cpu_tag[2] = 0; + h->cpu_tag[0] = 0x8000; // CPU tag marker + h->cpu_tag[1] = h->cpu_tag[2] = 0; + if (prio >= 0) + h->cpu_tag[2] = BIT(13) | prio << 8; // Enable and set Priority Queue h->cpu_tag[3] = 0; h->cpu_tag[4] = 0; h->cpu_tag[5] = 0; - h->cpu_tag[6] = 0; - h->cpu_tag[7] = 0xffff; + h->cpu_tag[6] = BIT(dest_port) >> 16; + h->cpu_tag[7] = BIT(dest_port) & 0xffff; } -void rtl931x_create_tx_header(struct p_hdr *h, int dest_port, int prio) +static void rtl931x_create_tx_header(struct p_hdr *h, int dest_port, int prio) { - h->cpu_tag[0] = 0x8000; - h->cpu_tag[1] = 0; // TODO: Fill port and prio - h->cpu_tag[2] = 0; + h->cpu_tag[0] = 0x8000; // CPU tag marker + h->cpu_tag[1] = h->cpu_tag[2] = 0; + if (prio >= 0) + h->cpu_tag[2] = BIT(13) | prio << 8; // Enable and set Priority Queue h->cpu_tag[3] = 0; - h->cpu_tag[4] = 0; - h->cpu_tag[5] = 0; - h->cpu_tag[6] = 0; - h->cpu_tag[7] = 0xffff; + h->cpu_tag[4] = h->cpu_tag[5] = h->cpu_tag[6] = h->cpu_tag[7] = 0; + if (dest_port >= 32) { + dest_port -= 32; + h->cpu_tag[4] = BIT(dest_port) >> 16; + h->cpu_tag[5] = BIT(dest_port) & 0xffff; + } else { + h->cpu_tag[6] = BIT(dest_port) >> 16; + h->cpu_tag[7] = BIT(dest_port) & 0xffff; + } } struct rtl838x_rx_q { From 2ab4d4029386849664d152949188c40590cfdd5f Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Sun, 5 Sep 2021 20:22:59 +0200 Subject: [PATCH 13/59] realtek: Increase maximum RX ring buffer length Increase the maximum ring buffer length in order to improve performance on RTL839x devices. Signed-off-by: Birger Koblitz --- .../files-5.10/drivers/net/ethernet/rtl838x_eth.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index 4711efbcdc..dfec2e55ee 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -30,11 +30,12 @@ extern struct rtl83xx_soc_info soc_info; * Maximum number of RX rings is 8 on RTL83XX and 32 on the 93XX * The ring is assigned by switch based on packet/port priortity * Maximum number of TX rings is 2, Ring 2 being the high priority - * ring on the RTL93xx SoCs. MAX_RING_SIZE * RING_BUFFER gives - * the memory used for the ring buffer. + * ring on the RTL93xx SoCs. MAX_RXLEN gives the maximum length + * for an RX ring, MAX_ENTRIES the maximum number of entries + * available in total for all queues. */ #define MAX_RXRINGS 32 -#define MAX_RXLEN 100 +#define MAX_RXLEN 200 #define MAX_ENTRIES (200 * 8) #define TXRINGS 2 #define TXRINGLEN 160 @@ -437,7 +438,7 @@ static irqreturn_t rtl83xx_net_irq(int irq, void *dev_id) /* RX buffer overrun */ if (status & 0x000ff) { - pr_info("RX buffer overrun: status %x, mask: %x\n", + pr_debug("RX buffer overrun: status %x, mask: %x\n", status, sw_r32(priv->r->dma_if_intr_msk)); sw_w32(status, priv->r->dma_if_intr_sts); rtl838x_rb_cleanup(priv, status & 0xff); From a6678accbd3da00a002158618125af155cc27b37 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Mon, 6 Sep 2021 07:24:09 +0200 Subject: [PATCH 14/59] realtek: Add port to smi-bus address mapping All RTL SoCs addresss PHYs via their port number, which is mapped to an SMI address. Add support for configuring this mapping via the .dts on all SoCs apart from the 839x, where the mapping to the 64 ports is fixed. Signed-off-by: Birger Koblitz --- .../drivers/net/ethernet/rtl838x_eth.c | 103 ++++++++++++------ 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index dfec2e55ee..0d9ced9b6c 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -47,6 +47,8 @@ extern struct rtl83xx_soc_info soc_info; #define RX_EN_93XX 0x10 #define TX_DO 0x2 #define WRAP 0x2 +#define MAX_PORTS 57 +#define MAX_SMI_BUSSES 4 #define RING_BUFFER 1600 @@ -185,6 +187,10 @@ struct rtl838x_eth_priv { u32 lastEvent; u16 rxrings; u16 rxringlen; + u8 smi_bus[MAX_PORTS]; + u8 smi_addr[MAX_PORTS]; + bool smi_bus_isc45[MAX_SMI_BUSSES]; + bool phy_is_internal[MAX_PORTS]; }; extern int rtl838x_phy_init(struct rtl838x_eth_priv *priv); @@ -1727,52 +1733,56 @@ static int rtl930x_mdio_reset(struct mii_bus *bus) { int i; int pos; + struct rtl838x_eth_priv *priv = bus->priv; + u32 c45_mask = 0; + u32 poll_sel[2]; + u32 poll_ctrl = 0; - pr_info("RTL930X_SMI_PORT0_15_POLLING_SEL %08x 16-27: %08x\n", - sw_r32(RTL930X_SMI_PORT0_15_POLLING_SEL), - sw_r32(RTL930X_SMI_PORT16_27_POLLING_SEL)); - - pr_info("%s: Enable SMI polling on SMI bus 0, SMI1, SMI2, disable on SMI3\n", __func__); - sw_w32_mask(BIT(20) | BIT(21) | BIT(22), BIT(23), RTL930X_SMI_GLB_CTRL); - - pr_info("RTL9300 Powering on SerDes ports\n"); - rtl9300_sds_power(24, 1); - rtl9300_sds_power(25, 1); - rtl9300_sds_power(26, 1); - rtl9300_sds_power(27, 1); - mdelay(200); - - // RTL930X_SMI_PORT0_15_POLLING_SEL 55550000 16-27: 00f9aaaa - // i.e SMI=0 for all ports - for (i = 0; i < 5; i++) - pr_info("port phy: %08x\n", sw_r32(RTL930X_SMI_PORT0_5_ADDR + i *4)); - - // 1-to-1 mapping of port to phy-address - for (i = 0; i < 24; i++) { + // Mapping of port to phy-addresses on an SMI bus + poll_sel[0] = poll_sel[1] = 0; + for (i = 0; i < 28; i++) { pos = (i % 6) * 5; - sw_w32_mask(0x1f << pos, i << pos, RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4); + sw_w32_mask(0x1f << pos, priv->smi_addr[i] << pos, + RTL930X_SMI_PORT0_5_ADDR + (i / 6) * 4); + + pos = (i * 2) % 32; + poll_sel[i / 16] |= priv->smi_bus[i] << pos; + poll_ctrl |= BIT(20 + priv->smi_bus[i]); } - // ports 24 and 25 have PHY addresses 8 and 9, ports 26/27 PHY 26/27 - sw_w32(8 | 9 << 5 | 26 << 10 | 27 << 15, RTL930X_SMI_PORT0_5_ADDR + 4 * 4); + // Configure which SMI bus is behind which port number + sw_w32(poll_sel[0], RTL930X_SMI_PORT0_15_POLLING_SEL); + sw_w32(poll_sel[1], RTL930X_SMI_PORT16_27_POLLING_SEL); - // Ports 24 and 25 live on SMI bus 1 and 2 - sw_w32_mask(0x3 << 16, 0x1 << 16, RTL930X_SMI_PORT16_27_POLLING_SEL); - sw_w32_mask(0x3 << 18, 0x2 << 18, RTL930X_SMI_PORT16_27_POLLING_SEL); + // Enable polling on the respective SMI busses + sw_w32_mask(0, poll_ctrl, RTL930X_SMI_GLB_CTRL); - // SMI bus 1 and 2 speak Clause 45 TODO: Configure from .dts - sw_w32_mask(0, BIT(17) | BIT(18), RTL930X_SMI_GLB_CTRL); + // Configure which SMI busses are polled in c45 based on a c45 PHY being on that bus + for (i = 0; i < 4; i++) + if (priv->smi_bus_isc45[i]) + c45_mask |= BIT(i + 16); - // Ports 24 and 25 are 2.5 Gig, set this type (1) - sw_w32_mask(0x7 << 12, 1 << 12, RTL930X_SMI_MAC_TYPE_CTRL); - sw_w32_mask(0x7 << 15, 1 << 15, RTL930X_SMI_MAC_TYPE_CTRL); + pr_info("c45_mask: %08x\n", c45_mask); + sw_w32_mask(0, c45_mask, RTL930X_SMI_GLB_CTRL); + + // Ports 24 to 27 are 2.5 or 10Gig, set this type (1) or (0) for internal SerDes + for (i = 24; i < 28; i++) { + pos = (i - 24) * 3 + 12; + if (priv->phy_is_internal[i]) + sw_w32_mask(0x7 << pos, 0 << pos, RTL930X_SMI_MAC_TYPE_CTRL); + else + sw_w32_mask(0x7 << pos, 1 << pos, RTL930X_SMI_MAC_TYPE_CTRL); + } + + // TODO: Set up RTL9300_SMI_10GPHY_POLLING_SEL_0 for Aquantia PHYs on e.g. XGS 1250 return 0; } static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) { - struct device_node *mii_np; + struct device_node *mii_np, *dn; + u32 pn; int ret; pr_debug("%s called\n", __func__); @@ -1825,6 +1835,33 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) priv->mii_bus->priv = priv; priv->mii_bus->parent = &priv->pdev->dev; + for_each_node_by_name(dn, "ethernet-phy") { + u32 smi_addr[2]; + + if (of_property_read_u32(dn, "reg", &pn)) + continue; + + if (of_property_read_u32_array(dn, "rtl9300,smi-address", &smi_addr[0], 2)) { + smi_addr[0] = 0; + smi_addr[1] = pn; + } + + if (pn < MAX_PORTS) { + priv->smi_bus[pn] = smi_addr[0]; + priv->smi_addr[pn] = smi_addr[1]; + } else { + pr_err("%s: illegal port number %d\n", __func__, pn); + } + + if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45")) + priv->smi_bus_isc45[smi_addr[0]] = true; + + if (of_property_read_bool(dn, "phy-is-integrated")) { + priv->phy_is_internal[pn] = true; + } + + } + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); ret = of_mdiobus_register(priv->mii_bus, mii_np); From 54805fc91186228eec0ce14f7c5a6b4149b0a244 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Tue, 7 Sep 2021 15:30:29 +0200 Subject: [PATCH 15/59] realtek: Add driver support for TC offloading This adds support for offloading TC flower by using the Packet Inspection Engine of the RTL-SoCs. Basic infrastructure support is provide with callbacks to the tc subsystem and support for HW packet counters. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/Makefile | 2 +- .../drivers/net/dsa/rtl83xx/common.c | 89 ++++ .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 4 + .../drivers/net/dsa/rtl83xx/rtl838x.h | 219 +++++++++- .../drivers/net/dsa/rtl83xx/rtl83xx.h | 5 + .../files-5.10/drivers/net/dsa/rtl83xx/tc.c | 409 ++++++++++++++++++ .../drivers/net/ethernet/rtl838x_eth.c | 3 + .../drivers/net/ethernet/rtl838x_eth.h | 2 +- 8 files changed, 730 insertions(+), 3 deletions(-) create mode 100644 target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/tc.c diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile index 016184c3d9..8752c79700 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_NET_DSA_RTL83XX) += common.o dsa.o \ - rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o + rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o tc.o diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index 25ac2d4679..dc783705f1 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -449,6 +449,62 @@ int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port) return 0; } +/* + * Allocate a 64 bit octet counter located in the LOG HW table + */ +static int rtl83xx_octet_cntr_alloc(struct rtl838x_switch_priv *priv) +{ + int idx; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->octet_cntr_use_bm, MAX_COUNTERS); + if (idx >= priv->n_counters) { + mutex_unlock(&priv->reg_mutex); + return -1; + } + + set_bit(idx, priv->octet_cntr_use_bm); + mutex_unlock(&priv->reg_mutex); + + return idx; +} + +/* + * Allocate a 32-bit packet counter + * 2 32-bit packet counters share the location of a 64-bit octet counter + * Initially there are no free packet counters and 2 new ones need to be freed + * by allocating the corresponding octet counter + */ +int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv) +{ + int idx, j; + + mutex_lock(&priv->reg_mutex); + + /* Because initially no packet counters are free, the logic is reversed: + * a 0-bit means the counter is already allocated (for octets) + */ + idx = find_first_bit(priv->packet_cntr_use_bm, MAX_COUNTERS * 2); + if (idx >= priv->n_counters * 2) { + j = find_first_zero_bit(priv->octet_cntr_use_bm, MAX_COUNTERS); + if (j >= priv->n_counters) { + mutex_unlock(&priv->reg_mutex); + return -1; + } + set_bit(j, priv->octet_cntr_use_bm); + idx = j * 2; + set_bit(j * 2 + 1, priv->packet_cntr_use_bm); + + } else { + clear_bit(idx, priv->packet_cntr_use_bm); + } + + mutex_unlock(&priv->reg_mutex); + + return idx; +} + static int rtl83xx_handle_changeupper(struct rtl838x_switch_priv *priv, struct net_device *ndev, struct netdev_notifier_changeupper_info *info) @@ -499,6 +555,30 @@ out: return 0; } +/* + * Is the lower network device a DSA slave network device of our RTL930X-switch? + * Unfortunately we cannot just follow dev->dsa_prt as this is only set for the + * DSA master device. + */ +int rtl83xx_port_is_under(const struct net_device * dev, struct rtl838x_switch_priv *priv) +{ + int i; + +// TODO: On 5.12: +// if(!dsa_slave_dev_check(dev)) { +// netdev_info(dev, "%s: not a DSA device.\n", __func__); +// return -EINVAL; +// } + + for (i = 0; i < priv->cpu_port; i++) { + if (!priv->ports[i].dp) + continue; + if (priv->ports[i].dp->slave == dev) + return i; + } + return -EINVAL; +} + static int rtl83xx_netdevice_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -568,6 +648,9 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) rtl8380_get_version(priv); priv->n_lags = 8; priv->l2_bucket_size = 4; + priv->n_pie_blocks = 12; + priv->port_ignore = 0x1f; + priv->n_counters = 128; break; case RTL8390_FAMILY_ID: priv->ds->ops = &rtl83xx_switch_ops; @@ -581,6 +664,9 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) rtl8390_get_version(priv); priv->n_lags = 16; priv->l2_bucket_size = 4; + priv->n_pie_blocks = 18; + priv->port_ignore = 0x3f; + priv->n_counters = 1024; break; case RTL9300_FAMILY_ID: priv->ds->ops = &rtl930x_switch_ops; @@ -595,6 +681,9 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) priv->n_lags = 16; sw_w32(1, RTL930X_ST_CTRL); priv->l2_bucket_size = 8; + priv->n_pie_blocks = 16; + priv->port_ignore = 0x3f; + priv->n_counters = 2048; break; case RTL9310_FAMILY_ID: priv->ds->ops = &rtl930x_switch_ops; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index 6c0ed5ae00..c79b4b2c81 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -188,6 +188,8 @@ static int rtl83xx_setup(struct dsa_switch *ds) rtl83xx_enable_phy_polling(priv); pr_debug("Please wait until PHY is settled\n"); msleep(1000); + priv->r->pie_init(priv); + return 0; } @@ -228,6 +230,8 @@ static int rtl930x_setup(struct dsa_switch *ds) rtl83xx_enable_phy_polling(priv); + priv->r->pie_init(priv); + return 0; } diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h index b2097363b9..a3e169f288 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -338,12 +338,45 @@ /* Debug features */ #define RTL930X_STAT_PRVTE_DROP_COUNTER0 (0xB5B8) +/* Packet Inspection Engine */ +#define RTL838X_METER_GLB_CTRL (0x4B08) +#define RTL839X_METER_GLB_CTRL (0x1300) +#define RTL930X_METER_GLB_CTRL (0xa0a0) +#define RTL839X_ACL_CTRL (0x1288) +#define RTL838X_ACL_BLK_LOOKUP_CTRL (0x6100) +#define RTL839X_ACL_BLK_LOOKUP_CTRL (0x1280) +#define RTL930X_PIE_BLK_LOOKUP_CTRL (0xa5a0) +#define RTL838X_ACL_BLK_PWR_CTRL (0x6104) +#define RTL839X_PS_ACL_PWR_CTRL (0x049c) +#define RTL838X_ACL_BLK_TMPLTE_CTRL(block) (0x6108 + ((block) << 2)) +#define RTL839X_ACL_BLK_TMPLTE_CTRL(block) (0x128c + ((block) << 2)) +#define RTL930X_PIE_BLK_TMPLTE_CTRL(block) (0xa624 + ((block) << 2)) +#define RTL838X_ACL_BLK_GROUP_CTRL (0x615C) +#define RTL839X_ACL_BLK_GROUP_CTRL (0x12ec) +#define RTL838X_ACL_CLR_CTRL (0x6168) +#define RTL839X_ACL_CLR_CTRL (0x12fc) +#define RTL930X_PIE_CLR_CTRL (0xa66c) +#define RTL838X_DMY_REG27 (0x3378) +#define RTL838X_ACL_PORT_LOOKUP_CTRL(p) (0x616C + (((p) << 2))) +#define RTL930X_ACL_PORT_LOOKUP_CTRL(p) (0xA784 + (((p) << 2))) +#define RTL930X_PIE_BLK_PHASE_CTRL (0xA5A4) + +// PIE actions +#define PIE_ACT_COPY_TO_PORT 2 +#define PIE_ACT_REDIRECT_TO_PORT 4 +#define PIE_ACT_ROUTE_UC 6 +#define PIE_ACT_VID_ASSIGN 0 + #define MAX_VLANS 4096 #define MAX_LAGS 16 #define MAX_PRIOS 8 #define RTL930X_PORT_IGNORE 0x3f #define MAX_MC_GROUPS 512 #define UNKNOWN_MC_PMASK (MAX_MC_GROUPS - 1) +#define PIE_BLOCK_SIZE 128 +#define MAX_PIE_ENTRIES (18 * PIE_BLOCK_SIZE) +#define N_FIXED_FIELDS 12 +#define MAX_COUNTERS 2048 enum phy_type { PHY_NONE = 0, @@ -409,6 +442,166 @@ struct rtl838x_l2_entry { bool nh_vlan_target; // Only RTL83xx: VLAN used for next hop }; +enum fwd_rule_action { + FWD_RULE_ACTION_NONE = 0, + FWD_RULE_ACTION_FWD = 1, +}; + +enum pie_phase { + PHASE_VACL = 0, + PHASE_IACL = 1, +}; + +/* Intermediate representation of a Packet Inspection Engine Rule + * as suggested by the Kernel's tc flower offload subsystem + * Field meaning is universal across SoC families, but data content is specific + * to SoC family (e.g. because of different port ranges) */ +struct pie_rule { + int id; + enum pie_phase phase; // Phase in which this template is applied + int packet_cntr; // ID of a packet counter assigned to this rule + int octet_cntr; // ID of a byte counter assigned to this rule + u32 last_packet_cnt; + u64 last_octet_cnt; + + // The following are requirements for the pie template + bool is_egress; + bool is_ipv6; // This is a rule with IPv6 fields + + // Fixed fields that are always matched against on RTL8380 + u8 spmmask_fix; + u8 spn; // Source port number + bool stacking_port; // Source port is stacking port + bool mgnt_vlan; // Packet arrived on management VLAN + bool dmac_hit_sw; // The packet's destination MAC matches one of the device's + bool content_too_deep; // The content of the packet cannot be parsed: too many layers + bool not_first_frag; // Not the first IP fragment + u8 frame_type_l4; // 0: UDP, 1: TCP, 2: ICMP/ICMPv6, 3: IGMP + u8 frame_type; // 0: ARP, 1: L2 only, 2: IPv4, 3: IPv6 + bool otag_fmt; // 0: outer tag packet, 1: outer priority tag or untagged + bool itag_fmt; // 0: inner tag packet, 1: inner priority tag or untagged + bool otag_exist; // packet with outer tag + bool itag_exist; // packet with inner tag + bool frame_type_l2; // 0: Ethernet, 1: LLC_SNAP, 2: LLC_Other, 3: Reserved + bool igr_normal_port; // Ingress port is not cpu or stacking port + u8 tid; // The template ID defining the what the templated fields mean + + // Masks for the fields that are always matched against on RTL8380 + u8 spmmask_fix_m; + u8 spn_m; + bool stacking_port_m; + bool mgnt_vlan_m; + bool dmac_hit_sw_m; + bool content_too_deep_m; + bool not_first_frag_m; + u8 frame_type_l4_m; + u8 frame_type_m; + bool otag_fmt_m; + bool itag_fmt_m; + bool otag_exist_m; + bool itag_exist_m; + bool frame_type_l2_m; + bool igr_normal_port_m; + u8 tid_m; + + // Logical operations between rules, special rules for rule numbers apply + bool valid; + bool cond_not; // Matches when conditions not match + bool cond_and1; // And this rule 2n with the next rule 2n+1 in same block + bool cond_and2; // And this rule m in block 2n with rule m in block 2n+1 + bool ivalid; + + // Actions to be performed + bool drop; // Drop the packet + bool fwd_sel; // Forward packet: to port, portmask, dest route, next rule, drop + bool ovid_sel; // So something to outer vlan-id: shift, re-assign + bool ivid_sel; // Do something to inner vlan-id: shift, re-assign + bool flt_sel; // Filter the packet when sending to certain ports + bool log_sel; // Log the packet in one of the LOG-table counters + bool rmk_sel; // Re-mark the packet, i.e. change the priority-tag + bool meter_sel; // Meter the packet, i.e. limit rate of this type of packet + bool tagst_sel; // Change the ergress tag + bool mir_sel; // Mirror the packet to a Link Aggregation Group + bool nopri_sel; // Change the normal priority + bool cpupri_sel; // Change the CPU priority + bool otpid_sel; // Change Outer Tag Protocol Identifier (802.1q) + bool itpid_sel; // Change Inner Tag Protocol Identifier (802.1q) + bool shaper_sel; // Apply traffic shaper + bool mpls_sel; // MPLS actions + bool bypass_sel; // Bypass actions + bool fwd_sa_lrn; // Learn the source address when forwarding + bool fwd_mod_to_cpu; // Forward the modified VLAN tag format to CPU-port + + // Fields used in predefined templates 0-2 on RTL8380 / 90 / 9300 + u64 spm; // Source Port Matrix + u16 otag; // Outer VLAN-ID + u8 smac[ETH_ALEN]; // Source MAC address + u8 dmac[ETH_ALEN]; // Destination MAC address + u16 ethertype; // Ethernet frame type field in ethernet header + u16 itag; // Inner VLAN-ID + u16 field_range_check; + u32 sip; // Source IP + struct in6_addr sip6; // IPv6 Source IP + u32 dip; // Destination IP + struct in6_addr dip6; // IPv6 Destination IP + u16 tos_proto; // IPv4: TOS + Protocol fields, IPv6: Traffic class + next header + u16 sport; // TCP/UDP source port + u16 dport; // TCP/UDP destination port + u16 icmp_igmp; + u16 tcp_info; + u16 dsap_ssap; // Destination / Source Service Access Point bytes (802.3) + + u64 spm_m; + u16 otag_m; + u8 smac_m[ETH_ALEN]; + u8 dmac_m[ETH_ALEN]; + u8 ethertype_m; + u16 itag_m; + u16 field_range_check_m; + u32 sip_m; + struct in6_addr sip6_m; // IPv6 Source IP mask + u32 dip_m; + struct in6_addr dip6_m; // IPv6 Destination IP mask + u16 tos_proto_m; + u16 sport_m; + u16 dport_m; + u16 icmp_igmp_m; + u16 tcp_info_m; + u16 dsap_ssap_m; + + // Data associated with actions + u8 fwd_act; // Type of forwarding action + // 0: permit, 1: drop, 2: copy to port id, 4: copy to portmask + // 4: redirect to portid, 5: redirect to portmask + // 6: route, 7: vlan leaky (only 8380) + u16 fwd_data; // Additional data for forwarding action, e.g. destination port + u8 ovid_act; + u16 ovid_data; // Outer VLAN ID + u8 ivid_act; + u16 ivid_data; // Inner VLAN ID + u16 flt_data; // Filtering data + u16 log_data; // ID of packet or octet counter in LOG table, on RTL93xx + // unnecessary since PIE-Rule-ID == LOG-counter-ID + bool log_octets; + u8 mpls_act; // MPLS action type + u16 mpls_lib_idx; // MPLS action data + + u16 rmk_data; // Data for remarking + u16 meter_data; // ID of meter for bandwidth control + u16 tagst_data; + u16 mir_data; + u16 nopri_data; + u16 cpupri_data; + u16 otpid_data; + u16 itpid_data; + u16 shaper_data; + + // Bypass actions, ignored on RTL8380 + bool bypass_all; // Not clear + bool bypass_igr_stp; // Bypass Ingress STP state + bool bypass_ibc_sc; // Bypass Ingress Bandwidth Control and Storm Control +}; + struct rtl838x_nexthop { u16 id; // ID in HW Nexthop table u32 ip; // IP Addres of nexthop @@ -424,6 +617,15 @@ struct rtl838x_nexthop { struct rtl838x_switch_priv; +struct rtl83xx_flow { + unsigned long cookie; + struct rhash_head node; + struct rcu_head rcu_head; + struct rtl838x_switch_priv *priv; + struct pie_rule rule; + u32 flags; +}; + struct rtl838x_reg { void (*mask_port_reg_be)(u64 clear, u64 set, int reg); void (*set_port_reg_be)(u64 set, int reg); @@ -491,6 +693,13 @@ struct rtl838x_reg { u64 (*read_mcast_pmask)(int idx); void (*write_mcast_pmask)(int idx, u64 portmask); void (*vlan_fwd_on_inner)(int port, bool is_set); + void (*pie_init)(struct rtl838x_switch_priv *priv); + int (*pie_rule_read)(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr); + int (*pie_rule_write)(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr); + int (*pie_rule_add)(struct rtl838x_switch_priv *priv, struct pie_rule *rule); + void (*pie_rule_rm)(struct rtl838x_switch_priv *priv, struct pie_rule *rule); + u32 (*packet_cntr_read)(int counter); + void (*packet_cntr_clear)(int counter); }; struct rtl838x_switch_priv { @@ -501,7 +710,8 @@ struct rtl838x_switch_priv { u16 family_id; char version; struct rtl838x_port ports[57]; - struct mutex reg_mutex; + struct mutex reg_mutex; // Mutex for individual register manipulations + struct mutex pie_mutex; // Mutex for Packet Inspection Engine int link_state_irq; int mirror_group_ports[4]; struct mii_bus *mii_bus; @@ -509,6 +719,7 @@ struct rtl838x_switch_priv { u8 cpu_port; u8 port_mask; u8 port_width; + u8 port_ignore; u64 irq_mask; u32 fib_entries; int l2_bucket_size; @@ -519,6 +730,12 @@ struct rtl838x_switch_priv { struct notifier_block nb; bool eee_enabled; unsigned long int mc_group_bm[MAX_MC_GROUPS >> 5]; + int n_pie_blocks; + struct rhashtable tc_ht; + unsigned long int pie_use_bm[MAX_PIE_ENTRIES >> 5]; + int n_counters; + unsigned long int octet_cntr_use_bm[MAX_COUNTERS >> 5]; + unsigned long int packet_cntr_use_bm[MAX_COUNTERS >> 4]; }; void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv); diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h index fd0455a6cd..ffd37aa5a8 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h @@ -74,6 +74,11 @@ inline u32 rtl_table_data_r(struct table_reg *r, int i); inline void rtl_table_data_w(struct table_reg *r, u32 v, int i); void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv); + +int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv); + +int rtl83xx_port_is_under(const struct net_device * dev, struct rtl838x_switch_priv *priv); + int read_phy(u32 port, u32 page, u32 reg, u32 *val); int write_phy(u32 port, u32 page, u32 reg, u32 val); diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/tc.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/tc.c new file mode 100644 index 0000000000..d0a8ee8cfe --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/tc.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +#include +#include "rtl83xx.h" +#include "rtl838x.h" + +/* + * Parse the flow rule for the matching conditions + */ +static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv, + struct flow_rule *rule, struct rtl83xx_flow *flow) +{ + struct flow_dissector *dissector = rule->match.dissector; + + pr_debug("In %s\n", __func__); + /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ + if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || + (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) { + pr_err("Cannot form TC key: used_keys = 0x%x\n", dissector->used_keys); + return -EOPNOTSUPP; + } + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; + + pr_debug("%s: BASIC\n", __func__); + flow_rule_match_basic(rule, &match); + if (match.key->n_proto == htons(ETH_P_ARP)) + flow->rule.frame_type = 0; + if (match.key->n_proto == htons(ETH_P_IP)) + flow->rule.frame_type = 2; + if (match.key->n_proto == htons(ETH_P_IPV6)) + flow->rule.frame_type = 3; + if ((match.key->n_proto == htons(ETH_P_ARP)) || flow->rule.frame_type) + flow->rule.frame_type_m = 3; + if (flow->rule.frame_type >= 2) { + if (match.key->ip_proto == IPPROTO_UDP) + flow->rule.frame_type_l4 = 0; + if (match.key->ip_proto == IPPROTO_TCP) + flow->rule.frame_type_l4 = 1; + if (match.key->ip_proto == IPPROTO_ICMP + || match.key->ip_proto ==IPPROTO_ICMPV6) + flow->rule.frame_type_l4 = 2; + if (match.key->ip_proto == IPPROTO_TCP) + flow->rule.frame_type_l4 = 3; + if ((match.key->ip_proto == IPPROTO_UDP) || flow->rule.frame_type_l4) + flow->rule.frame_type_l4_m = 7; + } + } + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + + pr_debug("%s: ETH_ADDR\n", __func__); + flow_rule_match_eth_addrs(rule, &match); + ether_addr_copy(flow->rule.dmac, match.key->dst); + ether_addr_copy(flow->rule.dmac_m, match.mask->dst); + ether_addr_copy(flow->rule.smac, match.key->src); + ether_addr_copy(flow->rule.smac_m, match.mask->src); + } + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; + + pr_debug("%s: VLAN\n", __func__); + flow_rule_match_vlan(rule, &match); + flow->rule.itag = match.key->vlan_id; + flow->rule.itag_m = match.mask->vlan_id; + // TODO: What about match.key->vlan_priority ? + } + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs match; + + pr_debug("%s: IPV4\n", __func__); + flow_rule_match_ipv4_addrs(rule, &match); + flow->rule.is_ipv6 = false; + flow->rule.dip = match.key->dst; + flow->rule.dip_m = match.mask->dst; + flow->rule.sip = match.key->src; + flow->rule.sip_m = match.mask->src; + } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { + struct flow_match_ipv6_addrs match; + + pr_debug("%s: IPV6\n", __func__); + flow->rule.is_ipv6 = true; + flow_rule_match_ipv6_addrs(rule, &match); + flow->rule.dip6 = match.key->dst; + flow->rule.dip6_m = match.mask->dst; + flow->rule.sip6 = match.key->src; + flow->rule.sip6_m = match.mask->src; + } + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; + + pr_debug("%s: PORTS\n", __func__); + flow_rule_match_ports(rule, &match); + flow->rule.dport = match.key->dst; + flow->rule.dport_m = match.mask->dst; + flow->rule.sport = match.key->src; + flow->rule.sport_m = match.mask->src; + } + + // TODO: ICMP + return 0; +} + +static void rtl83xx_flow_bypass_all(struct rtl83xx_flow *flow) +{ + flow->rule.bypass_sel = true; + flow->rule.bypass_all = true; + flow->rule.bypass_igr_stp = true; + flow->rule.bypass_ibc_sc = true; +} + +static int rtl83xx_parse_fwd(struct rtl838x_switch_priv *priv, + const struct flow_action_entry *act, struct rtl83xx_flow *flow) +{ + struct net_device *dev = act->dev; + int port; + + port = rtl83xx_port_is_under(dev, priv); + if (port < 0) { + netdev_info(dev, "%s: not a DSA device.\n", __func__); + return -EINVAL; + } + + flow->rule.fwd_sel = true; + flow->rule.fwd_data = port; + pr_debug("Using port index: %d\n", port); + rtl83xx_flow_bypass_all(flow); + + return 0; +} + +static int rtl83xx_add_flow(struct rtl838x_switch_priv *priv, struct flow_cls_offload *f, + struct rtl83xx_flow *flow) +{ + struct flow_rule *rule = flow_cls_offload_flow_rule(f); + const struct flow_action_entry *act; + int i, err; + + pr_debug("%s\n", __func__); + + rtl83xx_parse_flow_rule(priv, rule, flow); + + flow_action_for_each(i, act, &rule->action) { + switch (act->id) { + case FLOW_ACTION_DROP: + pr_debug("%s: DROP\n", __func__); + flow->rule.drop = true; + rtl83xx_flow_bypass_all(flow); + return 0; + + case FLOW_ACTION_TRAP: + pr_debug("%s: TRAP\n", __func__); + flow->rule.fwd_data = priv->cpu_port; + flow->rule.fwd_act = PIE_ACT_REDIRECT_TO_PORT; + rtl83xx_flow_bypass_all(flow); + break; + + case FLOW_ACTION_MANGLE: + pr_err("%s: FLOW_ACTION_MANGLE not supported\n", __func__); + return -EOPNOTSUPP; + + case FLOW_ACTION_ADD: + pr_err("%s: FLOW_ACTION_ADD not supported\n", __func__); + return -EOPNOTSUPP; + + case FLOW_ACTION_VLAN_PUSH: + pr_debug("%s: VLAN_PUSH\n", __func__); +// TODO: act->vlan.proto + flow->rule.ivid_act = PIE_ACT_VID_ASSIGN; + flow->rule.ivid_sel = true; + flow->rule.ivid_data = htons(act->vlan.vid); + flow->rule.ovid_act = PIE_ACT_VID_ASSIGN; + flow->rule.ovid_sel = true; + flow->rule.ovid_data = htons(act->vlan.vid); + flow->rule.fwd_mod_to_cpu = true; + break; + + case FLOW_ACTION_VLAN_POP: + pr_debug("%s: VLAN_POP\n", __func__); + flow->rule.ivid_act = PIE_ACT_VID_ASSIGN; + flow->rule.ivid_data = 0; + flow->rule.ivid_sel = true; + flow->rule.ovid_act = PIE_ACT_VID_ASSIGN; + flow->rule.ovid_data = 0; + flow->rule.ovid_sel = true; + flow->rule.fwd_mod_to_cpu = true; + break; + + case FLOW_ACTION_CSUM: + pr_err("%s: FLOW_ACTION_CSUM not supported\n", __func__); + return -EOPNOTSUPP; + + case FLOW_ACTION_REDIRECT: + pr_debug("%s: REDIRECT\n", __func__); + err = rtl83xx_parse_fwd(priv, act, flow); + if (err) + return err; + flow->rule.fwd_act = PIE_ACT_REDIRECT_TO_PORT; + break; + + case FLOW_ACTION_MIRRED: + pr_debug("%s: MIRRED\n", __func__); + err = rtl83xx_parse_fwd(priv, act, flow); + if (err) + return err; + flow->rule.fwd_act = PIE_ACT_COPY_TO_PORT; + break; + + default: + pr_err("%s: Flow action not supported: %d\n", __func__, act->id); + return -EOPNOTSUPP; + } + } + + return 0; +} + +static const struct rhashtable_params tc_ht_params = { + .head_offset = offsetof(struct rtl83xx_flow, node), + .key_offset = offsetof(struct rtl83xx_flow, cookie), + .key_len = sizeof(((struct rtl83xx_flow *)0)->cookie), + .automatic_shrinking = true, +}; + +static int rtl83xx_configure_flower(struct rtl838x_switch_priv *priv, + struct flow_cls_offload *f) +{ + struct rtl83xx_flow *flow; + int err = 0; + + pr_debug("In %s\n", __func__); + + rcu_read_lock(); + pr_debug("Cookie %08lx\n", f->cookie); + flow = rhashtable_lookup(&priv->tc_ht, &f->cookie, tc_ht_params); + if (flow) { + pr_info("%s: Got flow\n", __func__); + err = -EEXIST; + goto rcu_unlock; + } + +rcu_unlock: + rcu_read_unlock(); + if (flow) + goto out; + pr_debug("%s: New flow\n", __func__); + + flow = kzalloc(sizeof(*flow), GFP_KERNEL); + if (!flow) { + err = -ENOMEM; + goto out; + } + + flow->cookie = f->cookie; + flow->priv = priv; + + err = rhashtable_insert_fast(&priv->tc_ht, &flow->node, tc_ht_params); + if (err) { + pr_err("Could not insert add new rule\n"); + goto out_free; + } + + rtl83xx_add_flow(priv, f, flow); // TODO: check error + + // Add log action to flow + flow->rule.packet_cntr = rtl83xx_packet_cntr_alloc(priv); + if (flow->rule.packet_cntr >= 0) { + pr_debug("Using packet counter %d\n", flow->rule.packet_cntr); + flow->rule.log_sel = true; + flow->rule.log_data = flow->rule.packet_cntr; + } + + err = priv->r->pie_rule_add(priv, &flow->rule); + return err; + +out_free: + kfree(flow); +out: + pr_err("%s: error %d\n", __func__, err); + return err; +} + +static int rtl83xx_delete_flower(struct rtl838x_switch_priv *priv, + struct flow_cls_offload * cls_flower) +{ + struct rtl83xx_flow *flow; + + pr_debug("In %s\n", __func__); + rcu_read_lock(); + flow = rhashtable_lookup_fast(&priv->tc_ht, &cls_flower->cookie, tc_ht_params); + if (!flow) { + rcu_read_unlock(); + return -EINVAL; + } + + priv->r->pie_rule_rm(priv, &flow->rule); + + rhashtable_remove_fast(&priv->tc_ht, &flow->node, tc_ht_params); + + kfree_rcu(flow, rcu_head); + + rcu_read_unlock(); + return 0; +} + +static int rtl83xx_stats_flower(struct rtl838x_switch_priv *priv, + struct flow_cls_offload * cls_flower) +{ + struct rtl83xx_flow *flow; + unsigned long lastused = 0; + int total_packets, new_packets; + + pr_debug("%s: \n", __func__); + flow = rhashtable_lookup_fast(&priv->tc_ht, &cls_flower->cookie, tc_ht_params); + if (!flow) + return -1; + + if (flow->rule.packet_cntr >= 0) { + total_packets = priv->r->packet_cntr_read(flow->rule.packet_cntr); + pr_debug("Total packets: %d\n", total_packets); + new_packets = total_packets - flow->rule.last_packet_cnt; + flow->rule.last_packet_cnt = total_packets; + } + + // TODO: We need a second PIE rule to count the bytes + flow_stats_update(&cls_flower->stats, 100 * new_packets, new_packets, 0, lastused, + FLOW_ACTION_HW_STATS_IMMEDIATE); + return 0; +} + +static int rtl83xx_setup_tc_cls_flower(struct rtl838x_switch_priv *priv, + struct flow_cls_offload *cls_flower) +{ + pr_debug("%s: %d\n", __func__, cls_flower->command); + switch (cls_flower->command) { + case FLOW_CLS_REPLACE: + return rtl83xx_configure_flower(priv, cls_flower); + case FLOW_CLS_DESTROY: + return rtl83xx_delete_flower(priv, cls_flower); + case FLOW_CLS_STATS: + return rtl83xx_stats_flower(priv, cls_flower); + default: + return -EOPNOTSUPP; + } +} + + +static int rtl83xx_setup_tc_block_cb(enum tc_setup_type type, void *type_data, + void *cb_priv) +{ + struct rtl838x_switch_priv *priv = cb_priv; + + switch (type) { + case TC_SETUP_CLSFLOWER: + pr_debug("%s: TC_SETUP_CLSFLOWER\n", __func__); + return rtl83xx_setup_tc_cls_flower(priv, type_data); + default: + return -EOPNOTSUPP; + } +} + +static LIST_HEAD(rtl83xx_block_cb_list); + +int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data) +{ + struct rtl838x_switch_priv *priv; + struct flow_block_offload *f = type_data; + static bool first_time = true; + int err; + + pr_debug("%s: %d\n", __func__, type); + + if(!netdev_uses_dsa(dev)) { + pr_err("%s: no DSA\n", __func__); + return 0; + } + priv = dev->dsa_ptr->ds->priv; + + switch (type) { + case TC_SETUP_BLOCK: + if (first_time) { + first_time = false; + err = rhashtable_init(&priv->tc_ht, &tc_ht_params); + if (err) + pr_err("%s: Could not initialize hash table\n", __func__); + } + + f->unlocked_driver_cb = true; + return flow_block_cb_setup_simple(type_data, + &rtl83xx_block_cb_list, + rtl83xx_setup_tc_block_cb, + priv, priv, true); + default: + return -EOPNOTSUPP; + } + + return 0; +} diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c index 0d9ced9b6c..c966746f02 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c @@ -1927,6 +1927,7 @@ static const struct net_device_ops rtl838x_eth_netdev_ops = { .ndo_tx_timeout = rtl838x_eth_tx_timeout, .ndo_set_features = rtl83xx_set_features, .ndo_fix_features = rtl838x_fix_features, + .ndo_setup_tc = rtl83xx_setup_tc, }; static const struct net_device_ops rtl839x_eth_netdev_ops = { @@ -1940,6 +1941,7 @@ static const struct net_device_ops rtl839x_eth_netdev_ops = { .ndo_tx_timeout = rtl838x_eth_tx_timeout, .ndo_set_features = rtl83xx_set_features, .ndo_fix_features = rtl838x_fix_features, + .ndo_setup_tc = rtl83xx_setup_tc, }; static const struct net_device_ops rtl930x_eth_netdev_ops = { @@ -1953,6 +1955,7 @@ static const struct net_device_ops rtl930x_eth_netdev_ops = { .ndo_tx_timeout = rtl838x_eth_tx_timeout, .ndo_set_features = rtl93xx_set_features, .ndo_fix_features = rtl838x_fix_features, + .ndo_setup_tc = rtl83xx_setup_tc, }; static const struct net_device_ops rtl931x_eth_netdev_ops = { diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h index c7e97057b3..d2691bfaf5 100644 --- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h @@ -424,6 +424,6 @@ int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val); int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val); int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val); int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val); -void rtl9300_sds_power(int sds_num, int val); +int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data); #endif /* _RTL838X_ETH_H */ From 87b3bd07a445376d9cae73aaf9354029260183ac Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Tue, 7 Sep 2021 15:32:56 +0200 Subject: [PATCH 16/59] realtek: Packet Inspection Engine support for RTL838x SoCs Adds the RTL838x-specific PIE support routines. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/rtl838x.c | 1007 +++++++++++++++++ 1 file changed, 1007 insertions(+) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c index 5d764b6a32..2d24eaa337 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c @@ -5,6 +5,96 @@ extern struct mutex smi_lock; +// see_dal_maple_acl_log2PhyTmplteField and src/app/diag_v2/src/diag_acl.c +/* Definition of the RTL838X-specific template field IDs as used in the PIE */ +enum template_field_id { + TEMPLATE_FIELD_SPMMASK = 0, + TEMPLATE_FIELD_SPM0 = 1, // Source portmask ports 0-15 + TEMPLATE_FIELD_SPM1 = 2, // Source portmask ports 16-28 + TEMPLATE_FIELD_RANGE_CHK = 3, + TEMPLATE_FIELD_DMAC0 = 4, // Destination MAC [15:0] + TEMPLATE_FIELD_DMAC1 = 5, // Destination MAC [31:16] + TEMPLATE_FIELD_DMAC2 = 6, // Destination MAC [47:32] + TEMPLATE_FIELD_SMAC0 = 7, // Source MAC [15:0] + TEMPLATE_FIELD_SMAC1 = 8, // Source MAC [31:16] + TEMPLATE_FIELD_SMAC2 = 9, // Source MAC [47:32] + TEMPLATE_FIELD_ETHERTYPE = 10, // Ethernet typ + TEMPLATE_FIELD_OTAG = 11, // Outer VLAN tag + TEMPLATE_FIELD_ITAG = 12, // Inner VLAN tag + TEMPLATE_FIELD_SIP0 = 13, // IPv4 or IPv6 source IP[15:0] or ARP/RARP + // source protocol address in header + TEMPLATE_FIELD_SIP1 = 14, // IPv4 or IPv6 source IP[31:16] or ARP/RARP + TEMPLATE_FIELD_DIP0 = 15, // IPv4 or IPv6 destination IP[15:0] + TEMPLATE_FIELD_DIP1 = 16, // IPv4 or IPv6 destination IP[31:16] + TEMPLATE_FIELD_IP_TOS_PROTO = 17, // IPv4 TOS/IPv6 traffic class and + // IPv4 proto/IPv6 next header fields + TEMPLATE_FIELD_L34_HEADER = 18, // packet with extra tag and IPv6 with auth, dest, + // frag, route, hop-by-hop option header, + // IGMP type, TCP flag + TEMPLATE_FIELD_L4_SPORT = 19, // TCP/UDP source port + TEMPLATE_FIELD_L4_DPORT = 20, // TCP/UDP destination port + TEMPLATE_FIELD_ICMP_IGMP = 21, + TEMPLATE_FIELD_IP_RANGE = 22, + TEMPLATE_FIELD_FIELD_SELECTOR_VALID = 23, // Field selector mask + TEMPLATE_FIELD_FIELD_SELECTOR_0 = 24, + TEMPLATE_FIELD_FIELD_SELECTOR_1 = 25, + TEMPLATE_FIELD_FIELD_SELECTOR_2 = 26, + TEMPLATE_FIELD_FIELD_SELECTOR_3 = 27, + TEMPLATE_FIELD_SIP2 = 28, // IPv6 source IP[47:32] + TEMPLATE_FIELD_SIP3 = 29, // IPv6 source IP[63:48] + TEMPLATE_FIELD_SIP4 = 30, // IPv6 source IP[79:64] + TEMPLATE_FIELD_SIP5 = 31, // IPv6 source IP[95:80] + TEMPLATE_FIELD_SIP6 = 32, // IPv6 source IP[111:96] + TEMPLATE_FIELD_SIP7 = 33, // IPv6 source IP[127:112] + TEMPLATE_FIELD_DIP2 = 34, // IPv6 destination IP[47:32] + TEMPLATE_FIELD_DIP3 = 35, // IPv6 destination IP[63:48] + TEMPLATE_FIELD_DIP4 = 36, // IPv6 destination IP[79:64] + TEMPLATE_FIELD_DIP5 = 37, // IPv6 destination IP[95:80] + TEMPLATE_FIELD_DIP6 = 38, // IPv6 destination IP[111:96] + TEMPLATE_FIELD_DIP7 = 39, // IPv6 destination IP[127:112] + TEMPLATE_FIELD_FWD_VID = 40, // Forwarding VLAN-ID + TEMPLATE_FIELD_FLOW_LABEL = 41, +}; + +/* + * The RTL838X SoCs use 5 fixed templates with definitions for which data fields are to + * be copied from the Ethernet Frame header into the 12 User-definable fields of the Packet + * Inspection Engine's buffer. The following defines the field contents for each of the fixed + * templates. Additionally, 3 user-definable templates can be set up via the definitions + * in RTL838X_ACL_TMPLTE_CTRL control registers. + * TODO: See all src/app/diag_v2/src/diag_pie.c + */ +#define N_FIXED_TEMPLATES 5 +static enum template_field_id fixed_templates[N_FIXED_TEMPLATES][N_FIXED_FIELDS] = +{ + { + TEMPLATE_FIELD_SPM0, TEMPLATE_FIELD_SPM1, TEMPLATE_FIELD_OTAG, + TEMPLATE_FIELD_SMAC0, TEMPLATE_FIELD_SMAC1, TEMPLATE_FIELD_SMAC2, + TEMPLATE_FIELD_DMAC0, TEMPLATE_FIELD_DMAC1, TEMPLATE_FIELD_DMAC2, + TEMPLATE_FIELD_ETHERTYPE, TEMPLATE_FIELD_ITAG, TEMPLATE_FIELD_RANGE_CHK + }, { + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_DIP0, + TEMPLATE_FIELD_DIP1,TEMPLATE_FIELD_IP_TOS_PROTO, TEMPLATE_FIELD_L4_SPORT, + TEMPLATE_FIELD_L4_DPORT, TEMPLATE_FIELD_ICMP_IGMP, TEMPLATE_FIELD_ITAG, + TEMPLATE_FIELD_RANGE_CHK, TEMPLATE_FIELD_SPM0, TEMPLATE_FIELD_SPM1 + }, { + TEMPLATE_FIELD_DMAC0, TEMPLATE_FIELD_DMAC1, TEMPLATE_FIELD_DMAC2, + TEMPLATE_FIELD_ITAG, TEMPLATE_FIELD_ETHERTYPE, TEMPLATE_FIELD_IP_TOS_PROTO, + TEMPLATE_FIELD_L4_DPORT, TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_SIP0, + TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_DIP0, TEMPLATE_FIELD_DIP1 + }, { + TEMPLATE_FIELD_DIP0, TEMPLATE_FIELD_DIP1, TEMPLATE_FIELD_DIP2, + TEMPLATE_FIELD_DIP3, TEMPLATE_FIELD_DIP4, TEMPLATE_FIELD_DIP5, + TEMPLATE_FIELD_DIP6, TEMPLATE_FIELD_DIP7, TEMPLATE_FIELD_L4_DPORT, + TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_ICMP_IGMP, TEMPLATE_FIELD_IP_TOS_PROTO + }, { + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_SIP2, + TEMPLATE_FIELD_SIP3, TEMPLATE_FIELD_SIP4, TEMPLATE_FIELD_SIP5, + TEMPLATE_FIELD_SIP6, TEMPLATE_FIELD_SIP7, TEMPLATE_FIELD_ITAG, + TEMPLATE_FIELD_RANGE_CHK, TEMPLATE_FIELD_SPM0, TEMPLATE_FIELD_SPM1 + }, +}; + void rtl838x_print_matrix(void) { unsigned volatile int *ptr8; @@ -535,6 +625,916 @@ static void rtl838x_init_eee(struct rtl838x_switch_priv *priv, bool enable) priv->eee_enabled = enable; } +static void rtl838x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index) +{ + int block = index / PIE_BLOCK_SIZE; + u32 block_state = sw_r32(RTL838X_ACL_BLK_LOOKUP_CTRL); + + // Make sure rule-lookup is enabled in the block + if (!(block_state & BIT(block))) + sw_w32(block_state | BIT(block), RTL838X_ACL_BLK_LOOKUP_CTRL); +} + +static void rtl838x_pie_rule_del(struct rtl838x_switch_priv *priv, int index_from, int index_to) +{ + int block_from = index_from / PIE_BLOCK_SIZE; + int block_to = index_to / PIE_BLOCK_SIZE; + u32 v = (index_from << 1)| (index_to << 12 ) | BIT(0); + int block; + u32 block_state; + + pr_debug("%s: from %d to %d\n", __func__, index_from, index_to); + mutex_lock(&priv->reg_mutex); + + // Remember currently active blocks + block_state = sw_r32(RTL838X_ACL_BLK_LOOKUP_CTRL); + + // Make sure rule-lookup is disabled in the relevant blocks + for (block = block_from; block <= block_to; block++) { + if (block_state & BIT(block)) + sw_w32(block_state & (~BIT(block)), RTL838X_ACL_BLK_LOOKUP_CTRL); + } + + // Write from-to and execute bit into control register + sw_w32(v, RTL838X_ACL_CLR_CTRL); + + // Wait until command has completed + do { + } while (sw_r32(RTL838X_ACL_CLR_CTRL) & BIT(0)); + + // Re-enable rule lookup + for (block = block_from; block <= block_to; block++) { + if (!(block_state & BIT(block))) + sw_w32(block_state | BIT(block), RTL838X_ACL_BLK_LOOKUP_CTRL); + } + + mutex_unlock(&priv->reg_mutex); +} + +/* + * Reads the intermediate representation of the templated match-fields of the + * PIE rule in the pie_rule structure and fills in the raw data fields in the + * raw register space r[]. + * The register space configuration size is identical for the RTL8380/90 and RTL9300, + * however the RTL9310 has 2 more registers / fields and the physical field-ids + * are specific to every platform. + */ +static void rtl838x_write_pie_templated(u32 r[], struct pie_rule *pr, enum template_field_id t[]) +{ + int i; + enum template_field_id field_type; + u16 data, data_m; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + field_type = t[i]; + data = data_m = 0; + + switch (field_type) { + case TEMPLATE_FIELD_SPM0: + data = pr->spm; + data_m = pr->spm_m; + break; + case TEMPLATE_FIELD_SPM1: + data = pr->spm >> 16; + data_m = pr->spm_m >> 16; + break; + case TEMPLATE_FIELD_OTAG: + data = pr->otag; + data_m = pr->otag_m; + break; + case TEMPLATE_FIELD_SMAC0: + data = pr->smac[4]; + data = (data << 8) | pr->smac[5]; + data_m = pr->smac_m[4]; + data_m = (data_m << 8) | pr->smac_m[5]; + break; + case TEMPLATE_FIELD_SMAC1: + data = pr->smac[2]; + data = (data << 8) | pr->smac[3]; + data_m = pr->smac_m[2]; + data_m = (data_m << 8) | pr->smac_m[3]; + break; + case TEMPLATE_FIELD_SMAC2: + data = pr->smac[0]; + data = (data << 8) | pr->smac[1]; + data_m = pr->smac_m[0]; + data_m = (data_m << 8) | pr->smac_m[1]; + break; + case TEMPLATE_FIELD_DMAC0: + data = pr->dmac[4]; + data = (data << 8) | pr->dmac[5]; + data_m = pr->dmac_m[4]; + data_m = (data_m << 8) | pr->dmac_m[5]; + break; + case TEMPLATE_FIELD_DMAC1: + data = pr->dmac[2]; + data = (data << 8) | pr->dmac[3]; + data_m = pr->dmac_m[2]; + data_m = (data_m << 8) | pr->dmac_m[3]; + break; + case TEMPLATE_FIELD_DMAC2: + data = pr->dmac[0]; + data = (data << 8) | pr->dmac[1]; + data_m = pr->dmac_m[0]; + data_m = (data_m << 8) | pr->dmac_m[1]; + break; + case TEMPLATE_FIELD_ETHERTYPE: + data = pr->ethertype; + data_m = pr->ethertype_m; + break; + case TEMPLATE_FIELD_ITAG: + data = pr->itag; + data_m = pr->itag_m; + break; + case TEMPLATE_FIELD_RANGE_CHK: + data = pr->field_range_check; + data_m = pr->field_range_check_m; + break; + case TEMPLATE_FIELD_SIP0: + if (pr->is_ipv6) { + data = pr->sip6.s6_addr16[7]; + data_m = pr->sip6_m.s6_addr16[7]; + } else { + data = pr->sip; + data_m = pr->sip_m; + } + break; + case TEMPLATE_FIELD_SIP1: + if (pr->is_ipv6) { + data = pr->sip6.s6_addr16[6]; + data_m = pr->sip6_m.s6_addr16[6]; + } else { + data = pr->sip >> 16; + data_m = pr->sip_m >> 16; + } + break; + + case TEMPLATE_FIELD_SIP2: + case TEMPLATE_FIELD_SIP3: + case TEMPLATE_FIELD_SIP4: + case TEMPLATE_FIELD_SIP5: + case TEMPLATE_FIELD_SIP6: + case TEMPLATE_FIELD_SIP7: + data = pr->sip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)]; + data_m = pr->sip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)]; + break; + + case TEMPLATE_FIELD_DIP0: + if (pr->is_ipv6) { + data = pr->dip6.s6_addr16[7]; + data_m = pr->dip6_m.s6_addr16[7]; + } else { + data = pr->dip; + data_m = pr->dip_m; + } + break; + + case TEMPLATE_FIELD_DIP1: + if (pr->is_ipv6) { + data = pr->dip6.s6_addr16[6]; + data_m = pr->dip6_m.s6_addr16[6]; + } else { + data = pr->dip >> 16; + data_m = pr->dip_m >> 16; + } + break; + + case TEMPLATE_FIELD_DIP2: + case TEMPLATE_FIELD_DIP3: + case TEMPLATE_FIELD_DIP4: + case TEMPLATE_FIELD_DIP5: + case TEMPLATE_FIELD_DIP6: + case TEMPLATE_FIELD_DIP7: + data = pr->dip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)]; + data_m = pr->dip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)]; + break; + + case TEMPLATE_FIELD_IP_TOS_PROTO: + data = pr->tos_proto; + data_m = pr->tos_proto_m; + break; + case TEMPLATE_FIELD_L4_SPORT: + data = pr->sport; + data_m = pr->sport_m; + break; + case TEMPLATE_FIELD_L4_DPORT: + data = pr->dport; + data_m = pr->dport_m; + break; + case TEMPLATE_FIELD_ICMP_IGMP: + data = pr->icmp_igmp; + data_m = pr->icmp_igmp_m; + break; + default: + pr_info("%s: unknown field %d\n", __func__, field_type); + continue; + } + if (!(i % 2)) { + r[5 - i / 2] = data; + r[12 - i / 2] = data_m; + } else { + r[5 - i / 2] |= ((u32)data) << 16; + r[12 - i / 2] |= ((u32)data_m) << 16; + } + } +} + +/* + * Creates the intermediate representation of the templated match-fields of the + * PIE rule in the pie_rule structure by reading the raw data fields in the + * raw register space r[]. + * The register space configuration size is identical for the RTL8380/90 and RTL9300, + * however the RTL9310 has 2 more registers / fields and the physical field-ids + */ +static void rtl838x_read_pie_templated(u32 r[], struct pie_rule *pr, enum template_field_id t[]) +{ + int i; + enum template_field_id field_type; + u16 data, data_m; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + field_type = t[i]; + if (!(i % 2)) { + data = r[5 - i / 2]; + data_m = r[12 - i / 2]; + } else { + data = r[5 - i / 2] >> 16; + data_m = r[12 - i / 2] >> 16; + } + + switch (field_type) { + case TEMPLATE_FIELD_SPM0: + pr->spm = (pr->spn << 16) | data; + pr->spm_m = (pr->spn << 16) | data_m; + break; + case TEMPLATE_FIELD_SPM1: + pr->spm = data; + pr->spm_m = data_m; + break; + case TEMPLATE_FIELD_OTAG: + pr->otag = data; + pr->otag_m = data_m; + break; + case TEMPLATE_FIELD_SMAC0: + pr->smac[4] = data >> 8; + pr->smac[5] = data; + pr->smac_m[4] = data >> 8; + pr->smac_m[5] = data; + break; + case TEMPLATE_FIELD_SMAC1: + pr->smac[2] = data >> 8; + pr->smac[3] = data; + pr->smac_m[2] = data >> 8; + pr->smac_m[3] = data; + break; + case TEMPLATE_FIELD_SMAC2: + pr->smac[0] = data >> 8; + pr->smac[1] = data; + pr->smac_m[0] = data >> 8; + pr->smac_m[1] = data; + break; + case TEMPLATE_FIELD_DMAC0: + pr->dmac[4] = data >> 8; + pr->dmac[5] = data; + pr->dmac_m[4] = data >> 8; + pr->dmac_m[5] = data; + break; + case TEMPLATE_FIELD_DMAC1: + pr->dmac[2] = data >> 8; + pr->dmac[3] = data; + pr->dmac_m[2] = data >> 8; + pr->dmac_m[3] = data; + break; + case TEMPLATE_FIELD_DMAC2: + pr->dmac[0] = data >> 8; + pr->dmac[1] = data; + pr->dmac_m[0] = data >> 8; + pr->dmac_m[1] = data; + break; + case TEMPLATE_FIELD_ETHERTYPE: + pr->ethertype = data; + pr->ethertype_m = data_m; + break; + case TEMPLATE_FIELD_ITAG: + pr->itag = data; + pr->itag_m = data_m; + break; + case TEMPLATE_FIELD_RANGE_CHK: + pr->field_range_check = data; + pr->field_range_check_m = data_m; + break; + case TEMPLATE_FIELD_SIP0: + pr->sip = data; + pr->sip_m = data_m; + break; + case TEMPLATE_FIELD_SIP1: + pr->sip = (pr->sip << 16) | data; + pr->sip_m = (pr->sip << 16) | data_m; + break; + case TEMPLATE_FIELD_SIP2: + pr->is_ipv6 = true; + // Make use of limitiations on the position of the match values + ipv6_addr_set(&pr->sip6, pr->sip, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + ipv6_addr_set(&pr->sip6_m, pr->sip_m, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + case TEMPLATE_FIELD_SIP3: + case TEMPLATE_FIELD_SIP4: + case TEMPLATE_FIELD_SIP5: + case TEMPLATE_FIELD_SIP6: + case TEMPLATE_FIELD_SIP7: + break; + + case TEMPLATE_FIELD_DIP0: + pr->dip = data; + pr->dip_m = data_m; + break; + case TEMPLATE_FIELD_DIP1: + pr->dip = (pr->dip << 16) | data; + pr->dip_m = (pr->dip << 16) | data_m; + break; + case TEMPLATE_FIELD_DIP2: + pr->is_ipv6 = true; + ipv6_addr_set(&pr->dip6, pr->dip, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + ipv6_addr_set(&pr->dip6_m, pr->dip_m, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + case TEMPLATE_FIELD_DIP3: + case TEMPLATE_FIELD_DIP4: + case TEMPLATE_FIELD_DIP5: + case TEMPLATE_FIELD_DIP6: + case TEMPLATE_FIELD_DIP7: + break; + case TEMPLATE_FIELD_IP_TOS_PROTO: + pr->tos_proto = data; + pr->tos_proto_m = data_m; + break; + case TEMPLATE_FIELD_L4_SPORT: + pr->sport = data; + pr->sport_m = data_m; + break; + case TEMPLATE_FIELD_L4_DPORT: + pr->dport = data; + pr->dport_m = data_m; + break; + case TEMPLATE_FIELD_ICMP_IGMP: + pr->icmp_igmp = data; + pr->icmp_igmp_m = data_m; + break; + default: + pr_info("%s: unknown field %d\n", __func__, field_type); + } + } +} + +static void rtl838x_read_pie_fixed_fields(u32 r[], struct pie_rule *pr) +{ + pr->spmmask_fix = (r[6] >> 22) & 0x3; + pr->spn = (r[6] >> 16) & 0x3f; + pr->mgnt_vlan = (r[6] >> 15) & 1; + pr->dmac_hit_sw = (r[6] >> 14) & 1; + pr->not_first_frag = (r[6] >> 13) & 1; + pr->frame_type_l4 = (r[6] >> 10) & 7; + pr->frame_type = (r[6] >> 8) & 3; + pr->otag_fmt = (r[6] >> 7) & 1; + pr->itag_fmt = (r[6] >> 6) & 1; + pr->otag_exist = (r[6] >> 5) & 1; + pr->itag_exist = (r[6] >> 4) & 1; + pr->frame_type_l2 = (r[6] >> 2) & 3; + pr->tid = r[6] & 3; + + pr->spmmask_fix_m = (r[13] >> 22) & 0x3; + pr->spn_m = (r[13] >> 16) & 0x3f; + pr->mgnt_vlan_m = (r[13] >> 15) & 1; + pr->dmac_hit_sw_m = (r[13] >> 14) & 1; + pr->not_first_frag_m = (r[13] >> 13) & 1; + pr->frame_type_l4_m = (r[13] >> 10) & 7; + pr->frame_type_m = (r[13] >> 8) & 3; + pr->otag_fmt_m = (r[13] >> 7) & 1; + pr->itag_fmt_m = (r[13] >> 6) & 1; + pr->otag_exist_m = (r[13] >> 5) & 1; + pr->itag_exist_m = (r[13] >> 4) & 1; + pr->frame_type_l2_m = (r[13] >> 2) & 3; + pr->tid_m = r[13] & 3; + + pr->valid = r[14] & BIT(31); + pr->cond_not = r[14] & BIT(30); + pr->cond_and1 = r[14] & BIT(29); + pr->cond_and2 = r[14] & BIT(28); + pr->ivalid = r[14] & BIT(27); + + pr->drop = (r[17] >> 14) & 3; + pr->fwd_sel = r[17] & BIT(13); + pr->ovid_sel = r[17] & BIT(12); + pr->ivid_sel = r[17] & BIT(11); + pr->flt_sel = r[17] & BIT(10); + pr->log_sel = r[17] & BIT(9); + pr->rmk_sel = r[17] & BIT(8); + pr->meter_sel = r[17] & BIT(7); + pr->tagst_sel = r[17] & BIT(6); + pr->mir_sel = r[17] & BIT(5); + pr->nopri_sel = r[17] & BIT(4); + pr->cpupri_sel = r[17] & BIT(3); + pr->otpid_sel = r[17] & BIT(2); + pr->itpid_sel = r[17] & BIT(1); + pr->shaper_sel = r[17] & BIT(0); +} + +static void rtl838x_write_pie_fixed_fields(u32 r[], struct pie_rule *pr) +{ + r[6] = ((u32) (pr->spmmask_fix & 0x3)) << 22; + r[6] |= ((u32) (pr->spn & 0x3f)) << 16; + r[6] |= pr->mgnt_vlan ? BIT(15) : 0; + r[6] |= pr->dmac_hit_sw ? BIT(14) : 0; + r[6] |= pr->not_first_frag ? BIT(13) : 0; + r[6] |= ((u32) (pr->frame_type_l4 & 0x7)) << 10; + r[6] |= ((u32) (pr->frame_type & 0x3)) << 8; + r[6] |= pr->otag_fmt ? BIT(7) : 0; + r[6] |= pr->itag_fmt ? BIT(6) : 0; + r[6] |= pr->otag_exist ? BIT(5) : 0; + r[6] |= pr->itag_exist ? BIT(4) : 0; + r[6] |= ((u32) (pr->frame_type_l2 & 0x3)) << 2; + r[6] |= ((u32) (pr->tid & 0x3)); + + r[13] = ((u32) (pr->spmmask_fix_m & 0x3)) << 22; + r[13] |= ((u32) (pr->spn_m & 0x3f)) << 16; + r[13] |= pr->mgnt_vlan_m ? BIT(15) : 0; + r[13] |= pr->dmac_hit_sw_m ? BIT(14) : 0; + r[13] |= pr->not_first_frag_m ? BIT(13) : 0; + r[13] |= ((u32) (pr->frame_type_l4_m & 0x7)) << 10; + r[13] |= ((u32) (pr->frame_type_m & 0x3)) << 8; + r[13] |= pr->otag_fmt_m ? BIT(7) : 0; + r[13] |= pr->itag_fmt_m ? BIT(6) : 0; + r[13] |= pr->otag_exist_m ? BIT(5) : 0; + r[13] |= pr->itag_exist_m ? BIT(4) : 0; + r[13] |= ((u32) (pr->frame_type_l2_m & 0x3)) << 2; + r[13] |= ((u32) (pr->tid_m & 0x3)); + + r[14] = pr->valid ? BIT(31) : 0; + r[14] |= pr->cond_not ? BIT(30) : 0; + r[14] |= pr->cond_and1 ? BIT(29) : 0; + r[14] |= pr->cond_and2 ? BIT(28) : 0; + r[14] |= pr->ivalid ? BIT(27) : 0; + + if (pr->drop) + r[17] = 0x1 << 14; // Standard drop action + else + r[17] = 0; + r[17] |= pr->fwd_sel ? BIT(13) : 0; + r[17] |= pr->ovid_sel ? BIT(12) : 0; + r[17] |= pr->ivid_sel ? BIT(11) : 0; + r[17] |= pr->flt_sel ? BIT(10) : 0; + r[17] |= pr->log_sel ? BIT(9) : 0; + r[17] |= pr->rmk_sel ? BIT(8) : 0; + r[17] |= pr->meter_sel ? BIT(7) : 0; + r[17] |= pr->tagst_sel ? BIT(6) : 0; + r[17] |= pr->mir_sel ? BIT(5) : 0; + r[17] |= pr->nopri_sel ? BIT(4) : 0; + r[17] |= pr->cpupri_sel ? BIT(3) : 0; + r[17] |= pr->otpid_sel ? BIT(2) : 0; + r[17] |= pr->itpid_sel ? BIT(1) : 0; + r[17] |= pr->shaper_sel ? BIT(0) : 0; +} + +static int rtl838x_write_pie_action(u32 r[], struct pie_rule *pr) +{ + u16 *aif = (u16 *)&r[17]; + u16 data; + int fields_used = 0; + + aif--; + + pr_debug("%s, at %08x\n", __func__, (u32)aif); + /* Multiple actions can be linked to a match of a PIE rule, + * they have different precedence depending on their type and this precedence + * defines which Action Information Field (0-4) in the IACL table stores + * the additional data of the action (like e.g. the port number a packet is + * forwarded to) */ + // TODO: count bits in selectors to limit to a maximum number of actions + if (pr->fwd_sel) { // Forwarding action + data = pr->fwd_act << 13; + data |= pr->fwd_data; + data |= pr->bypass_all ? BIT(12) : 0; + data |= pr->bypass_ibc_sc ? BIT(11) : 0; + data |= pr->bypass_igr_stp ? BIT(10) : 0; + *aif-- = data; + fields_used++; + } + + if (pr->ovid_sel) { // Outer VID action + data = (pr->ovid_act & 0x3) << 12; + data |= pr->ovid_data; + *aif-- = data; + fields_used++; + } + + if (pr->ivid_sel) { // Inner VID action + data = (pr->ivid_act & 0x3) << 12; + data |= pr->ivid_data; + *aif-- = data; + fields_used++; + } + + if (pr->flt_sel) { // Filter action + *aif-- = pr->flt_data; + fields_used++; + } + + if (pr->log_sel) { // Log action + if (fields_used >= 4) + return -1; + *aif-- = pr->log_data; + fields_used++; + } + + if (pr->rmk_sel) { // Remark action + if (fields_used >= 4) + return -1; + *aif-- = pr->rmk_data; + fields_used++; + } + + if (pr->meter_sel) { // Meter action + if (fields_used >= 4) + return -1; + *aif-- = pr->meter_data; + fields_used++; + } + + if (pr->tagst_sel) { // Egress Tag Status action + if (fields_used >= 4) + return -1; + *aif-- = pr->tagst_data; + fields_used++; + } + + if (pr->mir_sel) { // Mirror action + if (fields_used >= 4) + return -1; + *aif-- = pr->mir_data; + fields_used++; + } + + if (pr->nopri_sel) { // Normal Priority action + if (fields_used >= 4) + return -1; + *aif-- = pr->nopri_data; + fields_used++; + } + + if (pr->cpupri_sel) { // CPU Priority action + if (fields_used >= 4) + return -1; + *aif-- = pr->nopri_data; + fields_used++; + } + + if (pr->otpid_sel) { // OTPID action + if (fields_used >= 4) + return -1; + *aif-- = pr->otpid_data; + fields_used++; + } + + if (pr->itpid_sel) { // ITPID action + if (fields_used >= 4) + return -1; + *aif-- = pr->itpid_data; + fields_used++; + } + + if (pr->shaper_sel) { // Traffic shaper action + if (fields_used >= 4) + return -1; + *aif-- = pr->shaper_data; + fields_used++; + } + + return 0; +} + +static void rtl838x_read_pie_action(u32 r[], struct pie_rule *pr) +{ + u16 *aif = (u16 *)&r[17]; + + aif--; + + pr_debug("%s, at %08x\n", __func__, (u32)aif); + if (pr->drop) + pr_debug("%s: Action Drop: %d", __func__, pr->drop); + + if (pr->fwd_sel){ // Forwarding action + pr->fwd_act = *aif >> 13; + pr->fwd_data = *aif--; + pr->bypass_all = pr->fwd_data & BIT(12); + pr->bypass_ibc_sc = pr->fwd_data & BIT(11); + pr->bypass_igr_stp = pr->fwd_data & BIT(10); + if (pr->bypass_all || pr->bypass_ibc_sc || pr->bypass_igr_stp) + pr->bypass_sel = true; + } + if (pr->ovid_sel) // Outer VID action + pr->ovid_data = *aif--; + if (pr->ivid_sel) // Inner VID action + pr->ivid_data = *aif--; + if (pr->flt_sel) // Filter action + pr->flt_data = *aif--; + if (pr->log_sel) // Log action + pr->log_data = *aif--; + if (pr->rmk_sel) // Remark action + pr->rmk_data = *aif--; + if (pr->meter_sel) // Meter action + pr->meter_data = *aif--; + if (pr->tagst_sel) // Egress Tag Status action + pr->tagst_data = *aif--; + if (pr->mir_sel) // Mirror action + pr->mir_data = *aif--; + if (pr->nopri_sel) // Normal Priority action + pr->nopri_data = *aif--; + if (pr->cpupri_sel) // CPU Priority action + pr->nopri_data = *aif--; + if (pr->otpid_sel) // OTPID action + pr->otpid_data = *aif--; + if (pr->itpid_sel) // ITPID action + pr->itpid_data = *aif--; + if (pr->shaper_sel) // Traffic shaper action + pr->shaper_data = *aif--; +} + +static void rtl838x_pie_rule_dump_raw(u32 r[]) +{ + pr_info("Raw IACL table entry:\n"); + pr_info("Match : %08x %08x %08x %08x %08x %08x\n", r[0], r[1], r[2], r[3], r[4], r[5]); + pr_info("Fixed : %08x\n", r[6]); + pr_info("Match M: %08x %08x %08x %08x %08x %08x\n", r[7], r[8], r[9], r[10], r[11], r[12]); + pr_info("Fixed M: %08x\n", r[13]); + pr_info("AIF : %08x %08x %08x\n", r[14], r[15], r[16]); + pr_info("Sel : %08x\n", r[17]); +} + +static void rtl838x_pie_rule_dump(struct pie_rule *pr) +{ + pr_info("Drop: %d, fwd: %d, ovid: %d, ivid: %d, flt: %d, log: %d, rmk: %d, meter: %d tagst: %d, mir: %d, nopri: %d, cpupri: %d, otpid: %d, itpid: %d, shape: %d\n", + pr->drop, pr->fwd_sel, pr->ovid_sel, pr->ivid_sel, pr->flt_sel, pr->log_sel, pr->rmk_sel, pr->log_sel, pr->tagst_sel, pr->mir_sel, pr->nopri_sel, + pr->cpupri_sel, pr->otpid_sel, pr->itpid_sel, pr->shaper_sel); + if (pr->fwd_sel) + pr_info("FWD: %08x\n", pr->fwd_data); + pr_info("TID: %x, %x\n", pr->tid, pr->tid_m); +} + +static int rtl838x_pie_rule_read(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr) +{ + // Read IACL table (1) via register 0 + struct table_reg *q = rtl_table_get(RTL8380_TBL_0, 1); + u32 r[18]; + int i; + int block = idx / PIE_BLOCK_SIZE; + u32 t_select = sw_r32(RTL838X_ACL_BLK_TMPLTE_CTRL(block)); + + memset(pr, 0, sizeof(*pr)); + rtl_table_read(q, idx); + for (i = 0; i < 18; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl838x_read_pie_fixed_fields(r, pr); + if (!pr->valid) + return 0; + + pr_info("%s: template_selectors %08x, tid: %d\n", __func__, t_select, pr->tid); + rtl838x_pie_rule_dump_raw(r); + + rtl838x_read_pie_templated(r, pr, fixed_templates[(t_select >> (pr->tid * 3)) & 0x7]); + + rtl838x_read_pie_action(r, pr); + + return 0; +} + +static int rtl838x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr) +{ + // Access IACL table (1) via register 0 + struct table_reg *q = rtl_table_get(RTL8380_TBL_0, 1); + u32 r[18]; + int i, err = 0; + int block = idx / PIE_BLOCK_SIZE; + u32 t_select = sw_r32(RTL838X_ACL_BLK_TMPLTE_CTRL(block)); + + pr_debug("%s: %d, t_select: %08x\n", __func__, idx, t_select); + + for (i = 0; i < 18; i++) + r[i] = 0; + + if (!pr->valid) + goto err_out; + + rtl838x_write_pie_fixed_fields(r, pr); + + pr_debug("%s: template %d\n", __func__, (t_select >> (pr->tid * 3)) & 0x7); + rtl838x_write_pie_templated(r, pr, fixed_templates[(t_select >> (pr->tid * 3)) & 0x7]); + + if (rtl838x_write_pie_action(r, pr)) { + pr_err("Rule actions too complex\n"); + goto err_out; + } + +// rtl838x_pie_rule_dump_raw(r); + + for (i = 0; i < 18; i++) + sw_w32(r[i], rtl_table_data(q, i)); + +err_out: + rtl_table_write(q, idx); + rtl_table_release(q); + + return err; +} + +static bool rtl838x_pie_templ_has(int t, enum template_field_id field_type) +{ + int i; + enum template_field_id ft; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + ft = fixed_templates[t][i]; + if (field_type == ft) + return true; + } + + return false; +} + +static int rtl838x_pie_verify_template(struct rtl838x_switch_priv *priv, + struct pie_rule *pr, int t, int block) +{ + int i; + + if (!pr->is_ipv6 && pr->sip_m && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_SIP0)) + return -1; + + if (!pr->is_ipv6 && pr->dip_m && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_DIP0)) + return -1; + + if (pr->is_ipv6) { + if ((pr->sip6_m.s6_addr32[0] || pr->sip6_m.s6_addr32[1] + || pr->sip6_m.s6_addr32[2] || pr->sip6_m.s6_addr32[3]) + && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_SIP2)) + return -1; + if ((pr->dip6_m.s6_addr32[0] || pr->dip6_m.s6_addr32[1] + || pr->dip6_m.s6_addr32[2] || pr->dip6_m.s6_addr32[3]) + && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_DIP2)) + return -1; + } + + if (ether_addr_to_u64(pr->smac) && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_SMAC0)) + return -1; + + if (ether_addr_to_u64(pr->dmac) && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0)) + return -1; + + // TODO: Check more + + i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE); + + if (i >= PIE_BLOCK_SIZE) + return -1; + + return i + PIE_BLOCK_SIZE * block; +} + +static int rtl838x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rule *pr) +{ + int idx, block, j, t; + + pr_debug("In %s\n", __func__); + + mutex_lock(&priv->pie_mutex); + + for (block = 0; block < priv->n_pie_blocks; block++) { + for (j = 0; j < 3; j++) { + t = (sw_r32(RTL838X_ACL_BLK_TMPLTE_CTRL(block)) >> (j * 3)) & 0x7; + pr_debug("Testing block %d, template %d, template id %d\n", block, j, t); + idx = rtl838x_pie_verify_template(priv, pr, t, block); + if (idx >= 0) + break; + } + if (j < 3) + break; + } + + if (block >= priv->n_pie_blocks) { + mutex_unlock(&priv->pie_mutex); + return -EOPNOTSUPP; + } + + pr_debug("Using block: %d, index %d, template-id %d\n", block, idx, j); + set_bit(idx, priv->pie_use_bm); + + pr->valid = true; + pr->tid = j; // Mapped to template number + pr->tid_m = 0x3; + pr->id = idx; + + rtl838x_pie_lookup_enable(priv, idx); + rtl838x_pie_rule_write(priv, idx, pr); + + mutex_unlock(&priv->pie_mutex); + return 0; +} + +static void rtl838x_pie_rule_rm(struct rtl838x_switch_priv *priv, struct pie_rule *pr) +{ + int idx = pr->id; + + rtl838x_pie_rule_del(priv, idx, idx); + clear_bit(idx, priv->pie_use_bm); +} + +/* + * Initializes the Packet Inspection Engine: + * powers it up, enables default matching templates for all blocks + * and clears all rules possibly installed by u-boot + */ +static void rtl838x_pie_init(struct rtl838x_switch_priv *priv) +{ + int i; + u32 template_selectors; + + mutex_init(&priv->pie_mutex); + + // Enable ACL lookup on all ports, including CPU_PORT + for (i = 0; i <= priv->cpu_port; i++) + sw_w32(1, RTL838X_ACL_PORT_LOOKUP_CTRL(i)); + + // Power on all PIE blocks + for (i = 0; i < priv->n_pie_blocks; i++) + sw_w32_mask(0, BIT(i), RTL838X_ACL_BLK_PWR_CTRL); + + // Include IPG in metering + sw_w32(1, RTL838X_METER_GLB_CTRL); + + // Delete all present rules + rtl838x_pie_rule_del(priv, 0, priv->n_pie_blocks * PIE_BLOCK_SIZE - 1); + + // Routing bypasses source port filter: disable write-protection, first + sw_w32_mask(0, 3, RTL838X_INT_RW_CTRL); + sw_w32_mask(0, 1, RTL838X_DMY_REG27); + sw_w32_mask(3, 0, RTL838X_INT_RW_CTRL); + + // Enable predefined templates 0, 1 and 2 for even blocks + template_selectors = 0 | (1 << 3) | (2 << 6); + for (i = 0; i < 6; i += 2) + sw_w32(template_selectors, RTL838X_ACL_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 0, 3 and 4 (IPv6 support) for odd blocks + template_selectors = 0 | (3 << 3) | (4 << 6); + for (i = 1; i < priv->n_pie_blocks; i += 2) + sw_w32(template_selectors, RTL838X_ACL_BLK_TMPLTE_CTRL(i)); + + // Group each pair of physical blocks together to a logical block + sw_w32(0b10101010101, RTL838X_ACL_BLK_GROUP_CTRL); +} + +static u32 rtl838x_packet_cntr_read(int counter) +{ + u32 v; + + // Read LOG table (3) via register RTL8380_TBL_0 + struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 3); + + pr_debug("In %s, id %d\n", __func__, counter); + rtl_table_read(r, counter / 2); + + pr_debug("Registers: %08x %08x\n", + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1))); + // The table has a size of 2 registers + if (counter % 2) + v = sw_r32(rtl_table_data(r, 0)); + else + v = sw_r32(rtl_table_data(r, 1)); + + rtl_table_release(r); + + return v; +} + +static void rtl838x_packet_cntr_clear(int counter) +{ + // Access LOG table (3) via register RTL8380_TBL_0 + struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 3); + + pr_debug("In %s, id %d\n", __func__, counter); + // The table has a size of 2 registers + if (counter % 2) + sw_w32(0, rtl_table_data(r, 0)); + else + sw_w32(0, rtl_table_data(r, 1)); + + rtl_table_write(r, counter / 2); + + rtl_table_release(r); +} + const struct rtl838x_reg rtl838x_reg = { .mask_port_reg_be = rtl838x_mask_port_reg, .set_port_reg_be = rtl838x_set_port_reg, @@ -600,6 +1600,13 @@ const struct rtl838x_reg rtl838x_reg = { .l2_hash_key = rtl838x_l2_hash_key, .read_mcast_pmask = rtl838x_read_mcast_pmask, .write_mcast_pmask = rtl838x_write_mcast_pmask, + .pie_init = rtl838x_pie_init, + .pie_rule_read = rtl838x_pie_rule_read, + .pie_rule_write = rtl838x_pie_rule_write, + .pie_rule_add = rtl838x_pie_rule_add, + .pie_rule_rm = rtl838x_pie_rule_rm, + .packet_cntr_read = rtl838x_packet_cntr_read, + .packet_cntr_clear = rtl838x_packet_cntr_clear, }; irqreturn_t rtl838x_switch_irq(int irq, void *dev_id) From 2d8d81fe2897586b5ca0e78997c448899ae1e8a5 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Tue, 7 Sep 2021 18:51:10 +0200 Subject: [PATCH 17/59] realtek: Packet Inspection Engine support for RTL839x SoCs Adds the RTL839x-specific PIE support routines. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/rtl839x.c | 875 ++++++++++++++++++ 1 file changed, 875 insertions(+) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c index c62dc441c1..8faf6c07e9 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c @@ -6,6 +6,104 @@ extern struct mutex smi_lock; extern struct rtl83xx_soc_info soc_info; +/* Definition of the RTL839X-specific template field IDs as used in the PIE */ +enum template_field_id { + TEMPLATE_FIELD_SPMMASK = 0, + TEMPLATE_FIELD_SPM0 = 1, // Source portmask ports 0-15 + TEMPLATE_FIELD_SPM1 = 2, // Source portmask ports 16-31 + TEMPLATE_FIELD_SPM2 = 3, // Source portmask ports 32-47 + TEMPLATE_FIELD_SPM3 = 4, // Source portmask ports 48-56 + TEMPLATE_FIELD_DMAC0 = 5, // Destination MAC [15:0] + TEMPLATE_FIELD_DMAC1 = 6, // Destination MAC [31:16] + TEMPLATE_FIELD_DMAC2 = 7, // Destination MAC [47:32] + TEMPLATE_FIELD_SMAC0 = 8, // Source MAC [15:0] + TEMPLATE_FIELD_SMAC1 = 9, // Source MAC [31:16] + TEMPLATE_FIELD_SMAC2 = 10, // Source MAC [47:32] + TEMPLATE_FIELD_ETHERTYPE = 11, // Ethernet frame type field + // Field-ID 12 is not used + TEMPLATE_FIELD_OTAG = 13, + TEMPLATE_FIELD_ITAG = 14, + TEMPLATE_FIELD_SIP0 = 15, + TEMPLATE_FIELD_SIP1 = 16, + TEMPLATE_FIELD_DIP0 = 17, + TEMPLATE_FIELD_DIP1 = 18, + TEMPLATE_FIELD_IP_TOS_PROTO = 19, + TEMPLATE_FIELD_IP_FLAG = 20, + TEMPLATE_FIELD_L4_SPORT = 21, + TEMPLATE_FIELD_L4_DPORT = 22, + TEMPLATE_FIELD_L34_HEADER = 23, + TEMPLATE_FIELD_ICMP_IGMP = 24, + TEMPLATE_FIELD_VID_RANG0 = 25, + TEMPLATE_FIELD_VID_RANG1 = 26, + TEMPLATE_FIELD_L4_PORT_RANG = 27, + TEMPLATE_FIELD_FIELD_SELECTOR_VALID = 28, + TEMPLATE_FIELD_FIELD_SELECTOR_0 = 29, + TEMPLATE_FIELD_FIELD_SELECTOR_1 = 30, + TEMPLATE_FIELD_FIELD_SELECTOR_2 = 31, + TEMPLATE_FIELD_FIELD_SELECTOR_3 = 32, + TEMPLATE_FIELD_FIELD_SELECTOR_4 = 33, + TEMPLATE_FIELD_FIELD_SELECTOR_5 = 34, + TEMPLATE_FIELD_SIP2 = 35, + TEMPLATE_FIELD_SIP3 = 36, + TEMPLATE_FIELD_SIP4 = 37, + TEMPLATE_FIELD_SIP5 = 38, + TEMPLATE_FIELD_SIP6 = 39, + TEMPLATE_FIELD_SIP7 = 40, + TEMPLATE_FIELD_OLABEL = 41, + TEMPLATE_FIELD_ILABEL = 42, + TEMPLATE_FIELD_OILABEL = 43, + TEMPLATE_FIELD_DPMMASK = 44, + TEMPLATE_FIELD_DPM0 = 45, + TEMPLATE_FIELD_DPM1 = 46, + TEMPLATE_FIELD_DPM2 = 47, + TEMPLATE_FIELD_DPM3 = 48, + TEMPLATE_FIELD_L2DPM0 = 49, + TEMPLATE_FIELD_L2DPM1 = 50, + TEMPLATE_FIELD_L2DPM2 = 51, + TEMPLATE_FIELD_L2DPM3 = 52, + TEMPLATE_FIELD_IVLAN = 53, + TEMPLATE_FIELD_OVLAN = 54, + TEMPLATE_FIELD_FWD_VID = 55, + TEMPLATE_FIELD_DIP2 = 56, + TEMPLATE_FIELD_DIP3 = 57, + TEMPLATE_FIELD_DIP4 = 58, + TEMPLATE_FIELD_DIP5 = 59, + TEMPLATE_FIELD_DIP6 = 60, + TEMPLATE_FIELD_DIP7 = 61, +}; + +// Number of fixed templates predefined in the SoC +#define N_FIXED_TEMPLATES 5 +static enum template_field_id fixed_templates[N_FIXED_TEMPLATES][N_FIXED_FIELDS] = +{ + { + TEMPLATE_FIELD_SPM0, TEMPLATE_FIELD_SPM1, TEMPLATE_FIELD_ITAG, + TEMPLATE_FIELD_SMAC0, TEMPLATE_FIELD_SMAC1, TEMPLATE_FIELD_SMAC2, + TEMPLATE_FIELD_DMAC0, TEMPLATE_FIELD_DMAC1, TEMPLATE_FIELD_DMAC2, + TEMPLATE_FIELD_ETHERTYPE, TEMPLATE_FIELD_SPM2, TEMPLATE_FIELD_SPM3 + }, { + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_DIP0, + TEMPLATE_FIELD_DIP1,TEMPLATE_FIELD_IP_TOS_PROTO, TEMPLATE_FIELD_L4_SPORT, + TEMPLATE_FIELD_L4_DPORT, TEMPLATE_FIELD_ICMP_IGMP, TEMPLATE_FIELD_SPM0, + TEMPLATE_FIELD_SPM1, TEMPLATE_FIELD_SPM2, TEMPLATE_FIELD_SPM3 + }, { + TEMPLATE_FIELD_DMAC0, TEMPLATE_FIELD_DMAC1, TEMPLATE_FIELD_DMAC2, + TEMPLATE_FIELD_ITAG, TEMPLATE_FIELD_ETHERTYPE, TEMPLATE_FIELD_IP_TOS_PROTO, + TEMPLATE_FIELD_L4_DPORT, TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_SIP0, + TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_DIP0, TEMPLATE_FIELD_DIP1 + }, { + TEMPLATE_FIELD_DIP0, TEMPLATE_FIELD_DIP1, TEMPLATE_FIELD_DIP2, + TEMPLATE_FIELD_DIP3, TEMPLATE_FIELD_DIP4, TEMPLATE_FIELD_DIP5, + TEMPLATE_FIELD_DIP6, TEMPLATE_FIELD_DIP7, TEMPLATE_FIELD_L4_DPORT, + TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_ICMP_IGMP, TEMPLATE_FIELD_IP_TOS_PROTO + }, { + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_SIP2, + TEMPLATE_FIELD_SIP3, TEMPLATE_FIELD_SIP4, TEMPLATE_FIELD_SIP5, + TEMPLATE_FIELD_SIP6, TEMPLATE_FIELD_SIP7, TEMPLATE_FIELD_SPM0, + TEMPLATE_FIELD_SPM1, TEMPLATE_FIELD_SPM2, TEMPLATE_FIELD_SPM3 + }, +}; + void rtl839x_print_matrix(void) { volatile u64 *ptr9; @@ -739,6 +837,776 @@ static void rtl839x_init_eee(struct rtl838x_switch_priv *priv, bool enable) priv->eee_enabled = enable; } +static void rtl839x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index) +{ + int block = index / PIE_BLOCK_SIZE; + + sw_w32_mask(0, BIT(block), RTL839X_ACL_BLK_LOOKUP_CTRL); +} + +/* + * Delete a range of Packet Inspection Engine rules + */ +static int rtl839x_pie_rule_del(struct rtl838x_switch_priv *priv, int index_from, int index_to) +{ + u32 v = (index_from << 1)| (index_to << 13 ) | BIT(0); + + pr_debug("%s: from %d to %d\n", __func__, index_from, index_to); + mutex_lock(&priv->reg_mutex); + + // Write from-to and execute bit into control register + sw_w32(v, RTL839X_ACL_CLR_CTRL); + + // Wait until command has completed + do { + } while (sw_r32(RTL839X_ACL_CLR_CTRL) & BIT(0)); + + mutex_unlock(&priv->reg_mutex); + return 0; +} + +/* + * Reads the intermediate representation of the templated match-fields of the + * PIE rule in the pie_rule structure and fills in the raw data fields in the + * raw register space r[]. + * The register space configuration size is identical for the RTL8380/90 and RTL9300, + * however the RTL9310 has 2 more registers / fields and the physical field-ids are different + * on all SoCs + * On the RTL8390 the template mask registers are not word-aligned! + */ +static void rtl839x_write_pie_templated(u32 r[], struct pie_rule *pr, enum template_field_id t[]) +{ + int i; + enum template_field_id field_type; + u16 data, data_m; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + field_type = t[i]; + data = data_m = 0; + + switch (field_type) { + case TEMPLATE_FIELD_SPM0: + data = pr->spm; + data_m = pr->spm_m; + break; + case TEMPLATE_FIELD_SPM1: + data = pr->spm >> 16; + data_m = pr->spm_m >> 16; + break; + case TEMPLATE_FIELD_SPM2: + data = pr->spm >> 32; + data_m = pr->spm_m >> 32; + break; + case TEMPLATE_FIELD_SPM3: + data = pr->spm >> 48; + data_m = pr->spm_m >> 48; + break; + case TEMPLATE_FIELD_OTAG: + data = pr->otag; + data_m = pr->otag_m; + break; + case TEMPLATE_FIELD_SMAC0: + data = pr->smac[4]; + data = (data << 8) | pr->smac[5]; + data_m = pr->smac_m[4]; + data_m = (data_m << 8) | pr->smac_m[5]; + break; + case TEMPLATE_FIELD_SMAC1: + data = pr->smac[2]; + data = (data << 8) | pr->smac[3]; + data_m = pr->smac_m[2]; + data_m = (data_m << 8) | pr->smac_m[3]; + break; + case TEMPLATE_FIELD_SMAC2: + data = pr->smac[0]; + data = (data << 8) | pr->smac[1]; + data_m = pr->smac_m[0]; + data_m = (data_m << 8) | pr->smac_m[1]; + break; + case TEMPLATE_FIELD_DMAC0: + data = pr->dmac[4]; + data = (data << 8) | pr->dmac[5]; + data_m = pr->dmac_m[4]; + data_m = (data_m << 8) | pr->dmac_m[5]; + break; + case TEMPLATE_FIELD_DMAC1: + data = pr->dmac[2]; + data = (data << 8) | pr->dmac[3]; + data_m = pr->dmac_m[2]; + data_m = (data_m << 8) | pr->dmac_m[3]; + break; + case TEMPLATE_FIELD_DMAC2: + data = pr->dmac[0]; + data = (data << 8) | pr->dmac[1]; + data_m = pr->dmac_m[0]; + data_m = (data_m << 8) | pr->dmac_m[1]; + break; + case TEMPLATE_FIELD_ETHERTYPE: + data = pr->ethertype; + data_m = pr->ethertype_m; + break; + case TEMPLATE_FIELD_ITAG: + data = pr->itag; + data_m = pr->itag_m; + break; + case TEMPLATE_FIELD_SIP0: + if (pr->is_ipv6) { + data = pr->sip6.s6_addr16[7]; + data_m = pr->sip6_m.s6_addr16[7]; + } else { + data = pr->sip; + data_m = pr->sip_m; + } + break; + case TEMPLATE_FIELD_SIP1: + if (pr->is_ipv6) { + data = pr->sip6.s6_addr16[6]; + data_m = pr->sip6_m.s6_addr16[6]; + } else { + data = pr->sip >> 16; + data_m = pr->sip_m >> 16; + } + break; + + case TEMPLATE_FIELD_SIP2: + case TEMPLATE_FIELD_SIP3: + case TEMPLATE_FIELD_SIP4: + case TEMPLATE_FIELD_SIP5: + case TEMPLATE_FIELD_SIP6: + case TEMPLATE_FIELD_SIP7: + data = pr->sip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)]; + data_m = pr->sip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)]; + break; + + case TEMPLATE_FIELD_DIP0: + if (pr->is_ipv6) { + data = pr->dip6.s6_addr16[7]; + data_m = pr->dip6_m.s6_addr16[7]; + } else { + data = pr->dip; + data_m = pr->dip_m; + } + break; + + case TEMPLATE_FIELD_DIP1: + if (pr->is_ipv6) { + data = pr->dip6.s6_addr16[6]; + data_m = pr->dip6_m.s6_addr16[6]; + } else { + data = pr->dip >> 16; + data_m = pr->dip_m >> 16; + } + break; + + case TEMPLATE_FIELD_DIP2: + case TEMPLATE_FIELD_DIP3: + case TEMPLATE_FIELD_DIP4: + case TEMPLATE_FIELD_DIP5: + case TEMPLATE_FIELD_DIP6: + case TEMPLATE_FIELD_DIP7: + data = pr->dip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)]; + data_m = pr->dip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)]; + break; + + case TEMPLATE_FIELD_IP_TOS_PROTO: + data = pr->tos_proto; + data_m = pr->tos_proto_m; + break; + case TEMPLATE_FIELD_L4_SPORT: + data = pr->sport; + data_m = pr->sport_m; + break; + case TEMPLATE_FIELD_L4_DPORT: + data = pr->dport; + data_m = pr->dport_m; + break; + case TEMPLATE_FIELD_ICMP_IGMP: + data = pr->icmp_igmp; + data_m = pr->icmp_igmp_m; + break; + default: + pr_info("%s: unknown field %d\n", __func__, field_type); + } + + // On the RTL8390, the mask fields are not word aligned! + if (!(i % 2)) { + r[5 - i / 2] = data; + r[12 - i / 2] |= ((u32)data_m << 8); + } else { + r[5 - i / 2] |= ((u32)data) << 16; + r[12 - i / 2] |= ((u32)data_m) << 24; + r[11 - i / 2] |= ((u32)data_m) >> 8; + } + } +} + +/* + * Creates the intermediate representation of the templated match-fields of the + * PIE rule in the pie_rule structure by reading the raw data fields in the + * raw register space r[]. + * The register space configuration size is identical for the RTL8380/90 and RTL9300, + * however the RTL9310 has 2 more registers / fields and the physical field-ids + * On the RTL8390 the template mask registers are not word-aligned! + */ +void rtl839x_read_pie_templated(u32 r[], struct pie_rule *pr, enum template_field_id t[]) +{ + int i; + enum template_field_id field_type; + u16 data, data_m; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + field_type = t[i]; + if (!(i % 2)) { + data = r[5 - i / 2]; + data_m = r[12 - i / 2]; + } else { + data = r[5 - i / 2] >> 16; + data_m = r[12 - i / 2] >> 16; + } + + switch (field_type) { + case TEMPLATE_FIELD_SPM0: + pr->spm = (pr->spn << 16) | data; + pr->spm_m = (pr->spn << 16) | data_m; + break; + case TEMPLATE_FIELD_SPM1: + pr->spm = data; + pr->spm_m = data_m; + break; + case TEMPLATE_FIELD_OTAG: + pr->otag = data; + pr->otag_m = data_m; + break; + case TEMPLATE_FIELD_SMAC0: + pr->smac[4] = data >> 8; + pr->smac[5] = data; + pr->smac_m[4] = data >> 8; + pr->smac_m[5] = data; + break; + case TEMPLATE_FIELD_SMAC1: + pr->smac[2] = data >> 8; + pr->smac[3] = data; + pr->smac_m[2] = data >> 8; + pr->smac_m[3] = data; + break; + case TEMPLATE_FIELD_SMAC2: + pr->smac[0] = data >> 8; + pr->smac[1] = data; + pr->smac_m[0] = data >> 8; + pr->smac_m[1] = data; + break; + case TEMPLATE_FIELD_DMAC0: + pr->dmac[4] = data >> 8; + pr->dmac[5] = data; + pr->dmac_m[4] = data >> 8; + pr->dmac_m[5] = data; + break; + case TEMPLATE_FIELD_DMAC1: + pr->dmac[2] = data >> 8; + pr->dmac[3] = data; + pr->dmac_m[2] = data >> 8; + pr->dmac_m[3] = data; + break; + case TEMPLATE_FIELD_DMAC2: + pr->dmac[0] = data >> 8; + pr->dmac[1] = data; + pr->dmac_m[0] = data >> 8; + pr->dmac_m[1] = data; + break; + case TEMPLATE_FIELD_ETHERTYPE: + pr->ethertype = data; + pr->ethertype_m = data_m; + break; + case TEMPLATE_FIELD_ITAG: + pr->itag = data; + pr->itag_m = data_m; + break; + case TEMPLATE_FIELD_SIP0: + pr->sip = data; + pr->sip_m = data_m; + break; + case TEMPLATE_FIELD_SIP1: + pr->sip = (pr->sip << 16) | data; + pr->sip_m = (pr->sip << 16) | data_m; + break; + case TEMPLATE_FIELD_SIP2: + pr->is_ipv6 = true; + // Make use of limitiations on the position of the match values + ipv6_addr_set(&pr->sip6, pr->sip, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + ipv6_addr_set(&pr->sip6_m, pr->sip_m, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + case TEMPLATE_FIELD_SIP3: + case TEMPLATE_FIELD_SIP4: + case TEMPLATE_FIELD_SIP5: + case TEMPLATE_FIELD_SIP6: + case TEMPLATE_FIELD_SIP7: + break; + + case TEMPLATE_FIELD_DIP0: + pr->dip = data; + pr->dip_m = data_m; + break; + + case TEMPLATE_FIELD_DIP1: + pr->dip = (pr->dip << 16) | data; + pr->dip_m = (pr->dip << 16) | data_m; + break; + + case TEMPLATE_FIELD_DIP2: + pr->is_ipv6 = true; + ipv6_addr_set(&pr->dip6, pr->dip, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + ipv6_addr_set(&pr->dip6_m, pr->dip_m, r[5 - i / 2], + r[4 - i / 2], r[3 - i / 2]); + case TEMPLATE_FIELD_DIP3: + case TEMPLATE_FIELD_DIP4: + case TEMPLATE_FIELD_DIP5: + case TEMPLATE_FIELD_DIP6: + case TEMPLATE_FIELD_DIP7: + break; + case TEMPLATE_FIELD_IP_TOS_PROTO: + pr->tos_proto = data; + pr->tos_proto_m = data_m; + break; + case TEMPLATE_FIELD_L4_SPORT: + pr->sport = data; + pr->sport_m = data_m; + break; + case TEMPLATE_FIELD_L4_DPORT: + pr->dport = data; + pr->dport_m = data_m; + break; + case TEMPLATE_FIELD_ICMP_IGMP: + pr->icmp_igmp = data; + pr->icmp_igmp_m = data_m; + break; + default: + pr_info("%s: unknown field %d\n", __func__, field_type); + } + } +} + +static void rtl839x_read_pie_fixed_fields(u32 r[], struct pie_rule *pr) +{ + pr->spmmask_fix = (r[6] >> 30) & 0x3; + pr->spn = (r[6] >> 24) & 0x3f; + pr->mgnt_vlan = (r[6] >> 23) & 1; + pr->dmac_hit_sw = (r[6] >> 22) & 1; + pr->not_first_frag = (r[6] >> 21) & 1; + pr->frame_type_l4 = (r[6] >> 18) & 7; + pr->frame_type = (r[6] >> 16) & 3; + pr->otag_fmt = (r[6] >> 15) & 1; + pr->itag_fmt = (r[6] >> 14) & 1; + pr->otag_exist = (r[6] >> 13) & 1; + pr->itag_exist = (r[6] >> 12) & 1; + pr->frame_type_l2 = (r[6] >> 10) & 3; + pr->tid = (r[6] >> 8) & 3; + + pr->spmmask_fix_m = (r[12] >> 6) & 0x3; + pr->spn_m = r[12] & 0x3f; + pr->mgnt_vlan_m = (r[13] >> 31) & 1; + pr->dmac_hit_sw_m = (r[13] >> 30) & 1; + pr->not_first_frag_m = (r[13] >> 29) & 1; + pr->frame_type_l4_m = (r[13] >> 26) & 7; + pr->frame_type_m = (r[13] >> 24) & 3; + pr->otag_fmt_m = (r[13] >> 23) & 1; + pr->itag_fmt_m = (r[13] >> 22) & 1; + pr->otag_exist_m = (r[13] >> 21) & 1; + pr->itag_exist_m = (r[13] >> 20) & 1; + pr->frame_type_l2_m = (r[13] >> 18) & 3; + pr->tid_m = (r[13] >> 16) & 3; + + pr->valid = r[13] & BIT(15); + pr->cond_not = r[13] & BIT(14); + pr->cond_and1 = r[13] & BIT(13); + pr->cond_and2 = r[13] & BIT(12); +} + +static void rtl839x_write_pie_fixed_fields(u32 r[], struct pie_rule *pr) +{ + r[6] = ((u32) (pr->spmmask_fix & 0x3)) << 30; + r[6] |= ((u32) (pr->spn & 0x3f)) << 24; + r[6] |= pr->mgnt_vlan ? BIT(23) : 0; + r[6] |= pr->dmac_hit_sw ? BIT(22) : 0; + r[6] |= pr->not_first_frag ? BIT(21) : 0; + r[6] |= ((u32) (pr->frame_type_l4 & 0x7)) << 18; + r[6] |= ((u32) (pr->frame_type & 0x3)) << 16; + r[6] |= pr->otag_fmt ? BIT(15) : 0; + r[6] |= pr->itag_fmt ? BIT(14) : 0; + r[6] |= pr->otag_exist ? BIT(13) : 0; + r[6] |= pr->itag_exist ? BIT(12) : 0; + r[6] |= ((u32) (pr->frame_type_l2 & 0x3)) << 10; + r[6] |= ((u32) (pr->tid & 0x3)) << 8; + + r[12] |= ((u32) (pr->spmmask_fix_m & 0x3)) << 6; + r[12] |= (u32) (pr->spn_m & 0x3f); + r[13] |= pr->mgnt_vlan_m ? BIT(31) : 0; + r[13] |= pr->dmac_hit_sw_m ? BIT(30) : 0; + r[13] |= pr->not_first_frag_m ? BIT(29) : 0; + r[13] |= ((u32) (pr->frame_type_l4_m & 0x7)) << 26; + r[13] |= ((u32) (pr->frame_type_m & 0x3)) << 24; + r[13] |= pr->otag_fmt_m ? BIT(23) : 0; + r[13] |= pr->itag_fmt_m ? BIT(22) : 0; + r[13] |= pr->otag_exist_m ? BIT(21) : 0; + r[13] |= pr->itag_exist_m ? BIT(20) : 0; + r[13] |= ((u32) (pr->frame_type_l2_m & 0x3)) << 18; + r[13] |= ((u32) (pr->tid_m & 0x3)) << 16; + + r[13] |= pr->valid ? BIT(15) : 0; + r[13] |= pr->cond_not ? BIT(14) : 0; + r[13] |= pr->cond_and1 ? BIT(13) : 0; + r[13] |= pr->cond_and2 ? BIT(12) : 0; +} + +static void rtl839x_write_pie_action(u32 r[], struct pie_rule *pr) +{ + if (pr->drop) { + r[13] |= 0x9; // Set ACT_MASK_FWD & FWD_ACT = DROP + r[13] |= BIT(3); + } else { + r[13] |= pr->fwd_sel ? BIT(3) : 0; + r[13] |= pr->fwd_act; + } + r[13] |= pr->bypass_sel ? BIT(11) : 0; + r[13] |= pr->mpls_sel ? BIT(10) : 0; + r[13] |= pr->nopri_sel ? BIT(9) : 0; + r[13] |= pr->ovid_sel ? BIT(8) : 0; + r[13] |= pr->ivid_sel ? BIT(7) : 0; + r[13] |= pr->meter_sel ? BIT(6) : 0; + r[13] |= pr->mir_sel ? BIT(5) : 0; + r[13] |= pr->log_sel ? BIT(4) : 0; + + r[14] |= ((u32)(pr->fwd_data & 0x3fff)) << 18; + r[14] |= pr->log_octets ? BIT(17) : 0; + r[14] |= ((u32)(pr->log_data & 0x7ff)) << 4; + r[14] |= (pr->mir_data & 0x3) << 3; + r[14] |= ((u32)(pr->meter_data >> 7)) & 0x7; + r[15] |= (u32)(pr->meter_data) << 26; + r[15] |= ((u32)(pr->ivid_act) << 23) & 0x3; + r[15] |= ((u32)(pr->ivid_data) << 9) & 0xfff; + r[15] |= ((u32)(pr->ovid_act) << 6) & 0x3; + r[15] |= ((u32)(pr->ovid_data) >> 4) & 0xff; + r[16] |= ((u32)(pr->ovid_data) & 0xf) << 28; + r[16] |= ((u32)(pr->nopri_data) & 0x7) << 20; + r[16] |= ((u32)(pr->mpls_act) & 0x7) << 20; + r[16] |= ((u32)(pr->mpls_lib_idx) & 0x7) << 20; + r[16] |= pr->bypass_all ? BIT(9) : 0; + r[16] |= pr->bypass_igr_stp ? BIT(8) : 0; + r[16] |= pr->bypass_ibc_sc ? BIT(7) : 0; +} + +static void rtl839x_read_pie_action(u32 r[], struct pie_rule *pr) +{ + if (r[13] & BIT(3)) { // ACT_MASK_FWD set, is it a drop? + if ((r[14] & 0x7) == 1) { + pr->drop = true; + } else { + pr->fwd_sel = true; + pr->fwd_act = r[14] & 0x7; + } + } + + pr->bypass_sel = r[13] & BIT(11); + pr->mpls_sel = r[13] & BIT(10); + pr->nopri_sel = r[13] & BIT(9); + pr->ovid_sel = r[13] & BIT(8); + pr->ivid_sel = r[13] & BIT(7); + pr->meter_sel = r[13] & BIT(6); + pr->mir_sel = r[13] & BIT(5); + pr->log_sel = r[13] & BIT(4); + + // TODO: Read in data fields + + pr->bypass_all = r[16] & BIT(9); + pr->bypass_igr_stp = r[16] & BIT(8); + pr->bypass_ibc_sc = r[16] & BIT(7); +} + +void rtl839x_pie_rule_dump_raw(u32 r[]) +{ + pr_info("Raw IACL table entry:\n"); + pr_info("Match : %08x %08x %08x %08x %08x %08x\n", r[0], r[1], r[2], r[3], r[4], r[5]); + pr_info("Fixed : %06x\n", r[6] >> 8); + pr_info("Match M: %08x %08x %08x %08x %08x %08x\n", + (r[6] << 24) | (r[7] >> 8), (r[7] << 24) | (r[8] >> 8), (r[8] << 24) | (r[9] >> 8), + (r[9] << 24) | (r[10] >> 8), (r[10] << 24) | (r[11] >> 8), + (r[11] << 24) | (r[12] >> 8)); + pr_info("R[13]: %08x\n", r[13]); + pr_info("Fixed M: %06x\n", ((r[12] << 16) | (r[13] >> 16)) & 0xffffff); + pr_info("Valid / not / and1 / and2 : %1x\n", (r[13] >> 12) & 0xf); + pr_info("r 13-16: %08x %08x %08x %08x\n", r[13], r[14], r[15], r[16]); +} + +void rtl839x_pie_rule_dump(struct pie_rule *pr) +{ + pr_info("Drop: %d, fwd: %d, ovid: %d, ivid: %d, flt: %d, log: %d, rmk: %d, meter: %d tagst: %d, mir: %d, nopri: %d, cpupri: %d, otpid: %d, itpid: %d, shape: %d\n", + pr->drop, pr->fwd_sel, pr->ovid_sel, pr->ivid_sel, pr->flt_sel, pr->log_sel, pr->rmk_sel, pr->log_sel, pr->tagst_sel, pr->mir_sel, pr->nopri_sel, + pr->cpupri_sel, pr->otpid_sel, pr->itpid_sel, pr->shaper_sel); + if (pr->fwd_sel) + pr_info("FWD: %08x\n", pr->fwd_data); + pr_info("TID: %x, %x\n", pr->tid, pr->tid_m); +} + +static int rtl839x_pie_rule_read(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr) +{ + // Read IACL table (2) via register 0 + struct table_reg *q = rtl_table_get(RTL8380_TBL_0, 2); + u32 r[17]; + int i; + int block = idx / PIE_BLOCK_SIZE; + u32 t_select = sw_r32(RTL839X_ACL_BLK_TMPLTE_CTRL(block)); + + memset(pr, 0, sizeof(*pr)); + rtl_table_read(q, idx); + for (i = 0; i < 17; i++) + r[i] = sw_r32(rtl_table_data(q, i)); + + rtl_table_release(q); + + rtl839x_read_pie_fixed_fields(r, pr); + if (!pr->valid) + return 0; + + pr_debug("%s: template_selectors %08x, tid: %d\n", __func__, t_select, pr->tid); + rtl839x_pie_rule_dump_raw(r); + + rtl839x_read_pie_templated(r, pr, fixed_templates[(t_select >> (pr->tid * 3)) & 0x7]); + + rtl839x_read_pie_action(r, pr); + + return 0; +} + +static int rtl839x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr) +{ + // Access IACL table (2) via register 0 + struct table_reg *q = rtl_table_get(RTL8390_TBL_0, 2); + u32 r[17]; + int i; + int block = idx / PIE_BLOCK_SIZE; + u32 t_select = sw_r32(RTL839X_ACL_BLK_TMPLTE_CTRL(block)); + + pr_debug("%s: %d, t_select: %08x\n", __func__, idx, t_select); + + for (i = 0; i < 17; i++) + r[i] = 0; + + if (!pr->valid) { + rtl_table_write(q, idx); + rtl_table_release(q); + return 0; + } + rtl839x_write_pie_fixed_fields(r, pr); + + pr_debug("%s: template %d\n", __func__, (t_select >> (pr->tid * 3)) & 0x7); + rtl839x_write_pie_templated(r, pr, fixed_templates[(t_select >> (pr->tid * 3)) & 0x7]); + + rtl839x_write_pie_action(r, pr); + +// rtl839x_pie_rule_dump_raw(r); + + for (i = 0; i < 17; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); + + return 0; +} + +static bool rtl839x_pie_templ_has(int t, enum template_field_id field_type) +{ + int i; + enum template_field_id ft; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + ft = fixed_templates[t][i]; + if (field_type == ft) + return true; + } + + return false; +} + +static int rtl839x_pie_verify_template(struct rtl838x_switch_priv *priv, + struct pie_rule *pr, int t, int block) +{ + int i; + + if (!pr->is_ipv6 && pr->sip_m && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_SIP0)) + return -1; + + if (!pr->is_ipv6 && pr->dip_m && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_DIP0)) + return -1; + + if (pr->is_ipv6) { + if ((pr->sip6_m.s6_addr32[0] || pr->sip6_m.s6_addr32[1] + || pr->sip6_m.s6_addr32[2] || pr->sip6_m.s6_addr32[3]) + && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_SIP2)) + return -1; + if ((pr->dip6_m.s6_addr32[0] || pr->dip6_m.s6_addr32[1] + || pr->dip6_m.s6_addr32[2] || pr->dip6_m.s6_addr32[3]) + && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_DIP2)) + return -1; + } + + if (ether_addr_to_u64(pr->smac) && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_SMAC0)) + return -1; + + if (ether_addr_to_u64(pr->dmac) && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0)) + return -1; + + // TODO: Check more + + i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE); + + if (i >= PIE_BLOCK_SIZE) + return -1; + + return i + PIE_BLOCK_SIZE * block; +} + +static int rtl839x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rule *pr) +{ + int idx, block, j, t; + int min_block = 0; + int max_block = priv->n_pie_blocks / 2; + + if (pr->is_egress) { + min_block = max_block; + max_block = priv->n_pie_blocks; + } + + mutex_lock(&priv->pie_mutex); + + for (block = min_block; block < max_block; block++) { + for (j = 0; j < 2; j++) { + t = (sw_r32(RTL839X_ACL_BLK_TMPLTE_CTRL(block)) >> (j * 3)) & 0x7; + idx = rtl839x_pie_verify_template(priv, pr, t, block); + if (idx >= 0) + break; + } + if (j < 2) + break; + } + + if (block >= priv->n_pie_blocks) { + mutex_unlock(&priv->pie_mutex); + return -EOPNOTSUPP; + } + + set_bit(idx, priv->pie_use_bm); + + pr->valid = true; + pr->tid = j; // Mapped to template number + pr->tid_m = 0x3; + pr->id = idx; + + rtl839x_pie_lookup_enable(priv, idx); + rtl839x_pie_rule_write(priv, idx, pr); + + mutex_unlock(&priv->pie_mutex); + return 0; +} + +static void rtl839x_pie_rule_rm(struct rtl838x_switch_priv *priv, struct pie_rule *pr) +{ + int idx = pr->id; + + rtl839x_pie_rule_del(priv, idx, idx); + clear_bit(idx, priv->pie_use_bm); +} + +static void rtl839x_pie_init(struct rtl838x_switch_priv *priv) +{ + int i; + u32 template_selectors; + + mutex_init(&priv->pie_mutex); + + // Power on all PIE blocks + for (i = 0; i < priv->n_pie_blocks; i++) + sw_w32_mask(0, BIT(i), RTL839X_PS_ACL_PWR_CTRL); + + // Set ingress and egress ACL blocks to 50/50: first Egress block is 9 + sw_w32_mask(0x1f, 9, RTL839X_ACL_CTRL); // Writes 9 to cutline field + + // Include IPG in metering + sw_w32(1, RTL839X_METER_GLB_CTRL); + + // Delete all present rules + rtl839x_pie_rule_del(priv, 0, priv->n_pie_blocks * PIE_BLOCK_SIZE - 1); + + // Enable predefined templates 0, 1 for blocks 0-2 + template_selectors = 0 | (1 << 3); + for (i = 0; i < 3; i++) + sw_w32(template_selectors, RTL839X_ACL_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 2, 3 for blocks 3-5 + template_selectors = 2 | (3 << 3); + for (i = 3; i < 6; i++) + sw_w32(template_selectors, RTL839X_ACL_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 1, 4 for blocks 6-8 + template_selectors = 2 | (3 << 3); + for (i = 6; i < 9; i++) + sw_w32(template_selectors, RTL839X_ACL_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 0, 1 for blocks 9-11 + template_selectors = 0 | (1 << 3); + for (i = 9; i < 12; i++) + sw_w32(template_selectors, RTL839X_ACL_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 2, 3 for blocks 12-14 + template_selectors = 2 | (3 << 3); + for (i = 12; i < 15; i++) + sw_w32(template_selectors, RTL839X_ACL_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 1, 4 for blocks 15-17 + template_selectors = 2 | (3 << 3); + for (i = 15; i < 18; i++) + sw_w32(template_selectors, RTL839X_ACL_BLK_TMPLTE_CTRL(i)); +} + +static u32 rtl839x_packet_cntr_read(int counter) +{ + u32 v; + + // Read LOG table (4) via register RTL8390_TBL_0 + struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 4); + + pr_debug("In %s, id %d\n", __func__, counter); + rtl_table_read(r, counter / 2); + + // The table has a size of 2 registers + if (counter % 2) + v = sw_r32(rtl_table_data(r, 0)); + else + v = sw_r32(rtl_table_data(r, 1)); + + rtl_table_release(r); + + return v; +} + +static void rtl839x_packet_cntr_clear(int counter) +{ + // Access LOG table (4) via register RTL8390_TBL_0 + struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 4); + + pr_debug("In %s, id %d\n", __func__, counter); + // The table has a size of 2 registers + if (counter % 2) + sw_w32(0, rtl_table_data(r, 0)); + else + sw_w32(0, rtl_table_data(r, 1)); + + rtl_table_write(r, counter / 2); + + rtl_table_release(r); +} + const struct rtl838x_reg rtl839x_reg = { .mask_port_reg_be = rtl839x_mask_port_reg_be, .set_port_reg_be = rtl839x_set_port_reg_be, @@ -804,4 +1672,11 @@ const struct rtl838x_reg rtl839x_reg = { .l2_hash_key = rtl839x_l2_hash_key, .read_mcast_pmask = rtl839x_read_mcast_pmask, .write_mcast_pmask = rtl839x_write_mcast_pmask, + .pie_init = rtl839x_pie_init, + .pie_rule_read = rtl839x_pie_rule_read, + .pie_rule_write = rtl839x_pie_rule_write, + .pie_rule_add = rtl839x_pie_rule_add, + .pie_rule_rm = rtl839x_pie_rule_rm, + .packet_cntr_read = rtl839x_packet_cntr_read, + .packet_cntr_clear = rtl839x_packet_cntr_clear, }; From a96b73a8902854b4e810c4c24e1f0c35326722a4 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Wed, 8 Sep 2021 07:56:11 +0200 Subject: [PATCH 18/59] realtek: Packet Inspection Engine support for RTL930x SoCs Adds the RTL930x-specific PIE support routines. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/rtl930x.c | 678 ++++++++++++++++++ 1 file changed, 678 insertions(+) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c index f1de39f0bc..4291954234 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c @@ -6,6 +6,98 @@ extern struct mutex smi_lock; extern struct rtl83xx_soc_info soc_info; +/* Definition of the RTL930X-specific template field IDs as used in the PIE */ +enum template_field_id { + TEMPLATE_FIELD_SPM0 = 0, // Source portmask ports 0-15 + TEMPLATE_FIELD_SPM1 = 1, // Source portmask ports 16-31 + TEMPLATE_FIELD_DMAC0 = 2, // Destination MAC [15:0] + TEMPLATE_FIELD_DMAC1 = 3, // Destination MAC [31:16] + TEMPLATE_FIELD_DMAC2 = 4, // Destination MAC [47:32] + TEMPLATE_FIELD_SMAC0 = 5, // Source MAC [15:0] + TEMPLATE_FIELD_SMAC1 = 6, // Source MAC [31:16] + TEMPLATE_FIELD_SMAC2 = 7, // Source MAC [47:32] + TEMPLATE_FIELD_ETHERTYPE = 8, // Ethernet frame type field + TEMPLATE_FIELD_OTAG = 9, + TEMPLATE_FIELD_ITAG = 10, + TEMPLATE_FIELD_SIP0 = 11, + TEMPLATE_FIELD_SIP1 = 12, + TEMPLATE_FIELD_DIP0 = 13, + TEMPLATE_FIELD_DIP1 = 14, + TEMPLATE_FIELD_IP_TOS_PROTO = 15, + TEMPLATE_FIELD_L4_SPORT = 16, + TEMPLATE_FIELD_L4_DPORT = 17, + TEMPLATE_FIELD_L34_HEADER = 18, + TEMPLATE_FIELD_TCP_INFO = 19, + TEMPLATE_FIELD_FIELD_SELECTOR_VALID = 20, + TEMPLATE_FIELD_FIELD_SELECTOR_0 = 21, + TEMPLATE_FIELD_FIELD_SELECTOR_1 = 22, + TEMPLATE_FIELD_FIELD_SELECTOR_2 = 23, + TEMPLATE_FIELD_FIELD_SELECTOR_3 = 24, + TEMPLATE_FIELD_FIELD_SELECTOR_4 = 25, + TEMPLATE_FIELD_FIELD_SELECTOR_5 = 26, + TEMPLATE_FIELD_SIP2 = 27, + TEMPLATE_FIELD_SIP3 = 28, + TEMPLATE_FIELD_SIP4 = 29, + TEMPLATE_FIELD_SIP5 = 30, + TEMPLATE_FIELD_SIP6 = 31, + TEMPLATE_FIELD_SIP7 = 32, + TEMPLATE_FIELD_DIP2 = 33, + TEMPLATE_FIELD_DIP3 = 34, + TEMPLATE_FIELD_DIP4 = 35, + TEMPLATE_FIELD_DIP5 = 36, + TEMPLATE_FIELD_DIP6 = 37, + TEMPLATE_FIELD_DIP7 = 38, + TEMPLATE_FIELD_PKT_INFO = 39, + TEMPLATE_FIELD_FLOW_LABEL = 40, + TEMPLATE_FIELD_DSAP_SSAP = 41, + TEMPLATE_FIELD_SNAP_OUI = 42, + TEMPLATE_FIELD_FWD_VID = 43, + TEMPLATE_FIELD_RANGE_CHK = 44, + TEMPLATE_FIELD_VLAN_GMSK = 45, // VLAN Group Mask/IP range check + TEMPLATE_FIELD_DLP = 46, + TEMPLATE_FIELD_META_DATA = 47, + TEMPLATE_FIELD_SRC_FWD_VID = 48, + TEMPLATE_FIELD_SLP = 49, +}; + +/* The meaning of TEMPLATE_FIELD_VLAN depends on phase and the configuration in + * RTL930X_PIE_CTRL. We use always the same definition and map to the inner VLAN tag: + */ +#define TEMPLATE_FIELD_VLAN TEMPLATE_FIELD_ITAG + +// Number of fixed templates predefined in the RTL9300 SoC +#define N_FIXED_TEMPLATES 5 +// RTL9300 specific predefined templates +static enum template_field_id fixed_templates[N_FIXED_TEMPLATES][N_FIXED_FIELDS] = +{ + { + TEMPLATE_FIELD_DMAC0, TEMPLATE_FIELD_DMAC1, TEMPLATE_FIELD_DMAC2, + TEMPLATE_FIELD_SMAC0, TEMPLATE_FIELD_SMAC1, TEMPLATE_FIELD_SMAC2, + TEMPLATE_FIELD_VLAN, TEMPLATE_FIELD_IP_TOS_PROTO, TEMPLATE_FIELD_DSAP_SSAP, + TEMPLATE_FIELD_ETHERTYPE, TEMPLATE_FIELD_SPM0, TEMPLATE_FIELD_SPM1 + }, { + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_DIP0, + TEMPLATE_FIELD_DIP1, TEMPLATE_FIELD_IP_TOS_PROTO, TEMPLATE_FIELD_TCP_INFO, + TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_L4_DPORT, TEMPLATE_FIELD_VLAN, + TEMPLATE_FIELD_RANGE_CHK, TEMPLATE_FIELD_SPM0, TEMPLATE_FIELD_SPM1 + }, { + TEMPLATE_FIELD_DMAC0, TEMPLATE_FIELD_DMAC1, TEMPLATE_FIELD_DMAC2, + TEMPLATE_FIELD_VLAN, TEMPLATE_FIELD_ETHERTYPE, TEMPLATE_FIELD_IP_TOS_PROTO, + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_DIP0, + TEMPLATE_FIELD_DIP1, TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_L4_DPORT + }, { + TEMPLATE_FIELD_DIP0, TEMPLATE_FIELD_DIP1, TEMPLATE_FIELD_DIP2, + TEMPLATE_FIELD_DIP3, TEMPLATE_FIELD_DIP4, TEMPLATE_FIELD_DIP5, + TEMPLATE_FIELD_DIP6, TEMPLATE_FIELD_DIP7, TEMPLATE_FIELD_IP_TOS_PROTO, + TEMPLATE_FIELD_TCP_INFO, TEMPLATE_FIELD_L4_SPORT, TEMPLATE_FIELD_L4_DPORT + }, { + TEMPLATE_FIELD_SIP0, TEMPLATE_FIELD_SIP1, TEMPLATE_FIELD_SIP2, + TEMPLATE_FIELD_SIP3, TEMPLATE_FIELD_SIP4, TEMPLATE_FIELD_SIP5, + TEMPLATE_FIELD_SIP6, TEMPLATE_FIELD_SIP7, TEMPLATE_FIELD_VLAN, + TEMPLATE_FIELD_RANGE_CHK, TEMPLATE_FIELD_SPM1, TEMPLATE_FIELD_SPM1 + }, +}; + void rtl930x_print_matrix(void) { int i; @@ -975,6 +1067,586 @@ static void rtl930x_init_eee(struct rtl838x_switch_priv *priv, bool enable) priv->eee_enabled = enable; } +static void rtl930x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index) +{ + int block = index / PIE_BLOCK_SIZE; + + sw_w32_mask(0, BIT(block), RTL930X_PIE_BLK_LOOKUP_CTRL); +} + +/* + * Reads the intermediate representation of the templated match-fields of the + * PIE rule in the pie_rule structure and fills in the raw data fields in the + * raw register space r[]. + * The register space configuration size is identical for the RTL8380/90 and RTL9300, + * however the RTL9310 has 2 more registers / fields and the physical field-ids are different + * on all SoCs + * On the RTL9300 the mask fields are not word-aligend! + */ +static void rtl930x_write_pie_templated(u32 r[], struct pie_rule *pr, enum template_field_id t[]) +{ + int i; + enum template_field_id field_type; + u16 data, data_m; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + field_type = t[i]; + data = data_m = 0; + + switch (field_type) { + case TEMPLATE_FIELD_SPM0: + data = pr->spm; + data_m = pr->spm_m; + break; + case TEMPLATE_FIELD_SPM1: + data = pr->spm >> 16; + data_m = pr->spm_m >> 16; + break; + case TEMPLATE_FIELD_OTAG: + data = pr->otag; + data_m = pr->otag_m; + break; + case TEMPLATE_FIELD_SMAC0: + data = pr->smac[4]; + data = (data << 8) | pr->smac[5]; + data_m = pr->smac_m[4]; + data_m = (data_m << 8) | pr->smac_m[5]; + break; + case TEMPLATE_FIELD_SMAC1: + data = pr->smac[2]; + data = (data << 8) | pr->smac[3]; + data_m = pr->smac_m[2]; + data_m = (data_m << 8) | pr->smac_m[3]; + break; + case TEMPLATE_FIELD_SMAC2: + data = pr->smac[0]; + data = (data << 8) | pr->smac[1]; + data_m = pr->smac_m[0]; + data_m = (data_m << 8) | pr->smac_m[1]; + break; + case TEMPLATE_FIELD_DMAC0: + data = pr->dmac[4]; + data = (data << 8) | pr->dmac[5]; + data_m = pr->dmac_m[4]; + data_m = (data_m << 8) | pr->dmac_m[5]; + break; + case TEMPLATE_FIELD_DMAC1: + data = pr->dmac[2]; + data = (data << 8) | pr->dmac[3]; + data_m = pr->dmac_m[2]; + data_m = (data_m << 8) | pr->dmac_m[3]; + break; + case TEMPLATE_FIELD_DMAC2: + data = pr->dmac[0]; + data = (data << 8) | pr->dmac[1]; + data_m = pr->dmac_m[0]; + data_m = (data_m << 8) | pr->dmac_m[1]; + break; + case TEMPLATE_FIELD_ETHERTYPE: + data = pr->ethertype; + data_m = pr->ethertype_m; + break; + case TEMPLATE_FIELD_ITAG: + data = pr->itag; + data_m = pr->itag_m; + break; + case TEMPLATE_FIELD_SIP0: + if (pr->is_ipv6) { + data = pr->sip6.s6_addr16[7]; + data_m = pr->sip6_m.s6_addr16[7]; + } else { + data = pr->sip; + data_m = pr->sip_m; + } + break; + case TEMPLATE_FIELD_SIP1: + if (pr->is_ipv6) { + data = pr->sip6.s6_addr16[6]; + data_m = pr->sip6_m.s6_addr16[6]; + } else { + data = pr->sip >> 16; + data_m = pr->sip_m >> 16; + } + break; + + case TEMPLATE_FIELD_SIP2: + case TEMPLATE_FIELD_SIP3: + case TEMPLATE_FIELD_SIP4: + case TEMPLATE_FIELD_SIP5: + case TEMPLATE_FIELD_SIP6: + case TEMPLATE_FIELD_SIP7: + data = pr->sip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)]; + data_m = pr->sip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_SIP2)]; + break; + + case TEMPLATE_FIELD_DIP0: + if (pr->is_ipv6) { + data = pr->dip6.s6_addr16[7]; + data_m = pr->dip6_m.s6_addr16[7]; + } else { + data = pr->dip; + data_m = pr->dip_m; + } + break; + + case TEMPLATE_FIELD_DIP1: + if (pr->is_ipv6) { + data = pr->dip6.s6_addr16[6]; + data_m = pr->dip6_m.s6_addr16[6]; + } else { + data = pr->dip >> 16; + data_m = pr->dip_m >> 16; + } + break; + + case TEMPLATE_FIELD_DIP2: + case TEMPLATE_FIELD_DIP3: + case TEMPLATE_FIELD_DIP4: + case TEMPLATE_FIELD_DIP5: + case TEMPLATE_FIELD_DIP6: + case TEMPLATE_FIELD_DIP7: + data = pr->dip6.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)]; + data_m = pr->dip6_m.s6_addr16[5 - (field_type - TEMPLATE_FIELD_DIP2)]; + break; + + case TEMPLATE_FIELD_IP_TOS_PROTO: + data = pr->tos_proto; + data_m = pr->tos_proto_m; + break; + case TEMPLATE_FIELD_L4_SPORT: + data = pr->sport; + data_m = pr->sport_m; + break; + case TEMPLATE_FIELD_L4_DPORT: + data = pr->dport; + data_m = pr->dport_m; + break; + case TEMPLATE_FIELD_DSAP_SSAP: + data = pr->dsap_ssap; + data_m = pr->dsap_ssap_m; + break; + case TEMPLATE_FIELD_TCP_INFO: + data = pr->tcp_info; + data_m = pr->tcp_info_m; + break; + case TEMPLATE_FIELD_RANGE_CHK: + pr_warn("Warning: TEMPLATE_FIELD_RANGE_CHK: not configured\n"); + break; + default: + pr_info("%s: unknown field %d\n", __func__, field_type); + } + + // On the RTL9300, the mask fields are not word aligned! + if (!(i % 2)) { + r[5 - i / 2] = data; + r[12 - i / 2] |= ((u32)data_m << 8); + } else { + r[5 - i / 2] |= ((u32)data) << 16; + r[12 - i / 2] |= ((u32)data_m) << 24; + r[11 - i / 2] |= ((u32)data_m) >> 8; + } + } +} + +static void rtl930x_read_pie_fixed_fields(u32 r[], struct pie_rule *pr) +{ + pr->stacking_port = r[6] & BIT(31); + pr->spn = (r[6] >> 24) & 0x7f; + pr->mgnt_vlan = r[6] & BIT(23); + if (pr->phase == PHASE_IACL) + pr->dmac_hit_sw = r[6] & BIT(22); + else + pr->content_too_deep = r[6] & BIT(22); + pr->not_first_frag = r[6] & BIT(21); + pr->frame_type_l4 = (r[6] >> 18) & 7; + pr->frame_type = (r[6] >> 16) & 3; + pr->otag_fmt = (r[6] >> 15) & 1; + pr->itag_fmt = (r[6] >> 14) & 1; + pr->otag_exist = (r[6] >> 13) & 1; + pr->itag_exist = (r[6] >> 12) & 1; + pr->frame_type_l2 = (r[6] >> 10) & 3; + pr->igr_normal_port = (r[6] >> 9) & 1; + pr->tid = (r[6] >> 8) & 1; + + pr->stacking_port_m = r[12] & BIT(7); + pr->spn_m = r[12] & 0x7f; + pr->mgnt_vlan_m = r[13] & BIT(31); + if (pr->phase == PHASE_IACL) + pr->dmac_hit_sw_m = r[13] & BIT(30); + else + pr->content_too_deep_m = r[13] & BIT(30); + pr->not_first_frag_m = r[13] & BIT(29); + pr->frame_type_l4_m = (r[13] >> 26) & 7; + pr->frame_type_m = (r[13] >> 24) & 3; + pr->otag_fmt_m = r[13] & BIT(23); + pr->itag_fmt_m = r[13] & BIT(22); + pr->otag_exist_m = r[13] & BIT(21); + pr->itag_exist_m = r[13] & BIT (20); + pr->frame_type_l2_m = (r[13] >> 18) & 3; + pr->igr_normal_port_m = r[13] & BIT(17); + pr->tid_m = (r[13] >> 16) & 1; + + pr->valid = r[13] & BIT(15); + pr->cond_not = r[13] & BIT(14); + pr->cond_and1 = r[13] & BIT(13); + pr->cond_and2 = r[13] & BIT(12); +} + +static void rtl930x_write_pie_fixed_fields(u32 r[], struct pie_rule *pr) +{ + r[6] = pr->stacking_port ? BIT(31) : 0; + r[6] |= ((u32) (pr->spn & 0x7f)) << 24; + r[6] |= pr->mgnt_vlan ? BIT(23) : 0; + if (pr->phase == PHASE_IACL) + r[6] |= pr->dmac_hit_sw ? BIT(22) : 0; + else + r[6] |= pr->content_too_deep ? BIT(22) : 0; + r[6] |= pr->not_first_frag ? BIT(21) : 0; + r[6] |= ((u32) (pr->frame_type_l4 & 0x7)) << 18; + r[6] |= ((u32) (pr->frame_type & 0x3)) << 16; + r[6] |= pr->otag_fmt ? BIT(15) : 0; + r[6] |= pr->itag_fmt ? BIT(14) : 0; + r[6] |= pr->otag_exist ? BIT(13) : 0; + r[6] |= pr->itag_exist ? BIT(12) : 0; + r[6] |= ((u32) (pr->frame_type_l2 & 0x3)) << 10; + r[6] |= pr->igr_normal_port ? BIT(9) : 0; + r[6] |= ((u32) (pr->tid & 0x1)) << 8; + + r[12] |= pr->stacking_port_m ? BIT(7) : 0; + r[12] |= (u32) (pr->spn_m & 0x7f); + r[13] |= pr->mgnt_vlan_m ? BIT(31) : 0; + if (pr->phase == PHASE_IACL) + r[13] |= pr->dmac_hit_sw_m ? BIT(30) : 0; + else + r[13] |= pr->content_too_deep_m ? BIT(30) : 0; + r[13] |= pr->not_first_frag_m ? BIT(29) : 0; + r[13] |= ((u32) (pr->frame_type_l4_m & 0x7)) << 26; + r[13] |= ((u32) (pr->frame_type_m & 0x3)) << 24; + r[13] |= pr->otag_fmt_m ? BIT(23) : 0; + r[13] |= pr->itag_fmt_m ? BIT(22) : 0; + r[13] |= pr->otag_exist_m ? BIT(21) : 0; + r[13] |= pr->itag_exist_m ? BIT(20) : 0; + r[13] |= ((u32) (pr->frame_type_l2_m & 0x3)) << 18; + r[13] |= pr->igr_normal_port_m ? BIT(17) : 0; + r[13] |= ((u32) (pr->tid_m & 0x1)) << 16; + + r[13] |= pr->valid ? BIT(15) : 0; + r[13] |= pr->cond_not ? BIT(14) : 0; + r[13] |= pr->cond_and1 ? BIT(13) : 0; + r[13] |= pr->cond_and2 ? BIT(12) : 0; +} + +static void rtl930x_write_pie_action(u32 r[], struct pie_rule *pr) +{ + // Either drop or forward + if (pr->drop) { + r[14] |= BIT(24) | BIT(25) | BIT(26); // Do Green, Yellow and Red drops + // Actually DROP, not PERMIT in Green / Yellow / Red + r[14] |= BIT(23) | BIT(22) | BIT(20); + } else { + r[14] |= pr->fwd_sel ? BIT(27) : 0; + r[14] |= pr->fwd_act << 18; + r[14] |= BIT(14); // We overwrite any drop + } + if (pr->phase == PHASE_VACL) + r[14] |= pr->fwd_sa_lrn ? BIT(15) : 0; + r[13] |= pr->bypass_sel ? BIT(5) : 0; + r[13] |= pr->nopri_sel ? BIT(4) : 0; + r[13] |= pr->tagst_sel ? BIT(3) : 0; + r[13] |= pr->ovid_sel ? BIT(1) : 0; + r[14] |= pr->ivid_sel ? BIT(31) : 0; + r[14] |= pr->meter_sel ? BIT(30) : 0; + r[14] |= pr->mir_sel ? BIT(29) : 0; + r[14] |= pr->log_sel ? BIT(28) : 0; + + r[14] |= ((u32)(pr->fwd_data & 0x3fff)) << 3; + r[15] |= pr->log_octets ? BIT(31) : 0; + r[15] |= (u32)(pr->meter_data) << 23; + + r[15] |= ((u32)(pr->ivid_act) << 21) & 0x3; + r[15] |= ((u32)(pr->ivid_data) << 9) & 0xfff; + r[16] |= ((u32)(pr->ovid_act) << 30) & 0x3; + r[16] |= ((u32)(pr->ovid_data) & 0xfff) << 16; + r[16] |= (pr->mir_data & 0x3) << 6; + r[17] |= ((u32)(pr->tagst_data) & 0xf) << 28; + r[17] |= ((u32)(pr->nopri_data) & 0x7) << 25; + r[17] |= pr->bypass_ibc_sc ? BIT(16) : 0; +} + +void rtl930x_pie_rule_dump_raw(u32 r[]) +{ + pr_info("Raw IACL table entry:\n"); + pr_info("r 0 - 7: %08x %08x %08x %08x %08x %08x %08x %08x\n", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); + pr_info("r 8 - 15: %08x %08x %08x %08x %08x %08x %08x %08x\n", + r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); + pr_info("r 16 - 18: %08x %08x %08x\n", r[16], r[17], r[18]); + pr_info("Match : %08x %08x %08x %08x %08x %08x\n", r[0], r[1], r[2], r[3], r[4], r[5]); + pr_info("Fixed : %06x\n", r[6] >> 8); + pr_info("Match M: %08x %08x %08x %08x %08x %08x\n", + (r[6] << 24) | (r[7] >> 8), (r[7] << 24) | (r[8] >> 8), (r[8] << 24) | (r[9] >> 8), + (r[9] << 24) | (r[10] >> 8), (r[10] << 24) | (r[11] >> 8), + (r[11] << 24) | (r[12] >> 8)); + pr_info("R[13]: %08x\n", r[13]); + pr_info("Fixed M: %06x\n", ((r[12] << 16) | (r[13] >> 16)) & 0xffffff); + pr_info("Valid / not / and1 / and2 : %1x\n", (r[13] >> 12) & 0xf); + pr_info("r 13-16: %08x %08x %08x %08x\n", r[13], r[14], r[15], r[16]); +} + +static int rtl930x_pie_rule_write(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr) +{ + // Access IACL table (2) via register 0 + struct table_reg *q = rtl_table_get(RTL9300_TBL_0, 2); + u32 r[19]; + int i; + int block = idx / PIE_BLOCK_SIZE; + u32 t_select = sw_r32(RTL930X_PIE_BLK_TMPLTE_CTRL(block)); + + pr_debug("%s: %d, t_select: %08x\n", __func__, idx, t_select); + + for (i = 0; i < 19; i++) + r[i] = 0; + + if (!pr->valid) { + rtl_table_write(q, idx); + rtl_table_release(q); + return 0; + } + rtl930x_write_pie_fixed_fields(r, pr); + + pr_debug("%s: template %d\n", __func__, (t_select >> (pr->tid * 4)) & 0xf); + rtl930x_write_pie_templated(r, pr, fixed_templates[(t_select >> (pr->tid * 4)) & 0xf]); + + rtl930x_write_pie_action(r, pr); + +// rtl930x_pie_rule_dump_raw(r); + + for (i = 0; i < 19; i++) + sw_w32(r[i], rtl_table_data(q, i)); + + rtl_table_write(q, idx); + rtl_table_release(q); + + return 0; +} + +static bool rtl930x_pie_templ_has(int t, enum template_field_id field_type) +{ + int i; + enum template_field_id ft; + + for (i = 0; i < N_FIXED_FIELDS; i++) { + ft = fixed_templates[t][i]; + if (field_type == ft) + return true; + } + + return false; +} + +/* + * Verify that the rule pr is compatible with a given template t in block block + * Note that this function is SoC specific since the values of e.g. TEMPLATE_FIELD_SIP0 + * depend on the SoC + */ +static int rtl930x_pie_verify_template(struct rtl838x_switch_priv *priv, + struct pie_rule *pr, int t, int block) +{ + int i; + + if (!pr->is_ipv6 && pr->sip_m && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_SIP0)) + return -1; + + if (!pr->is_ipv6 && pr->dip_m && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_DIP0)) + return -1; + + if (pr->is_ipv6) { + if ((pr->sip6_m.s6_addr32[0] || pr->sip6_m.s6_addr32[1] + || pr->sip6_m.s6_addr32[2] || pr->sip6_m.s6_addr32[3]) + && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_SIP2)) + return -1; + if ((pr->dip6_m.s6_addr32[0] || pr->dip6_m.s6_addr32[1] + || pr->dip6_m.s6_addr32[2] || pr->dip6_m.s6_addr32[3]) + && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_DIP2)) + return -1; + } + + if (ether_addr_to_u64(pr->smac) && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_SMAC0)) + return -1; + + if (ether_addr_to_u64(pr->dmac) && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0)) + return -1; + + // TODO: Check more + + i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE); + + if (i >= PIE_BLOCK_SIZE) + return -1; + + return i + PIE_BLOCK_SIZE * block; +} + +static int rtl930x_pie_rule_add(struct rtl838x_switch_priv *priv, struct pie_rule *pr) +{ + int idx, block, j, t; + int min_block = 0; + int max_block = priv->n_pie_blocks / 2; + + if (pr->is_egress) { + min_block = max_block; + max_block = priv->n_pie_blocks; + } + pr_debug("In %s\n", __func__); + + mutex_lock(&priv->pie_mutex); + + for (block = min_block; block < max_block; block++) { + for (j = 0; j < 2; j++) { + t = (sw_r32(RTL930X_PIE_BLK_TMPLTE_CTRL(block)) >> (j * 4)) & 0xf; + pr_debug("Testing block %d, template %d, template id %d\n", block, j, t); + pr_debug("%s: %08x\n", + __func__, sw_r32(RTL930X_PIE_BLK_TMPLTE_CTRL(block))); + idx = rtl930x_pie_verify_template(priv, pr, t, block); + if (idx >= 0) + break; + } + if (j < 2) + break; + } + + if (block >= priv->n_pie_blocks) { + mutex_unlock(&priv->pie_mutex); + return -EOPNOTSUPP; + } + + pr_debug("Using block: %d, index %d, template-id %d\n", block, idx, j); + set_bit(idx, priv->pie_use_bm); + + pr->valid = true; + pr->tid = j; // Mapped to template number + pr->tid_m = 0x1; + pr->id = idx; + + rtl930x_pie_lookup_enable(priv, idx); + rtl930x_pie_rule_write(priv, idx, pr); + + mutex_unlock(&priv->pie_mutex); + return 0; +} + +/* + * Delete a range of Packet Inspection Engine rules + */ +static int rtl930x_pie_rule_del(struct rtl838x_switch_priv *priv, int index_from, int index_to) +{ + u32 v = (index_from << 1)| (index_to << 12 ) | BIT(0); + + pr_debug("%s: from %d to %d\n", __func__, index_from, index_to); + mutex_lock(&priv->reg_mutex); + + // Write from-to and execute bit into control register + sw_w32(v, RTL930X_PIE_CLR_CTRL); + + // Wait until command has completed + do { + } while (sw_r32(RTL930X_PIE_CLR_CTRL) & BIT(0)); + + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static void rtl930x_pie_rule_rm(struct rtl838x_switch_priv *priv, struct pie_rule *pr) +{ + int idx = pr->id; + + rtl930x_pie_rule_del(priv, idx, idx); + clear_bit(idx, priv->pie_use_bm); +} + +static void rtl930x_pie_init(struct rtl838x_switch_priv *priv) +{ + int i; + u32 template_selectors; + + mutex_init(&priv->pie_mutex); + + pr_info("%s\n", __func__); + // Enable ACL lookup on all ports, including CPU_PORT + for (i = 0; i <= priv->cpu_port; i++) + sw_w32(1, RTL930X_ACL_PORT_LOOKUP_CTRL(i)); + + // Include IPG in metering + sw_w32_mask(0, 1, RTL930X_METER_GLB_CTRL); + + // Delete all present rules, block size is 128 on all SoC families + rtl930x_pie_rule_del(priv, 0, priv->n_pie_blocks * 128 - 1); + + // Assign blocks 0-7 to VACL phase (bit = 0), blocks 8-15 to IACL (bit = 1) + sw_w32(0xff00, RTL930X_PIE_BLK_PHASE_CTRL); + + // Enable predefined templates 0, 1 for first quarter of all blocks + template_selectors = 0 | (1 << 4); + for (i = 0; i < priv->n_pie_blocks / 4; i++) + sw_w32(template_selectors, RTL930X_PIE_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 2, 3 for second quarter of all blocks + template_selectors = 2 | (3 << 4); + for (i = priv->n_pie_blocks / 4; i < priv->n_pie_blocks / 2; i++) + sw_w32(template_selectors, RTL930X_PIE_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 0, 1 for third half of all blocks + template_selectors = 0 | (1 << 4); + for (i = priv->n_pie_blocks / 2; i < priv->n_pie_blocks * 3 / 4; i++) + sw_w32(template_selectors, RTL930X_PIE_BLK_TMPLTE_CTRL(i)); + + // Enable predefined templates 2, 3 for fourth quater of all blocks + template_selectors = 2 | (3 << 4); + for (i = priv->n_pie_blocks * 3 / 4; i < priv->n_pie_blocks; i++) + sw_w32(template_selectors, RTL930X_PIE_BLK_TMPLTE_CTRL(i)); + +} + +static u32 rtl930x_packet_cntr_read(int counter) +{ + u32 v; + + // Read LOG table (3) via register RTL9300_TBL_0 + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 3); + + pr_debug("In %s, id %d\n", __func__, counter); + rtl_table_read(r, counter / 2); + + pr_debug("Registers: %08x %08x\n", + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1))); + // The table has a size of 2 registers + if (counter % 2) + v = sw_r32(rtl_table_data(r, 0)); + else + v = sw_r32(rtl_table_data(r, 1)); + + rtl_table_release(r); + + return v; +} + +static void rtl930x_packet_cntr_clear(int counter) +{ + // Access LOG table (3) via register RTL9300_TBL_0 + struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 3); + + pr_info("In %s, id %d\n", __func__, counter); + // The table has a size of 2 registers + if (counter % 2) + sw_w32(0, rtl_table_data(r, 0)); + else + sw_w32(0, rtl_table_data(r, 1)); + + rtl_table_write(r, counter / 2); + + rtl_table_release(r); +} + const struct rtl838x_reg rtl930x_reg = { .mask_port_reg_be = rtl838x_mask_port_reg, .set_port_reg_be = rtl838x_set_port_reg, @@ -1036,4 +1708,10 @@ const struct rtl838x_reg rtl930x_reg = { .eee_port_ability = rtl930x_eee_port_ability, .read_mcast_pmask = rtl930x_read_mcast_pmask, .write_mcast_pmask = rtl930x_write_mcast_pmask, + .pie_init = rtl930x_pie_init, + .pie_rule_write = rtl930x_pie_rule_write, + .pie_rule_add = rtl930x_pie_rule_add, + .pie_rule_rm = rtl930x_pie_rule_rm, + .packet_cntr_read = rtl930x_packet_cntr_read, + .packet_cntr_clear = rtl930x_packet_cntr_clear, }; From 9d9bf16aa8d966834ac1280f96c37d22552c33d1 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Wed, 8 Sep 2021 16:13:18 +0200 Subject: [PATCH 19/59] realtek: Add phylink configuration routines for RTL93xx This adds RTL93xx-specific MAC configuration routines that allow also configuration of 10GBit links for phylink. There is support for the Realtek-specific HISGMI protocol. Signed-off-by: Birger Koblitz --- .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 260 ++++++++++++++++-- .../drivers/net/dsa/rtl83xx/rtl838x.h | 1 + ...04-include-linux-add-phy-hsgmii-mode.patch | 19 ++ 3 files changed, 260 insertions(+), 20 deletions(-) create mode 100644 target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index c79b4b2c81..3a0806e70a 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -280,7 +280,7 @@ static void rtl83xx_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 1000baseX_Full); /* On the RTL839x family of SoCs, ports 48 to 51 are SFP ports */ - if (port >=48 && port <= 51 && priv->family_id == RTL8390_FAMILY_ID) + if (port >= 48 && port <= 51 && priv->family_id == RTL8390_FAMILY_ID) phylink_set(mask, 1000baseX_Full); phylink_set(mask, 10baseT_Half); @@ -294,6 +294,67 @@ static void rtl83xx_phylink_validate(struct dsa_switch *ds, int port, __ETHTOOL_LINK_MODE_MASK_NBITS); } +static void rtl93xx_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + pr_debug("In %s port %d, state is %d (%s)", __func__, port, state->interface, + phy_modes(state->interface)); + + if (!phy_interface_mode_is_rgmii(state->interface) && + state->interface != PHY_INTERFACE_MODE_NA && + state->interface != PHY_INTERFACE_MODE_1000BASEX && + state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII && + state->interface != PHY_INTERFACE_MODE_GMII && + state->interface != PHY_INTERFACE_MODE_QSGMII && + state->interface != PHY_INTERFACE_MODE_XGMII && + state->interface != PHY_INTERFACE_MODE_HSGMII && + state->interface != PHY_INTERFACE_MODE_10GKR && + state->interface != PHY_INTERFACE_MODE_USXGMII && + state->interface != PHY_INTERFACE_MODE_INTERNAL && + state->interface != PHY_INTERFACE_MODE_SGMII) { + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + dev_err(ds->dev, + "Unsupported interface: %d for port %d\n", + state->interface, port); + return; + } + + /* Allow all the expected bits */ + phylink_set(mask, Autoneg); + phylink_set_port_modes(mask); + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + + /* With the exclusion of MII and Reverse MII, we support Gigabit, + * including Half duplex + */ + if (state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_REVMII) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseT_Half); + } + + /* On the RTL9300 family of SoCs, ports 26 to 27 may be SFP ports TODO: take out of .dts */ + if (port >= 26 && port <= 27) + phylink_set(mask, 1000baseX_Full); + if (port >= 26 && port <= 27) + phylink_set(mask, 10000baseKR_Full); + + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + + bitmap_and(supported, supported, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + static int rtl83xx_phylink_mac_link_state(struct dsa_switch *ds, int port, struct phylink_link_state *state) { @@ -304,15 +365,8 @@ static int rtl83xx_phylink_mac_link_state(struct dsa_switch *ds, int port, if (port < 0 || port > priv->cpu_port) return -EINVAL; - /* - * On the RTL9300 for at least the RTL8226B PHY, the MAC-side link - * state needs to be read twice in order to read a correct result. - * This would not be necessary for ports connected e.g. to RTL8218D - * PHYs. - */ state->link = 0; link = priv->r->get_port_reg_le(priv->r->mac_link_sts); - link = priv->r->get_port_reg_le(priv->r->mac_link_sts); if (link & BIT_ULL(port)) state->link = 1; pr_debug("%s: link state port %d: %llx\n", __func__, port, link & BIT_ULL(port)); @@ -349,6 +403,70 @@ static int rtl83xx_phylink_mac_link_state(struct dsa_switch *ds, int port, return 1; } +static int rtl93xx_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct rtl838x_switch_priv *priv = ds->priv; + u64 speed; + u64 link; + + if (port < 0 || port > priv->cpu_port) + return -EINVAL; + + /* + * On the RTL9300 for at least the RTL8226B PHY, the MAC-side link + * state needs to be read twice in order to read a correct result. + * This would not be necessary for ports connected e.g. to RTL8218D + * PHYs. + */ + state->link = 0; + link = priv->r->get_port_reg_le(priv->r->mac_link_sts); + link = priv->r->get_port_reg_le(priv->r->mac_link_sts); + if (link & BIT_ULL(port)) + state->link = 1; + pr_debug("%s: link state port %d: %llx, media %08x\n", __func__, port, + link & BIT_ULL(port), sw_r32(RTL930X_MAC_LINK_MEDIA_STS)); + + state->duplex = 0; + if (priv->r->get_port_reg_le(priv->r->mac_link_dup_sts) & BIT_ULL(port)) + state->duplex = 1; + + speed = priv->r->get_port_reg_le(priv->r->mac_link_spd_sts(port)); + speed >>= (port % 8) << 2; + switch (speed & 0xf) { + case 0: + state->speed = SPEED_10; + break; + case 1: + state->speed = SPEED_100; + break; + case 2: + case 7: + state->speed = SPEED_1000; + break; + case 4: + state->speed = SPEED_10000; + break; + case 5: + case 8: + state->speed = SPEED_2500; + break; + case 6: + state->speed = SPEED_5000; + break; + default: + pr_err("%s: unknown speed: %d\n", __func__, (u32)speed & 0xf); + } + + pr_debug("%s: speed is: %d %d\n", __func__, (u32)speed & 0xf, state->speed); + state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); + if (priv->r->get_port_reg_le(priv->r->mac_rx_pause_sts) & BIT_ULL(port)) + state->pause |= MLO_PAUSE_RX; + if (priv->r->get_port_reg_le(priv->r->mac_tx_pause_sts) & BIT_ULL(port)) + state->pause |= MLO_PAUSE_TX; + return 1; +} + static void rtl83xx_config_interface(int port, phy_interface_t interface) { u32 old, int_shift, sds_shift; @@ -396,10 +514,6 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port, pr_debug("%s port %d, mode %x\n", __func__, port, mode); - // BUG: Make this work on RTL93XX - if (priv->family_id >= RTL9300_FAMILY_ID) - return; - if (port == priv->cpu_port) { /* Set Speed, duplex, flow control * FORCE_EN | LINK_EN | NWAY_EN | DUP_SEL @@ -468,6 +582,81 @@ static void rtl83xx_phylink_mac_config(struct dsa_switch *ds, int port, sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); } +static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct rtl838x_switch_priv *priv = ds->priv; + int sds_num, sds_mode; + u32 reg; + + pr_debug("%s port %d, mode %x, phy-mode: %s, speed %d, link %d\n", __func__, + port, mode, phy_modes(state->interface), state->speed, state->link); + + // Nothing to be done for the CPU-port + if (port == priv->cpu_port) + return; + + reg = sw_r32(priv->r->mac_force_mode_ctrl(port)); + reg &= ~(0xf << 3); + + // On the RTL930X, ports 24 to 27 are using an internal SerDes + if (port >=24 && port <= 27) { + sds_num = port - 18; // Port 24 mapped to SerDes 6, 25 to 7 ... + switch (state->interface) { + case PHY_INTERFACE_MODE_HSGMII: + sds_mode = 0x12; + break; + case PHY_INTERFACE_MODE_1000BASEX: + sds_mode = 0x1b; // 10G 1000X Auto + break; + case PHY_INTERFACE_MODE_XGMII: + sds_mode = 0x10; + break; + case PHY_INTERFACE_MODE_10GKR: + sds_mode = 0x1a; + // We need to use media sel for fibre media: + reg |= BIT(16); + break; + case PHY_INTERFACE_MODE_USXGMII: + sds_mode = 0x0d; + break; + default: + pr_err("%s: unknown serdes mode: %s\n", + __func__, phy_modes(state->interface)); + return; + } + rtl9300_sds_rst(sds_num, sds_mode); + } + + switch (state->speed) { + case SPEED_10000: + reg |= 4 << 3; + break; + case SPEED_5000: + reg |= 6 << 3; + break; + case SPEED_2500: + reg |= 5 << 3; + break; + case SPEED_1000: + reg |= 2 << 3; + break; + default: + reg |= 2 << 3; + break; + } + + if (state->link) + reg |= FORCE_LINK_EN; + + if (state->duplex == DUPLEX_FULL) + reg |= BIT(2); + + reg |= 1; // Force Link up + sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); +} + static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface) @@ -477,6 +666,18 @@ static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port, sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port)); } +static void rtl93xx_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +{ + struct rtl838x_switch_priv *priv = ds->priv; + /* Stop TX/RX to port */ + sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port)); + + // No longer force link + sw_w32_mask(3, 0, priv->r->mac_force_mode_ctrl(port)); +} + static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface, @@ -487,6 +688,21 @@ static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port, struct rtl838x_switch_priv *priv = ds->priv; /* Restart TX/RX to port */ sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port)); + // TODO: Set speed/duplex/pauses +} + +static void rtl93xx_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct rtl838x_switch_priv *priv = ds->priv; + + /* Restart TX/RX to port */ + sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port)); + // TODO: Set speed/duplex/pauses } static void rtl83xx_get_strings(struct dsa_switch *ds, @@ -1183,7 +1399,10 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port, if (!e.valid) continue; - if (e.port == port) { + if (e.port == port || e.port == RTL930X_PORT_IGNORE) { + u64 seed; + u32 key; + fid = ((i >> 2) & 0x3ff) | (e.rvid & ~0x3ff); mac = ether_addr_to_u64(&e.mac[0]); pkey = priv->r->l2_hash_key(priv, priv->r->l2_hash_seed(mac, fid)); @@ -1191,13 +1410,14 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port, pr_info("-> index %d, key %x, bucket %d, dmac %016llx, fid: %x rvid: %x\n", i, i >> 2, i & 0x3, mac, fid, e.rvid); dump_l2_entry(&e); - u64 seed = priv->r->l2_hash_seed(mac, e.rvid); - u32 key = priv->r->l2_hash_key(priv, seed); + seed = priv->r->l2_hash_seed(mac, e.rvid); + key = priv->r->l2_hash_key(priv, seed); pr_info("seed: %016llx, key based on rvid: %08x\n", seed, key); cb(e.mac, e.vid, e.is_static, data); } if (e.type == L2_MULTICAST) { u64 portmask = priv->r->read_mcast_pmask(e.mc_portmask_index); + if (portmask & BIT_ULL(port)) { dump_l2_entry(&e); pr_info(" PM: %016llx\n", portmask); @@ -1558,11 +1778,11 @@ const struct dsa_switch_ops rtl930x_switch_ops = { .phy_read = dsa_phy_read, .phy_write = dsa_phy_write, - .phylink_validate = rtl83xx_phylink_validate, - .phylink_mac_link_state = rtl83xx_phylink_mac_link_state, - .phylink_mac_config = rtl83xx_phylink_mac_config, - .phylink_mac_link_down = rtl83xx_phylink_mac_link_down, - .phylink_mac_link_up = rtl83xx_phylink_mac_link_up, + .phylink_validate = rtl93xx_phylink_validate, + .phylink_mac_link_state = rtl93xx_phylink_mac_link_state, + .phylink_mac_config = rtl93xx_phylink_mac_config, + .phylink_mac_link_down = rtl93xx_phylink_mac_link_down, + .phylink_mac_link_up = rtl93xx_phylink_mac_link_up, .get_strings = rtl83xx_get_strings, .get_ethtool_stats = rtl83xx_get_ethtool_stats, diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h index a3e169f288..e695879da1 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -145,6 +145,7 @@ #define RTL839X_MAC_RX_PAUSE_STS (0x03c0) #define RTL930X_MAC_RX_PAUSE_STS (0xCB30) #define RTL931X_MAC_RX_PAUSE_STS (0x0F00) +#define RTL930X_MAC_LINK_MEDIA_STS (0xCB14) /* MAC link state bits */ #define FORCE_EN (1 << 0) diff --git a/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch b/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch new file mode 100644 index 0000000000..9a61a70c44 --- /dev/null +++ b/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch @@ -0,0 +1,19 @@ +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -93,6 +93,7 @@ + PHY_INTERFACE_MODE_SMII, + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_MOCA, ++ PHY_INTERFACE_MODE_HSGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_1000BASEX, +@@ -163,6 +164,8 @@ + return "xgmii"; + case PHY_INTERFACE_MODE_MOCA: + return "moca"; ++ case PHY_INTERFACE_MODE_HSGMII: ++ return "hsgmii"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; + case PHY_INTERFACE_MODE_TRGMII: From 28e972b2ea2f55a593defcbd2dc21710cce648c7 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Wed, 8 Sep 2021 20:00:31 +0200 Subject: [PATCH 20/59] realtek: Configure initial L2 learning setup Configure a sane L2 learning configuration upon DSA driver load so that the switch can start learning L2 addresses. Also configure the correct flood masks for broadcast and unknown unicast traffice. Signed-off-by: Birger Koblitz --- .../files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 4 ++++ .../drivers/net/dsa/rtl83xx/rtl838x.c | 19 +++++++++++++++++++ .../drivers/net/dsa/rtl83xx/rtl838x.h | 12 ++++++++++++ .../drivers/net/dsa/rtl83xx/rtl839x.c | 15 +++++++++++++++ .../drivers/net/dsa/rtl83xx/rtl930x.c | 14 +++++++++++++- 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index 3a0806e70a..8ed0e45bb9 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -184,6 +184,8 @@ static int rtl83xx_setup(struct dsa_switch *ds) ds->configure_vlan_while_not_filtering = true; + priv->r->l2_learning_setup(); + /* Enable MAC Polling PHY again */ rtl83xx_enable_phy_polling(priv); pr_debug("Please wait until PHY is settled\n"); @@ -228,6 +230,8 @@ static int rtl930x_setup(struct dsa_switch *ds) ds->configure_vlan_while_not_filtering = true; + priv->r->l2_learning_setup(); + rtl83xx_enable_phy_polling(priv); priv->r->pie_init(priv); diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c index 2d24eaa337..15a486d724 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c @@ -491,6 +491,24 @@ static void rtl838x_vlan_profile_setup(int profile) rtl838x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0x1fffffff); } +static void rtl838x_l2_learning_setup(void) +{ + /* Set portmask for broadcast traffic and unknown unicast address flooding + * to the reserved entry in the portmask table used also for + * multicast flooding */ + sw_w32(UNKNOWN_MC_PMASK << 12 | UNKNOWN_MC_PMASK, RTL838X_L2_FLD_PMSK); + + /* Enable learning constraint system-wide (bit 0), per-port (bit 1) + * and per vlan (bit 2) */ + sw_w32(0x7, RTL838X_L2_LRN_CONSTRT_EN); + + // Limit learning to maximum: 16k entries, after that just flood (bits 0-1) + sw_w32((0x3fff << 2) | 0, RTL838X_L2_LRN_CONSTRT); + + // Do not trap ARP packets to CPU_PORT + sw_w32(0, RTL838X_SPCL_TRAP_ARP_CTRL); +} + static inline int rtl838x_vlan_port_egr_filter(int port) { return RTL838X_VLAN_PORT_EGR_FLTR; @@ -1605,6 +1623,7 @@ const struct rtl838x_reg rtl838x_reg = { .pie_rule_write = rtl838x_pie_rule_write, .pie_rule_add = rtl838x_pie_rule_add, .pie_rule_rm = rtl838x_pie_rule_rm, + .l2_learning_setup = rtl838x_l2_learning_setup, .packet_cntr_read = rtl838x_packet_cntr_read, .packet_cntr_clear = rtl838x_packet_cntr_clear, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h index e695879da1..6ff59c4348 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -198,6 +198,15 @@ #define RTL930X_L2_TBL_FLUSH_CTRL (0x9404) #define RTL931X_L2_TBL_FLUSH_CTRL (0xCD9C) +#define RTL838X_L2_LRN_CONSTRT (0x329C) +#define RTL839X_L2_LRN_CONSTRT (0x3910) +#define RTL930X_L2_LRN_CONSTRT_CTRL (0x909c) +#define RTL838X_L2_FLD_PMSK (0x3288) +#define RTL839X_L2_FLD_PMSK (0x38EC) +#define RTL930X_L2_BC_FLD_PMSK (0x9068) +#define RTL930X_L2_UNKN_UC_FLD_PMSK (0x9064) +#define RTL838X_L2_LRN_CONSTRT_EN (0x3368) + #define RTL838X_L2_PORT_NEW_SALRN(p) (0x328c + (((p >> 4) << 2))) #define RTL839X_L2_PORT_NEW_SALRN(p) (0x38F0 + (((p >> 4) << 2))) #define RTL930X_L2_PORT_SALRN(p) (0x8FEC + (((p >> 4) << 2))) @@ -303,6 +312,8 @@ /* 802.1X */ #define RTL838X_SPCL_TRAP_EAPOL_CTRL (0x6988) #define RTL839X_SPCL_TRAP_EAPOL_CTRL (0x105C) +#define RTL838X_SPCL_TRAP_ARP_CTRL (0x698C) +#define RTL839X_SPCL_TRAP_ARP_CTRL (0x1060) /* QoS */ #define RTL838X_QM_INTPRI2QID_CTRL (0x5F00) @@ -699,6 +710,7 @@ struct rtl838x_reg { int (*pie_rule_write)(struct rtl838x_switch_priv *priv, int idx, struct pie_rule *pr); int (*pie_rule_add)(struct rtl838x_switch_priv *priv, struct pie_rule *rule); void (*pie_rule_rm)(struct rtl838x_switch_priv *priv, struct pie_rule *rule); + void (*l2_learning_setup)(void); u32 (*packet_cntr_read)(int counter); void (*packet_cntr_clear)(int counter); }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c index 8faf6c07e9..4ed2184efa 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c @@ -542,6 +542,20 @@ void rtl839x_traffic_disable(int source, int dest) rtl839x_mask_port_reg_be(BIT_ULL(dest), 0, rtl839x_port_iso_ctrl(source)); } +static void rtl839x_l2_learning_setup(void) +{ + /* Set portmask for broadcast (offset bit 12) and unknown unicast (offset 0) + * address flooding to the reserved entry in the portmask table used + * also for multicast flooding */ + sw_w32(UNKNOWN_MC_PMASK << 12 | UNKNOWN_MC_PMASK, RTL839X_L2_FLD_PMSK); + + // Limit learning to maximum: 32k entries, after that just flood (bits 0-1) + sw_w32((0x7fff << 2) | 0, RTL839X_L2_LRN_CONSTRT); + + // Do not trap ARP packets to CPU_PORT + sw_w32(0, RTL839X_SPCL_TRAP_ARP_CTRL); +} + irqreturn_t rtl839x_switch_irq(int irq, void *dev_id) { struct dsa_switch *ds = dev_id; @@ -1677,6 +1691,7 @@ const struct rtl838x_reg rtl839x_reg = { .pie_rule_write = rtl839x_pie_rule_write, .pie_rule_add = rtl839x_pie_rule_add, .pie_rule_rm = rtl839x_pie_rule_rm, + .l2_learning_setup = rtl839x_l2_learning_setup, .packet_cntr_read = rtl839x_packet_cntr_read, .packet_cntr_clear = rtl839x_packet_cntr_clear, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c index 4291954234..aa6306c1c6 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c @@ -254,7 +254,18 @@ static void rtl930x_vlan_profile_setup(int profile) sw_w32(p[2], RTL930X_VLAN_PROFILE_SET(profile) + 8); sw_w32(p[3], RTL930X_VLAN_PROFILE_SET(profile) + 12); sw_w32(p[4], RTL930X_VLAN_PROFILE_SET(profile) + 16); - pr_info("Leaving %s\n", __func__); +} + +static void rtl930x_l2_learning_setup(void) +{ + // Portmask for flooding broadcast traffic + sw_w32(0x1fffffff, RTL930X_L2_BC_FLD_PMSK); + + // Portmask for flooding unicast traffic with unknown destination + sw_w32(0x1fffffff, RTL930X_L2_UNKN_UC_FLD_PMSK); + + // Limit learning to maximum: 32k entries, after that just flood (bits 0-1) + sw_w32((0x7fff << 2) | 0, RTL930X_L2_LRN_CONSTRT_CTRL); } static void rtl930x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) @@ -1712,6 +1723,7 @@ const struct rtl838x_reg rtl930x_reg = { .pie_rule_write = rtl930x_pie_rule_write, .pie_rule_add = rtl930x_pie_rule_add, .pie_rule_rm = rtl930x_pie_rule_rm, + .l2_learning_setup = rtl930x_l2_learning_setup, .packet_cntr_read = rtl930x_packet_cntr_read, .packet_cntr_clear = rtl930x_packet_cntr_clear, }; From 9ae927febd4b07e064bdb9eaeb43862ea6c7ac8f Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Wed, 8 Sep 2021 20:16:39 +0200 Subject: [PATCH 21/59] realtek: Fix bug in VLAN ingress and egress filtering The ingress filter registers use 2 bits for each port to define the filtering state, whereas the egress filter uses 1 bit. So for for the ingress filter the register offset for a given port is: (port >> 4) << 4: since there are 16 entries in a register of 32 bits and for the egress filter: (port >> 5) << 4: since there are 32 entries in a register of 32 bits Signed-off-by: Birger Koblitz --- .../realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c index 8ed0e45bb9..8ad713163e 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c @@ -1071,14 +1071,14 @@ static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port, */ if (port != priv->cpu_port) sw_w32_mask(0b10 << ((port % 16) << 1), 0b01 << ((port % 16) << 1), - priv->r->vlan_port_igr_filter + ((port >> 5) << 2)); - sw_w32_mask(0, BIT(port % 32), priv->r->vlan_port_egr_filter + ((port >> 4) << 2)); + priv->r->vlan_port_igr_filter + ((port >> 4) << 2)); + sw_w32_mask(0, BIT(port % 32), priv->r->vlan_port_egr_filter + ((port >> 5) << 2)); } else { /* Disable ingress and egress filtering */ if (port != priv->cpu_port) sw_w32_mask(0b11 << ((port % 16) << 1), 0, - priv->r->vlan_port_igr_filter + ((port >> 5) << 2)); - sw_w32_mask(BIT(port % 32), 0, priv->r->vlan_port_egr_filter + ((port >> 4) << 2)); + priv->r->vlan_port_igr_filter + ((port >> 4) << 2)); + sw_w32_mask(BIT(port % 32), 0, priv->r->vlan_port_egr_filter + ((port >> 5) << 2)); } /* Do we need to do something to the CPU-Port, too? */ From ee6f483a625d4e7c6198d422dab1cfddf1de040a Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Sun, 26 Sep 2021 17:37:25 +0200 Subject: [PATCH 22/59] realtek: Improve MDIO bus probing for RTL9300 Improve handling of multi-gig ports on the RTL9300 when probing the MDIO bus. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/common.c | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index dc783705f1..3049151c08 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -2,6 +2,11 @@ #include #include +#include +#include +#include +#include +#include #include #include "rtl83xx.h" @@ -303,38 +308,32 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) continue; // Check for the integrated SerDes of the RTL8380M first - if (of_property_read_bool(dn, "phy-is-integrated") - && priv->id == 0x8380 && pn >= 24) { + if (of_property_read_bool(dn, "phy-is-integrated") && priv->id == 0x8380 && pn >= 24) { pr_debug("----> FÓUND A SERDES\n"); priv->ports[pn].phy = PHY_RTL838X_SDS; continue; } - if (of_property_read_bool(dn, "phy-is-integrated") - && !of_property_read_bool(dn, "sfp")) { + if (of_property_read_bool(dn, "phy-is-integrated") && !of_property_read_bool(dn, "sfp")) { priv->ports[pn].phy = PHY_RTL8218B_INT; continue; } - if (!of_property_read_bool(dn, "phy-is-integrated") - && of_property_read_bool(dn, "sfp")) { + if (!of_property_read_bool(dn, "phy-is-integrated") && of_property_read_bool(dn, "sfp")) { priv->ports[pn].phy = PHY_RTL8214FC; continue; } - if (!of_property_read_bool(dn, "phy-is-integrated") - && !of_property_read_bool(dn, "sfp")) { + if (!of_property_read_bool(dn, "phy-is-integrated") && !of_property_read_bool(dn, "sfp")) { priv->ports[pn].phy = PHY_RTL8218B_EXT; continue; } } - // TODO: Do this needs to come from the .dts, at least the SerDes number + // TODO: Do this needs to come from the .dts if (priv->family_id == RTL9300_FAMILY_ID) { priv->ports[24].is2G5 = true; priv->ports[25].is2G5 = true; - priv->ports[24].sds_num = 1; - priv->ports[24].sds_num = 2; } /* Disable MAC polling the PHY so that we can start configuration */ @@ -344,7 +343,7 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) if (priv->family_id == RTL8380_FAMILY_ID) { /* Enable SerDes NWAY and PHY control via SoC */ sw_w32_mask(BIT(7), BIT(15), RTL838X_SMI_GLB_CTRL); - } else { + } else if (priv->family_id == RTL8390_FAMILY_ID) { /* Disable PHY polling via SoC */ sw_w32_mask(BIT(7), 0, RTL839X_SMI_GLB_CTRL); } @@ -356,15 +355,6 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) rtl8380_sds_power(26, 1); } - // TODO: Only power on SerDes with external PHYs connected - if (priv->family_id == RTL9300_FAMILY_ID) { - pr_info("RTL9300 Powering on SerDes ports\n"); - rtl9300_sds_power(24, 1); - rtl9300_sds_power(25, 1); - rtl9300_sds_power(26, 1); - rtl9300_sds_power(27, 1); - } - pr_debug("%s done\n", __func__); return 0; } From 35b3c4c212588deb49369635571ef63a7413b6f6 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Mon, 27 Sep 2021 10:41:25 +0200 Subject: [PATCH 23/59] 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 --- .../hack-5.10/720-net-phy-add-aqr-phys.patch | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 target/linux/generic/hack-5.10/720-net-phy-add-aqr-phys.patch diff --git a/target/linux/generic/hack-5.10/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.10/720-net-phy-add-aqr-phys.patch new file mode 100644 index 0000000000..73afb245b4 --- /dev/null +++ b/target/linux/generic/hack-5.10/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 @@ + 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 @@ + 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 @@ + .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 @@ + .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 @@ + { 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) }, + { } + }; + From 03e1d93e07791833e3167d8cfaef2e40a7113a23 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Fri, 10 Sep 2021 15:04:27 +0200 Subject: [PATCH 24/59] realtek: add driver support for routing offload Add generic support for listening to FIB and Event notifier updates and use this information to hook into the L3 hardware capabilities of the RTL SoCs. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/common.c | 815 +++++++++++++++++- .../drivers/net/dsa/rtl83xx/rtl838x.h | 151 +++- 2 files changed, 946 insertions(+), 20 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index 3049151c08..2745ead061 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "rtl83xx.h" @@ -495,6 +496,105 @@ int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv) return idx; } +/* + * Add an L2 nexthop entry for the L3 routing system / PIE forwarding in the SoC + * Use VID and MAC in rtl838x_l2_entry to identify either a free slot in the L2 hash table + * or mark an existing entry as a nexthop by setting it's nexthop bit + * Called from the L3 layer + * The index in the L2 hash table is filled into nh->l2_id; + */ +int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_nexthop *nh) +{ + struct rtl838x_l2_entry e; + u64 seed = priv->r->l2_hash_seed(nh->mac, nh->rvid); + u32 key = priv->r->l2_hash_key(priv, seed); + int i, idx = -1; + u64 entry; + + pr_debug("%s searching for %08llx vid %d with key %d, seed: %016llx\n", + __func__, nh->mac, nh->rvid, key, seed); + + e.type = L2_UNICAST; + u64_to_ether_addr(nh->mac, &e.mac[0]); + e.port = nh->port; + + // Loop over all entries in the hash-bucket and over the second block on 93xx SoCs + for (i = 0; i < priv->l2_bucket_size; i++) { + entry = priv->r->read_l2_entry_using_hash(key, i, &e); + + if (!e.valid || ((entry & 0x0fffffffffffffffULL) == seed)) { + idx = i > 3 ? ((key >> 14) & 0xffff) | i >> 1 + : ((key << 2) | i) & 0xffff; + break; + } + } + + if (idx < 0) { + pr_err("%s: No more L2 forwarding entries available\n", __func__); + return -1; + } + + // Found an existing (e->valid is true) or empty entry, make it a nexthop entry + nh->l2_id = idx; + if (e.valid) { + nh->port = e.port; + nh->vid = e.vid; // Save VID + nh->rvid = e.rvid; + nh->dev_id = e.stack_dev; + // If the entry is already a valid next hop entry, don't change it + if (e.next_hop) + return 0; + } else { + e.valid = true; + e.is_static = true; + e.rvid = nh->rvid; + e.is_ip_mc = false; + e.is_ipv6_mc = false; + e.block_da = false; + e.block_sa = false; + e.suspended = false; + e.age = 0; // With port-ignore + e.port = priv->port_ignore; + u64_to_ether_addr(nh->mac, &e.mac[0]); + } + e.next_hop = true; + e.nh_route_id = nh->id; // NH route ID takes place of VID + e.nh_vlan_target = false; + + priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); + + return 0; +} + +/* + * Removes a Layer 2 next hop entry in the forwarding database + * If it was static, the entire entry is removed, otherwise the nexthop bit is cleared + * and we wait until the entry ages out + */ +int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_nexthop *nh) +{ + struct rtl838x_l2_entry e; + u32 key = nh->l2_id >> 2; + int i = nh->l2_id & 0x3; + u64 entry = entry = priv->r->read_l2_entry_using_hash(key, i, &e); + + pr_debug("%s: id %d, key %d, index %d\n", __func__, nh->l2_id, key, i); + if (!e.valid) { + dev_err(priv->dev, "unknown nexthop, id %x\n", nh->l2_id); + return -1; + } + + if (e.is_static) + e.valid = false; + e.next_hop = false; + e.vid = nh->vid; // Restore VID + e.rvid = nh->rvid; + + priv->r->write_l2_entry_using_hash(key, i, &e); + + return 0; +} + static int rtl83xx_handle_changeupper(struct rtl838x_switch_priv *priv, struct net_device *ndev, struct netdev_notifier_changeupper_info *info) @@ -594,6 +694,671 @@ static int rtl83xx_netdevice_event(struct notifier_block *this, return NOTIFY_DONE; } +const static struct rhashtable_params route_ht_params = { + .key_len = sizeof(u32), + .key_offset = offsetof(struct rtl83xx_route, gw_ip), + .head_offset = offsetof(struct rtl83xx_route, linkage), +}; + +/* + * Updates an L3 next hop entry in the ROUTING table + */ +static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac) +{ + struct rtl83xx_route *r; + struct rhlist_head *tmp, *list; + + rcu_read_lock(); + list = rhltable_lookup(&priv->routes, &ip_addr, route_ht_params); + if (!list) { + rcu_read_unlock(); + return -ENOENT; + } + + rhl_for_each_entry_rcu(r, tmp, list, linkage) { + pr_info("%s: Setting up fwding: ip %pI4, GW mac %016llx\n", + __func__, &ip_addr, mac); + + // Reads the ROUTING table entry associated with the route + priv->r->route_read(r->id, r); + pr_info("Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len); + + r->nh.mac = r->nh.gw = mac; + r->nh.port = priv->port_ignore; + r->nh.id = r->id; + + // Do we need to explicitly add a DMAC entry with the route's nh index? + if (priv->r->set_l3_egress_mac) + priv->r->set_l3_egress_mac(r->id, mac); + + // Update ROUTING table: map gateway-mac and switch-mac id to route id + rtl83xx_l2_nexthop_add(priv, &r->nh); + + r->attr.valid = true; + r->attr.action = ROUTE_ACT_FORWARD; + r->attr.type = 0; + r->attr.hit = false; // Reset route-used indicator + + // Add PIE entry with dst_ip and prefix_len + r->pr.dip = r->dst_ip; + r->pr.dip_m = inet_make_mask(r->prefix_len); + + if (r->is_host_route) { + int slot = priv->r->find_l3_slot(r, false); + + pr_info("%s: Got slot for route: %d\n", __func__, slot); + priv->r->host_route_write(slot, r); + } else { + priv->r->route_write(r->id, r); + r->pr.fwd_sel = true; + r->pr.fwd_data = r->nh.l2_id; + r->pr.fwd_act = PIE_ACT_ROUTE_UC; + } + + if (priv->r->set_l3_nexthop) + priv->r->set_l3_nexthop(r->nh.id, r->nh.l2_id, r->nh.if_id); + + if (r->pr.id < 0) { + r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); + if (r->pr.packet_cntr >= 0) { + pr_info("Using packet counter %d\n", r->pr.packet_cntr); + r->pr.log_sel = true; + r->pr.log_data = r->pr.packet_cntr; + } + priv->r->pie_rule_add(priv, &r->pr); + } else { + int pkts = priv->r->packet_cntr_read(r->pr.packet_cntr); + pr_info("%s: total packets: %d\n", __func__, pkts); + + priv->r->pie_rule_write(priv, r->pr.id, &r->pr); + } + } + rcu_read_unlock(); + return 0; +} + +static int rtl83xx_port_ipv4_resolve(struct rtl838x_switch_priv *priv, + struct net_device *dev, __be32 ip_addr) +{ + struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); + int err = 0; + u64 mac; + + if (!n) { + n = neigh_create(&arp_tbl, &ip_addr, dev); + if (IS_ERR(n)) + return PTR_ERR(n); + } + + /* If the neigh is already resolved, then go ahead and + * install the entry, otherwise start the ARP process to + * resolve the neigh. + */ + if (n->nud_state & NUD_VALID) { + mac = ether_addr_to_u64(n->ha); + pr_info("%s: resolved mac: %016llx\n", __func__, mac); + rtl83xx_l3_nexthop_update(priv, ip_addr, mac); + } else { + pr_info("%s: need to wait\n", __func__); + neigh_event_send(n, NULL); + } + + neigh_release(n); + return err; +} + +struct rtl83xx_walk_data { + struct rtl838x_switch_priv *priv; + int port; +}; + +static int rtl83xx_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) +{ + struct rtl83xx_walk_data *data = (struct rtl83xx_walk_data *)_priv->data; + struct rtl838x_switch_priv *priv = data->priv; + int ret = 0; + int index; + + index = rtl83xx_port_is_under(lower, priv); + data->port = index; + if (index >= 0) { + pr_debug("Found DSA-port, index %d\n", index); + ret = 1; + } + + return ret; +} + +int rtl83xx_port_dev_lower_find(struct net_device *dev, struct rtl838x_switch_priv *priv) +{ + struct rtl83xx_walk_data data; + struct netdev_nested_priv _priv; + + data.priv = priv; + data.port = 0; + _priv.data = (void *)&data; + + netdev_walk_all_lower_dev(dev, rtl83xx_port_lower_walk, &_priv); + + return data.port; +} + +static struct rtl83xx_route *rtl83xx_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) +{ + struct rtl83xx_route *r; + int idx = 0, err; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->route_use_bm, MAX_ROUTES); + pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + mutex_unlock(&priv->reg_mutex); + return r; + } + + r->id = idx; + r->gw_ip = ip; + r->pr.id = -1; // We still need to allocate a rule in HW + r->is_host_route = false; + + err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params); + if (err) { + pr_err("Could not insert new rule\n"); + mutex_unlock(&priv->reg_mutex); + goto out_free; + } + + set_bit(idx, priv->route_use_bm); + + mutex_unlock(&priv->reg_mutex); + + return r; + +out_free: + kfree(r); + return NULL; +} + + +static struct rtl83xx_route *rtl83xx_host_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) +{ + struct rtl83xx_route *r; + int idx = 0, err; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->host_route_use_bm, MAX_HOST_ROUTES); + pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + mutex_unlock(&priv->reg_mutex); + return r; + } + + /* We require a unique route ID irrespective of whether it is a prefix or host + * route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry */ + r->id = idx + MAX_ROUTES; + + r->gw_ip = ip; + r->pr.id = -1; // We still need to allocate a rule in HW + r->is_host_route = true; + + err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params); + if (err) { + pr_err("Could not insert new rule\n"); + mutex_unlock(&priv->reg_mutex); + goto out_free; + } + + set_bit(idx, priv->host_route_use_bm); + + mutex_unlock(&priv->reg_mutex); + + return r; + +out_free: + kfree(r); + return NULL; +} + + + +static void rtl83xx_route_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_route *r) +{ + int id; + + if (rhltable_remove(&priv->routes, &r->linkage, route_ht_params)) + dev_warn(priv->dev, "Could not remove route\n"); + + if (r->is_host_route) { + id = priv->r->find_l3_slot(r, false); + pr_debug("%s: Got id for host route: %d\n", __func__, id); + r->attr.valid = false; + priv->r->host_route_write(id, r); + clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); + } else { + // If there is a HW representation of the route, delete it + if (priv->r->route_lookup_hw) { + id = priv->r->route_lookup_hw(r); + pr_info("%s: Got id for prefix route: %d\n", __func__, id); + r->attr.valid = false; + priv->r->route_write(id, r); + } + clear_bit(r->id, priv->route_use_bm); + } + + kfree(r); +} + +static int rtl83xx_fib4_del(struct rtl838x_switch_priv *priv, + struct fib_entry_notifier_info *info) +{ + struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct rtl83xx_route *r; + struct rhlist_head *tmp, *list; + + pr_debug("In %s, ip %pI4, len %d\n", __func__, &info->dst, info->dst_len); + rcu_read_lock(); + list = rhltable_lookup(&priv->routes, &nh->fib_nh_gw4, route_ht_params); + if (!list) { + rcu_read_unlock(); + pr_err("%s: no such gateway: %pI4\n", __func__, &nh->fib_nh_gw4); + return -ENOENT; + } + rhl_for_each_entry_rcu(r, tmp, list, linkage) { + if (r->dst_ip == info->dst && r->prefix_len == info->dst_len) { + pr_info("%s: found a route with id %d, nh-id %d\n", + __func__, r->id, r->nh.id); + break; + } + } + rcu_read_unlock(); + + rtl83xx_l2_nexthop_rm(priv, &r->nh); + + pr_debug("%s: Releasing packet counter %d\n", __func__, r->pr.packet_cntr); + set_bit(r->pr.packet_cntr, priv->packet_cntr_use_bm); + priv->r->pie_rule_rm(priv, &r->pr); + + rtl83xx_route_rm(priv, r); + + nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; + + return 0; +} + +/* + * On the RTL93xx, an L3 termination endpoint MAC address on which the router waits + * for packets to be routed needs to be allocated. + */ +static int rtl83xx_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) +{ + int i, free_mac = -1; + struct rtl93xx_rt_mac m; + + mutex_lock(&priv->reg_mutex); + for (i = 0; i < MAX_ROUTER_MACS; i++) { + priv->r->get_l3_router_mac(i, &m); + if (free_mac < 0 && !m.valid) { + free_mac = i; + continue; + } + if (m.valid && m.mac == mac) { + free_mac = i; + break; + } + } + + if (free_mac < 0) { + pr_err("No free router MACs, cannot offload\n"); + mutex_unlock(&priv->reg_mutex); + return -1; + } + + m.valid = true; + m.mac = mac; + m.p_type = 0; // An individual port, not a trunk port + m.p_id = 0x3f; // Listen on any port + m.p_id_mask = 0; + m.vid = 0; // Listen on any VLAN... + m.vid_mask = 0; // ... so mask needs to be 0 + m.mac_mask = 0xffffffffffffULL; // We want an exact match of the interface MAC + m.action = L3_FORWARD; // Route the packet + priv->r->set_l3_router_mac(free_mac, &m); + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int rtl83xx_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan) +{ + int i, free_mac = -1; + struct rtl838x_l3_intf intf; + u64 m; + + mutex_lock(&priv->reg_mutex); + for (i = 0; i < MAX_SMACS; i++) { + m = priv->r->get_l3_egress_mac(L3_EGRESS_DMACS + i); + if (free_mac < 0 && !m) { + free_mac = i; + continue; + } + if (m == mac) { + mutex_unlock(&priv->reg_mutex); + return i; + } + } + + if (free_mac < 0) { + pr_err("No free egress interface, cannot offload\n"); + return -1; + } + + // Set up default egress interface 1 + intf.vid = vlan; + intf.smac_idx = free_mac; + intf.ip4_mtu_id = 1; + intf.ip6_mtu_id = 1; + intf.ttl_scope = 1; // TTL + intf.hl_scope = 1; // Hop Limit + intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; // FORWARD + intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; // FORWARD; + priv->r->set_l3_egress_intf(free_mac, &intf); + + priv->r->set_l3_egress_mac(L3_EGRESS_DMACS + free_mac, mac); + + mutex_unlock(&priv->reg_mutex); + + return free_mac; +} + +static int rtl83xx_fib4_add(struct rtl838x_switch_priv *priv, + struct fib_entry_notifier_info *info) +{ + struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct net_device *dev = fib_info_nh(info->fi, 0)->fib_nh_dev; + int port; + struct rtl83xx_route *r; + bool to_localhost; + int vlan = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : 0; + + pr_debug("In %s, ip %pI4, len %d\n", __func__, &info->dst, info->dst_len); + if (!info->dst) { + pr_info("Not offloading default route for now\n"); + return 0; + } + + pr_debug("GW: %pI4, interface name %s, mac %016llx, vlan %d\n", &nh->fib_nh_gw4, dev->name, + ether_addr_to_u64(dev->dev_addr), vlan + ); + + port = rtl83xx_port_dev_lower_find(dev, priv); + if (port < 0) + return -1; + + // For now we only work with routes that have a gateway and are not ourself +// if ((!nh->fib_nh_gw4) && (info->dst_len != 32)) +// return 0; + + if ((info->dst & 0xff) == 0xff) + return 0; + + // Do not offload routes to 192.168.100.x + if ((info->dst & 0xffffff00) == 0xc0a86400) + return 0; + + // Do not offload routes to 127.x.x.x + if ((info->dst & 0xff000000) == 0x7f000000) + return 0; + + // Allocate route or host-route (entry if hardware supports this) + if (info->dst_len == 32 && priv->r->host_route_write) + r = rtl83xx_host_route_alloc(priv, nh->fib_nh_gw4); + else + r = rtl83xx_route_alloc(priv, nh->fib_nh_gw4); + + if (!r) { + pr_err("%s: No more free route entries\n", __func__); + return -1; + } + + r->dst_ip = info->dst; + r->prefix_len = info->dst_len; + r->nh.rvid = vlan; + to_localhost = !nh->fib_nh_gw4; + + if (priv->r->set_l3_router_mac) { + u64 mac = ether_addr_to_u64(dev->dev_addr); + + pr_debug("Local route and router mac %016llx\n", mac); + + if (rtl83xx_alloc_router_mac(priv, mac)) + goto out_free_rt; + + // vid = 0: Do not care about VID + r->nh.if_id = rtl83xx_alloc_egress_intf(priv, mac, vlan); + if (r->nh.if_id < 0) + goto out_free_rmac; + + if (to_localhost) { + int slot; + + r->nh.mac = mac; + r->nh.port = priv->port_ignore; + r->attr.valid = true; + r->attr.action = ROUTE_ACT_TRAP2CPU; + r->attr.type = 0; + + slot = priv->r->find_l3_slot(r, false); + pr_debug("%s: Got slot for route: %d\n", __func__, slot); + priv->r->host_route_write(slot, r); + } + } + + // We need to resolve the mac address of the GW + if (!to_localhost) + rtl83xx_port_ipv4_resolve(priv, dev, nh->fib_nh_gw4); + + nh->fib_nh_flags |= RTNH_F_OFFLOAD; + + return 0; + +out_free_rmac: +out_free_rt: + return 0; +} + +static int rtl83xx_fib6_add(struct rtl838x_switch_priv *priv, + struct fib6_entry_notifier_info *info) +{ + pr_debug("In %s\n", __func__); +// nh->fib_nh_flags |= RTNH_F_OFFLOAD; + return 0; +} + +struct net_event_work { + struct work_struct work; + struct rtl838x_switch_priv *priv; + u64 mac; + u32 gw_addr; +}; + +static void rtl83xx_net_event_work_do(struct work_struct *work) +{ + struct net_event_work *net_work = + container_of(work, struct net_event_work, work); + struct rtl838x_switch_priv *priv = net_work->priv; + + rtl83xx_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac); +} + +static int rtl83xx_netevent_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct rtl838x_switch_priv *priv; + struct net_device *dev; + struct neighbour *n = ptr; + int err, port; + struct net_event_work *net_work; + + priv = container_of(this, struct rtl838x_switch_priv, ne_nb); + + net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); + if (!net_work) + return NOTIFY_BAD; + + INIT_WORK(&net_work->work, rtl83xx_net_event_work_do); + net_work->priv = priv; + + switch (event) { + case NETEVENT_NEIGH_UPDATE: + if (n->tbl != &arp_tbl) + return NOTIFY_DONE; + dev = n->dev; + port = rtl83xx_port_dev_lower_find(dev, priv); + if (port < 0 || !(n->nud_state & NUD_VALID)) { + pr_debug("%s: Neigbour invalid, not updating\n", __func__); + kfree(net_work); + return NOTIFY_DONE; + } + + net_work->mac = ether_addr_to_u64(n->ha); + net_work->gw_addr = *(__be32 *) n->primary_key; + + pr_debug("%s: updating neighbour on port %d, mac %016llx\n", + __func__, port, net_work->mac); + schedule_work(&net_work->work); + if (err) + netdev_warn(dev, "failed to handle neigh update (err %d)\n", err); + break; + } + + return NOTIFY_DONE; +} + +struct rtl83xx_fib_event_work { + struct work_struct work; + union { + struct fib_entry_notifier_info fen_info; + struct fib6_entry_notifier_info fen6_info; + struct fib_rule_notifier_info fr_info; + }; + struct rtl838x_switch_priv *priv; + bool is_fib6; + unsigned long event; +}; + +static void rtl83xx_fib_event_work_do(struct work_struct *work) +{ + struct rtl83xx_fib_event_work *fib_work = + container_of(work, struct rtl83xx_fib_event_work, work); + struct rtl838x_switch_priv *priv = fib_work->priv; + struct fib_rule *rule; + int err; + + /* Protect internal structures from changes */ + rtnl_lock(); + pr_debug("%s: doing work, event %ld\n", __func__, fib_work->event); + switch (fib_work->event) { + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: + if (fib_work->is_fib6) { + err = rtl83xx_fib6_add(priv, &fib_work->fen6_info); + } else { + err = rtl83xx_fib4_add(priv, &fib_work->fen_info); + fib_info_put(fib_work->fen_info.fi); + } + if (err) + pr_err("%s: FIB4 failed\n", __func__); + break; + case FIB_EVENT_ENTRY_DEL: + rtl83xx_fib4_del(priv, &fib_work->fen_info); + fib_info_put(fib_work->fen_info.fi); + break; + case FIB_EVENT_RULE_ADD: + case FIB_EVENT_RULE_DEL: + rule = fib_work->fr_info.rule; + if (!fib4_rule_default(rule)) + pr_err("%s: FIB4 default rule failed\n", __func__); + fib_rule_put(rule); + break; + } + rtnl_unlock(); + kfree(fib_work); +} + +/* Called with rcu_read_lock() */ +static int rtl83xx_fib_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct fib_notifier_info *info = ptr; + struct rtl838x_switch_priv *priv; + struct rtl83xx_fib_event_work *fib_work; + + if ((info->family != AF_INET && info->family != AF_INET6 && + info->family != RTNL_FAMILY_IPMR && + info->family != RTNL_FAMILY_IP6MR)) + return NOTIFY_DONE; + + priv = container_of(this, struct rtl838x_switch_priv, fib_nb); + + fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); + if (!fib_work) + return NOTIFY_BAD; + + INIT_WORK(&fib_work->work, rtl83xx_fib_event_work_do); + fib_work->priv = priv; + fib_work->event = event; + fib_work->is_fib6 = false; + + switch (event) { + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: + case FIB_EVENT_ENTRY_DEL: + pr_debug("%s: FIB_ENTRY ADD/DELL, event %ld\n", __func__, event); + if (info->family == AF_INET) { + struct fib_entry_notifier_info *fen_info = ptr; + + if (fen_info->fi->fib_nh_is_v6) { + NL_SET_ERR_MSG_MOD(info->extack, + "IPv6 gateway with IPv4 route is not supported"); + kfree(fib_work); + return notifier_from_errno(-EINVAL); + } + + memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info)); + /* Take referece on fib_info to prevent it from being + * freed while work is queued. Release it afterwards. + */ + fib_info_hold(fib_work->fen_info.fi); + + } else if (info->family == AF_INET6) { + struct fib6_entry_notifier_info *fen6_info = ptr; + pr_warn("%s: FIB_RULE ADD/DELL for IPv6 not supported\n", __func__); + kfree(fib_work); + return notifier_from_errno(-EINVAL); + } + break; + + case FIB_EVENT_RULE_ADD: + case FIB_EVENT_RULE_DEL: + pr_debug("%s: FIB_RULE ADD/DELL, event: %ld\n", __func__, event); + memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); + fib_rule_get(fib_work->fr_info.rule); + break; + } + + schedule_work(&fib_work->work); + + return NOTIFY_DONE; +} + static int __init rtl83xx_sw_probe(struct platform_device *pdev) { int err = 0, i; @@ -623,6 +1388,8 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) priv->ds->ops = &rtl83xx_switch_ops; priv->dev = dev; + mutex_init(&priv->reg_mutex); + priv->family_id = soc_info.family; priv->id = soc_info.id; switch(soc_info.family) { @@ -751,18 +1518,51 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) rtl83xx_setup_qos(priv); + priv->r->l3_setup(priv); + /* Clear all destination ports for mirror groups */ for (i = 0; i < 4; i++) priv->mirror_group_ports[i] = -1; + /* + * Register netdevice event callback to catch changes in link aggregation groups + */ priv->nb.notifier_call = rtl83xx_netdevice_event; - if (register_netdevice_notifier(&priv->nb)) { - priv->nb.notifier_call = NULL; - dev_err(dev, "Failed to register LAG netdev notifier\n"); + if (register_netdevice_notifier(&priv->nb)) { + priv->nb.notifier_call = NULL; + dev_err(dev, "Failed to register LAG netdev notifier\n"); + goto err_register_nb; } + // Initialize hash table for L3 routing + rhltable_init(&priv->routes, &route_ht_params); + + /* + * Register netevent notifier callback to catch notifications about neighboring + * changes to update nexthop entries for L3 routing. + */ + priv->ne_nb.notifier_call = rtl83xx_netevent_event; + if (register_netevent_notifier(&priv->ne_nb)) { + priv->ne_nb.notifier_call = NULL; + dev_err(dev, "Failed to register netevent notifier\n"); + goto err_register_ne_nb; + } + + priv->fib_nb.notifier_call = rtl83xx_fib_event; + + /* + * Register Forwarding Information Base notifier to offload routes where + * where possible + * Only FIBs pointing to our own netdevs are programmed into + * the device, so no need to pass a callback. + */ + err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL); + if (err) + goto err_register_fib_nb; + + // TODO: put this into l2_setup() // Flood BPDUs to all ports including cpu-port - if (soc_info.family != RTL9300_FAMILY_ID) { // TODO: Port this functionality + if (soc_info.family != RTL9300_FAMILY_ID) { bpdu_mask = soc_info.family == RTL8380_FAMILY_ID ? 0x1FFFFFFF : 0x1FFFFFFFFFFFFF; priv->r->set_port_reg_be(bpdu_mask, priv->r->rma_bpdu_fld_pmask); @@ -772,6 +1572,13 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) rtl838x_dbgfs_init(priv); } + return 0; + +err_register_fib_nb: + unregister_netevent_notifier(&priv->ne_nb); +err_register_ne_nb: + unregister_netdevice_notifier(&priv->nb); +err_register_nb: return err; } diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h index 6ff59c4348..c9307458f8 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.h @@ -66,29 +66,28 @@ #define RTL838X_VLAN_PROFILE(idx) (0x3A88 + ((idx) << 2)) #define RTL838X_VLAN_PORT_EGR_FLTR (0x3A84) #define RTL838X_VLAN_PORT_PB_VLAN (0x3C00) -#define RTL838X_VLAN_PORT_IGR_FLTR(port) (0x3A7C + (((port >> 4) << 2))) -#define RTL838X_VLAN_PORT_IGR_FLTR_0 (0x3A7C) -#define RTL838X_VLAN_PORT_IGR_FLTR_1 (0x3A7C + 4) +#define RTL838X_VLAN_PORT_IGR_FLTR (0x3A7C) #define RTL838X_VLAN_PORT_TAG_STS_CTRL (0xA530) #define RTL839X_VLAN_PROFILE(idx) (0x25C0 + (((idx) << 3))) #define RTL839X_VLAN_CTRL (0x26D4) #define RTL839X_VLAN_PORT_PB_VLAN (0x26D8) -#define RTL839X_VLAN_PORT_IGR_FLTR(port) (0x27B4 + (((port >> 4) << 2))) -#define RTL839X_VLAN_PORT_EGR_FLTR(port) (0x27C4 + (((port >> 5) << 2))) +#define RTL839X_VLAN_PORT_IGR_FLTR (0x27B4) +#define RTL839X_VLAN_PORT_EGR_FLTR (0x27C4) +#define RTL839X_VLAN_PORT_TAG_STS_CTRL (0x6828) #define RTL839X_VLAN_PORT_TAG_STS_CTRL (0x6828) #define RTL930X_VLAN_PROFILE_SET(idx) (0x9c60 + (((idx) * 20))) #define RTL930X_VLAN_CTRL (0x82D4) #define RTL930X_VLAN_PORT_PB_VLAN (0x82D8) -#define RTL930X_VLAN_PORT_IGR_FLTR(port) (0x83C0 + (((port >> 4) << 2))) +#define RTL930X_VLAN_PORT_IGR_FLTR (0x83C0) #define RTL930X_VLAN_PORT_EGR_FLTR (0x83C8) #define RTL930X_VLAN_PORT_TAG_STS_CTRL (0xCE24) #define RTL931X_VLAN_PROFILE_SET(idx) (0x9800 + (((idx) * 28))) #define RTL931X_VLAN_CTRL (0x94E4) -#define RTL931X_VLAN_PORT_IGR_FLTR(port) (0x96B4 + (((port >> 4) << 2))) -#define RTL931X_VLAN_PORT_EGR_FLTR(port) (0x96C4 + (((port >> 5) << 2))) +#define RTL931X_VLAN_PORT_IGR_FLTR (0x96B4) +#define RTL931X_VLAN_PORT_EGR_FLTR (0x96C4) #define RTL931X_VLAN_PORT_TAG_CTRL (0x4860) /* Table access registers */ @@ -379,6 +378,35 @@ #define PIE_ACT_ROUTE_UC 6 #define PIE_ACT_VID_ASSIGN 0 +// L3 actions +#define L3_FORWARD 0 +#define L3_DROP 1 +#define L3_TRAP2CPU 2 +#define L3_COPY2CPU 3 +#define L3_TRAP2MASTERCPU 4 +#define L3_COPY2MASTERCPU 5 +#define L3_HARDDROP 6 + +// Route actions +#define ROUTE_ACT_FORWARD 0 +#define ROUTE_ACT_TRAP2CPU 1 +#define ROUTE_ACT_COPY2CPU 2 +#define ROUTE_ACT_DROP 3 + +/* L3 Routing */ +#define RTL839X_ROUTING_SA_CTRL 0x6afc +#define RTL930X_L3_HOST_TBL_CTRL (0xAB48) +#define RTL930X_L3_IPUC_ROUTE_CTRL (0xAB4C) +#define RTL930X_L3_IP6UC_ROUTE_CTRL (0xAB50) +#define RTL930X_L3_IPMC_ROUTE_CTRL (0xAB54) +#define RTL930X_L3_IP6MC_ROUTE_CTRL (0xAB58) +#define RTL930X_L3_IP_MTU_CTRL(i) (0xAB5C + ((i >> 1) << 2)) +#define RTL930X_L3_IP6_MTU_CTRL(i) (0xAB6C + ((i >> 1) << 2)) +#define RTL930X_L3_HW_LU_KEY_CTRL (0xAC9C) +#define RTL930X_L3_HW_LU_KEY_IP_CTRL (0xACA0) +#define RTL930X_L3_HW_LU_CTRL (0xACC0) +#define RTL930X_L3_IP_ROUTE_CTRL 0xab44 + #define MAX_VLANS 4096 #define MAX_LAGS 16 #define MAX_PRIOS 8 @@ -389,6 +417,14 @@ #define MAX_PIE_ENTRIES (18 * PIE_BLOCK_SIZE) #define N_FIXED_FIELDS 12 #define MAX_COUNTERS 2048 +#define MAX_ROUTES 512 +#define MAX_HOST_ROUTES 1536 +#define MAX_INTF_MTUS 8 +#define DEFAULT_MTU 1536 +#define MAX_INTERFACES 100 +#define MAX_ROUTER_MACS 64 +#define L3_EGRESS_DMACS 2048 +#define MAX_SMACS 64 enum phy_type { PHY_NONE = 0, @@ -614,17 +650,52 @@ struct pie_rule { bool bypass_ibc_sc; // Bypass Ingress Bandwidth Control and Storm Control }; -struct rtl838x_nexthop { - u16 id; // ID in HW Nexthop table - u32 ip; // IP Addres of nexthop +struct rtl838x_l3_intf { + u16 vid; + u8 smac_idx; + u8 ip4_mtu_id; + u8 ip6_mtu_id; + u16 ip4_mtu; + u16 ip6_mtu; + u8 ttl_scope; + u8 hl_scope; + u8 ip4_icmp_redirect; + u8 ip6_icmp_redirect; + u8 ip4_pbr_icmp_redirect; + u8 ip6_pbr_icmp_redirect; +}; + +/* + * An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point + * for the L3 routing system. Packets arriving and matching an entry in this table + * will be considered for routing. + * Mask fields state whether the corresponding data fields matter for matching + */ +struct rtl93xx_rt_mac { + bool valid; // Valid or not + bool p_type; // Individual (0) or trunk (1) port + bool p_mask; // Whether the port type is used + u8 p_id; + u8 p_id_mask; // Mask for the port + u8 action; // Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU + // 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP + u16 vid; + u16 vid_mask; + u64 mac; // MAC address used as source MAC in the routed packet + u64 mac_mask; +}; + +struct rtl83xx_nexthop { + u16 id; // ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP u32 dev_id; u16 port; - u16 vid; - u16 fid; - u64 mac; + u16 vid; // VLAN-ID for L2 table entry (saved from L2-UC entry) + u16 rvid; // Relay VID/FID for the L2 table entry + u64 mac; // The MAC address of the entry in the L2_NEXT_HOP table u16 mac_id; u16 l2_id; // Index of this next hop forwarding entry in L2 FIB table - u16 if_id; + u64 gw; // The gateway MAC address packets are forwarded to + int if_id; // Interface (into L3_EGR_INTF_IDX) }; struct rtl838x_switch_priv; @@ -638,6 +709,32 @@ struct rtl83xx_flow { u32 flags; }; +struct rtl93xx_route_attr { + bool valid; + bool hit; + bool ttl_dec; + bool ttl_check; + bool dst_null; + bool qos_as; + u8 qos_prio; + u8 type; + u8 action; +}; + +struct rtl83xx_route { + u32 gw_ip; // IP of the route's gateway + u32 dst_ip; // IP of the destination net + struct in6_addr dst_ip6; + int prefix_len; // Network prefix len of the destination net + bool is_host_route; + int id; // ID number of this route + struct rhlist_head linkage; + u16 switch_mac_id; // Index into switch's own MACs, RTL839X only + struct rtl83xx_nexthop nh; + struct pie_rule pr; + struct rtl93xx_route_attr attr; +}; + struct rtl838x_reg { void (*mask_port_reg_be)(u64 clear, u64 set, int reg); void (*set_port_reg_be)(u64 set, int reg); @@ -713,6 +810,19 @@ struct rtl838x_reg { void (*l2_learning_setup)(void); u32 (*packet_cntr_read)(int counter); void (*packet_cntr_clear)(int counter); + void (*route_read)(int idx, struct rtl83xx_route *rt); + void (*route_write)(int idx, struct rtl83xx_route *rt); + void (*host_route_write)(int idx, struct rtl83xx_route *rt); + int (*l3_setup)(struct rtl838x_switch_priv *priv); + void (*set_l3_nexthop)(int idx, u16 dmac_id, u16 interface); + void (*get_l3_nexthop)(int idx, u16 *dmac_id, u16 *interface); + u64 (*get_l3_egress_mac)(u32 idx); + void (*set_l3_egress_mac)(u32 idx, u64 mac); + int (*find_l3_slot)(struct rtl83xx_route *rt, bool must_exist); + int (*route_lookup_hw)(struct rtl83xx_route *rt); + void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); + void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); + void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf); }; struct rtl838x_switch_priv { @@ -740,7 +850,9 @@ struct rtl838x_switch_priv { int n_lags; u64 lags_port_members[MAX_LAGS]; struct net_device *lag_devs[MAX_LAGS]; - struct notifier_block nb; + struct notifier_block nb; // TODO: change to different name + struct notifier_block ne_nb; + struct notifier_block fib_nb; bool eee_enabled; unsigned long int mc_group_bm[MAX_MC_GROUPS >> 5]; int n_pie_blocks; @@ -749,8 +861,15 @@ struct rtl838x_switch_priv { int n_counters; unsigned long int octet_cntr_use_bm[MAX_COUNTERS >> 5]; unsigned long int packet_cntr_use_bm[MAX_COUNTERS >> 4]; + struct rhltable routes; + unsigned long int route_use_bm[MAX_ROUTES >> 5]; + unsigned long int host_route_use_bm[MAX_HOST_ROUTES >> 5]; + struct rtl838x_l3_intf *interfaces[MAX_INTERFACES]; + u16 intf_mtus[MAX_INTF_MTUS]; + int intf_mtu_count[MAX_INTF_MTUS]; }; void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv); +void rtl930x_dbgfs_init(struct rtl838x_switch_priv *priv); #endif /* _RTL838X_H */ From 1f402512ae0474ffd03c34bcfa54b2882d927861 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Fri, 10 Sep 2021 15:06:24 +0200 Subject: [PATCH 25/59] realtek: Add SoC-specific routing offload implementation Adds SoC specific routing offload implementations for RTL8380/90 and RTL9300. RTL83xx supports merely nexthop routing, RTL9300 full host and prefix routes. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/rtl838x.c | 77 +- .../drivers/net/dsa/rtl83xx/rtl839x.c | 114 ++- .../drivers/net/dsa/rtl83xx/rtl930x.c | 908 +++++++++++++++--- .../drivers/net/dsa/rtl83xx/rtl931x.c | 4 +- 4 files changed, 938 insertions(+), 165 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c index 15a486d724..7470fff5eb 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl838x.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only #include +#include + #include "rtl83xx.h" extern struct mutex smi_lock; @@ -290,9 +292,10 @@ static void rtl838x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) e->suspended = !!(r[1] & BIT(29)); e->next_hop = !!(r[1] & BIT(28)); if (e->next_hop) { - pr_info("Found next hop entry, need to read extra data\n"); + pr_debug("Found next hop entry, need to read extra data\n"); e->nh_vlan_target = !!(r[0] & BIT(9)); e->nh_route_id = r[0] & 0x1ff; + e->vid = e->rvid; } e->age = (r[0] >> 17) & 0x3; e->valid = true; @@ -304,7 +307,7 @@ static void rtl838x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) else e->type = L2_UNICAST; } else { // L2 multicast - pr_info("Got L2 MC entry: %08x %08x %08x\n", r[0], r[1], r[2]); + pr_debug("Got L2 MC entry: %08x %08x %08x\n", r[0], r[1], r[2]); e->valid = true; e->type = L2_MULTICAST; e->mc_portmask_index = (r[0] >> 12) & 0x1ff; @@ -312,9 +315,8 @@ static void rtl838x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) } else { // IPv4 and IPv6 multicast e->valid = true; e->mc_portmask_index = (r[0] >> 12) & 0x1ff; - e->mc_gip = r[1]; - e->mc_sip = r[2]; - e->rvid = r[0] & 0xfff; + e->mc_gip = (r[1] << 20) | (r[2] >> 12); + e->rvid = r[2] & 0xfff; } if (e->is_ip_mc) e->type = IP4_MULTICAST; @@ -353,19 +355,20 @@ static void rtl838x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) if (e->next_hop) { r[1] |= BIT(28); r[0] |= e->nh_vlan_target ? BIT(9) : 0; - r[0] |= e->nh_route_id &0x1ff; + r[0] |= e->nh_route_id & 0x1ff; } r[0] |= (e->age & 0x3) << 17; } else { // L2 Multicast r[0] |= (e->mc_portmask_index & 0x1ff) << 12; r[2] |= e->rvid & 0xfff; r[0] |= e->vid & 0xfff; - pr_info("FILL MC: %08x %08x %08x\n", r[0], r[1], r[2]); + pr_debug("FILL MC: %08x %08x %08x\n", r[0], r[1], r[2]); } } else { // IPv4 and IPv6 multicast - r[1] = e->mc_gip; - r[2] = e->mc_sip; - r[0] |= e->rvid; + r[0] |= (e->mc_portmask_index & 0x1ff) << 12; + r[1] = e->mc_gip >> 20; + r[2] = e->mc_gip << 12; + r[2] |= e->rvid; } } @@ -392,7 +395,7 @@ static u64 rtl838x_read_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_l2 if (!e->valid) return 0; - entry = (((u64) r[1]) << 32) | (r[2] & 0xfffff000) | (r[0] & 0xfff); + entry = (((u64) r[1]) << 32) | (r[2]); // mac and vid concatenated as hash seed return entry; } @@ -433,7 +436,7 @@ static u64 rtl838x_read_cam(int idx, struct rtl838x_l2_entry *e) pr_debug("Found in CAM: R1 %x R2 %x R3 %x\n", r[0], r[1], r[2]); // Return MAC with concatenated VID ac concatenated ID - entry = (((u64) r[1]) << 32) | (r[2] & 0xfffff000) | (r[0] & 0xfff); + entry = (((u64) r[1]) << 32) | r[2]; return entry; } @@ -509,16 +512,6 @@ static void rtl838x_l2_learning_setup(void) sw_w32(0, RTL838X_SPCL_TRAP_ARP_CTRL); } -static inline int rtl838x_vlan_port_egr_filter(int port) -{ - return RTL838X_VLAN_PORT_EGR_FLTR; -} - -static inline int rtl838x_vlan_port_igr_filter(int port) -{ - return RTL838X_VLAN_PORT_IGR_FLTR(port); -} - static void rtl838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) { int i; @@ -1553,6 +1546,41 @@ static void rtl838x_packet_cntr_clear(int counter) rtl_table_release(r); } +static void rtl838x_route_read(int idx, struct rtl83xx_route *rt) +{ + // Read ROUTING table (2) via register RTL8380_TBL_1 + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); + + pr_debug("In %s, id %d\n", __func__, idx); + rtl_table_read(r, idx); + + // The table has a size of 2 registers + rt->nh.gw = sw_r32(rtl_table_data(r, 0)); + rt->nh.gw <<= 32; + rt->nh.gw |= sw_r32(rtl_table_data(r, 1)); + + rtl_table_release(r); +} + +static void rtl838x_route_write(int idx, struct rtl83xx_route *rt) +{ + // Access ROUTING table (2) via register RTL8380_TBL_1 + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); + + pr_debug("In %s, id %d, gw: %016llx\n", __func__, idx, rt->nh.gw); + sw_w32(rt->nh.gw >> 32, rtl_table_data(r, 0)); + sw_w32(rt->nh.gw, rtl_table_data(r, 1)); + rtl_table_write(r, idx); + + rtl_table_release(r); +} + +static int rtl838x_l3_setup(struct rtl838x_switch_priv *priv) +{ + // Nothing to be done + return 0; +} + const struct rtl838x_reg rtl838x_reg = { .mask_port_reg_be = rtl838x_mask_port_reg, .set_port_reg_be = rtl838x_set_port_reg, @@ -1605,7 +1633,7 @@ const struct rtl838x_reg rtl838x_reg = { .read_cam = rtl838x_read_cam, .write_cam = rtl838x_write_cam, .vlan_port_egr_filter = RTL838X_VLAN_PORT_EGR_FLTR, - .vlan_port_igr_filter = RTL838X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_igr_filter = RTL838X_VLAN_PORT_IGR_FLTR, .vlan_port_pb = RTL838X_VLAN_PORT_PB_VLAN, .vlan_port_tag_sts_ctrl = RTL838X_VLAN_PORT_TAG_STS_CTRL, .trk_mbr_ctr = rtl838x_trk_mbr_ctr, @@ -1626,6 +1654,9 @@ const struct rtl838x_reg rtl838x_reg = { .l2_learning_setup = rtl838x_l2_learning_setup, .packet_cntr_read = rtl838x_packet_cntr_read, .packet_cntr_clear = rtl838x_packet_cntr_clear, + .route_read = rtl838x_route_read, + .route_write = rtl838x_route_write, + .l3_setup = rtl838x_l3_setup, }; irqreturn_t rtl838x_switch_irq(int irq, void *dev_id) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c index 4ed2184efa..cca8824ce5 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c @@ -300,7 +300,7 @@ static void rtl839x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) e->is_ip_mc = !!(r[2] & BIT(31)); e->is_ipv6_mc = !!(r[2] & BIT(30)); e->type = L2_INVALID; - if (!e->is_ip_mc) { + if (!e->is_ip_mc && !e->is_ipv6_mc) { e->mac[0] = (r[0] >> 12); e->mac[1] = (r[0] >> 4); e->mac[2] = ((r[1] >> 28) | (r[0] << 4)); @@ -308,18 +308,23 @@ static void rtl839x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) e->mac[4] = (r[1] >> 12); e->mac[5] = (r[1] >> 4); + e->vid = (r[2] >> 4) & 0xfff; + e->rvid = (r[0] >> 20) & 0xfff; + /* Is it a unicast entry? check multicast bit */ if (!(e->mac[0] & 1)) { e->is_static = !!((r[2] >> 18) & 1); - e->vid = (r[2] >> 4) & 0xfff; - e->rvid = (r[0] >> 20) & 0xfff; e->port = (r[2] >> 24) & 0x3f; e->block_da = !!(r[2] & (1 << 19)); e->block_sa = !!(r[2] & (1 << 20)); e->suspended = !!(r[2] & (1 << 17)); e->next_hop = !!(r[2] & (1 << 16)); - if (e->next_hop) - pr_info("Found next hop entry, need to read data\n"); + if (e->next_hop) { + pr_debug("Found next hop entry, need to read data\n"); + e->nh_vlan_target = !!(r[2] & BIT(15)); + e->nh_route_id = (r[2] >> 4) & 0x1ff; + e->vid = e->rvid; + } e->age = (r[2] >> 21) & 3; e->valid = true; if (!(r[2] & 0xc0fd0000)) /* Check for valid entry */ @@ -329,8 +334,13 @@ static void rtl839x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) } else { e->valid = true; e->type = L2_MULTICAST; - e->mc_portmask_index = (r[2]>>6) & 0xfff; + e->mc_portmask_index = (r[2] >> 6) & 0xfff; + e->vid = e->rvid; } + } else { // IPv4 and IPv6 multicast + e->vid = e->rvid = (r[0] << 20) & 0xfff; + e->mc_gip = r[1]; + e->mc_portmask_index = (r[2] >> 6) & 0xfff; } if (e->is_ip_mc) { e->valid = true; @@ -340,10 +350,11 @@ static void rtl839x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) e->valid = true; e->type = IP6_MULTICAST; } + // pr_info("%s: vid %d, rvid: %d\n", __func__, e->vid, e->rvid); } /* - * Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry + * Fills the 3 SoC table registers r[] with the information in the rtl838x_l2_entry */ static void rtl839x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) { @@ -366,27 +377,28 @@ static void rtl839x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) if (!(e->mac[0] & 1)) { // Not multicast r[2] |= e->is_static ? BIT(18) : 0; - r[2] |= e->vid << 4; r[0] |= ((u32)e->rvid) << 20; r[2] |= e->port << 24; r[2] |= e->block_da ? BIT(19) : 0; r[2] |= e->block_sa ? BIT(20) : 0; r[2] |= e->suspended ? BIT(17) : 0; + r[2] |= ((u32)e->age) << 21; if (e->next_hop) { r[2] |= BIT(16); r[2] |= e->nh_vlan_target ? BIT(15) : 0; r[2] |= (e->nh_route_id & 0x7ff) << 4; + } else { + r[2] |= e->vid << 4; } - r[2] |= ((u32)e->age) << 21; + pr_debug("Write L2 NH: %08x %08x %08x\n", r[0], r[1], r[2]); } else { // L2 Multicast r[0] |= ((u32)e->rvid) << 20; r[2] |= ((u32)e->mc_portmask_index) << 6; - pr_debug("Write L2 MC entry: %08x %08x %08x\n", r[0], r[1], r[2]); } } else { // IPv4 or IPv6 MC entry r[0] = ((u32)e->rvid) << 20; - r[2] |= ((u32)e->mc_portmask_index) << 6; r[1] = e->mc_gip; + r[2] |= ((u32)e->mc_portmask_index) << 6; } } @@ -512,16 +524,6 @@ static void rtl839x_vlan_profile_setup(int profile) rtl839x_write_mcast_pmask(UNKNOWN_MC_PMASK, 0x001fffffffffffff); } -static inline int rtl839x_vlan_port_egr_filter(int port) -{ - return RTL839X_VLAN_PORT_EGR_FLTR(port); -} - -static inline int rtl839x_vlan_port_igr_filter(int port) -{ - return RTL839X_VLAN_PORT_IGR_FLTR(port); -} - u64 rtl839x_traffic_get(int source) { return rtl839x_get_port_reg_be(rtl839x_port_iso_ctrl(source)); @@ -1621,6 +1623,69 @@ static void rtl839x_packet_cntr_clear(int counter) rtl_table_release(r); } +static void rtl839x_route_read(int idx, struct rtl83xx_route *rt) +{ + u64 v; + // Read ROUTING table (2) via register RTL8390_TBL_1 + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); + + pr_debug("In %s\n", __func__); + rtl_table_read(r, idx); + + // The table has a size of 2 registers + v = sw_r32(rtl_table_data(r, 0)); + v <<= 32; + v |= sw_r32(rtl_table_data(r, 1)); + rt->switch_mac_id = (v >> 12) & 0xf; + rt->nh.gw = v >> 16; + + rtl_table_release(r); +} + +static void rtl839x_route_write(int idx, struct rtl83xx_route *rt) +{ + u32 v; + + // Read ROUTING table (2) via register RTL8390_TBL_1 + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); + + pr_debug("In %s\n", __func__); + sw_w32(rt->nh.gw >> 16, rtl_table_data(r, 0)); + v = rt->nh.gw << 16; + v |= rt->switch_mac_id << 12; + sw_w32(v, rtl_table_data(r, 1)); + rtl_table_write(r, idx); + + rtl_table_release(r); +} + +/* + * Configure the switch's own MAC addresses used when routing packets + */ +static void rtl839x_setup_port_macs(struct rtl838x_switch_priv *priv) +{ + int i; + struct net_device *dev; + u64 mac; + + pr_debug("%s: got port %08x\n", __func__, (u32)priv->ports[priv->cpu_port].dp); + dev = priv->ports[priv->cpu_port].dp->slave; + mac = ether_addr_to_u64(dev->dev_addr); + + for (i = 0; i < 15; i++) { + mac++; // BUG: VRRP for testing + sw_w32(mac >> 32, RTL839X_ROUTING_SA_CTRL + i * 8); + sw_w32(mac, RTL839X_ROUTING_SA_CTRL + i * 8 + 4); + } +} + +int rtl839x_l3_setup(struct rtl838x_switch_priv *priv) +{ + rtl839x_setup_port_macs(priv); + + return 0; +} + const struct rtl838x_reg rtl839x_reg = { .mask_port_reg_be = rtl839x_mask_port_reg_be, .set_port_reg_be = rtl839x_set_port_reg_be, @@ -1672,8 +1737,8 @@ const struct rtl838x_reg rtl839x_reg = { .write_l2_entry_using_hash = rtl839x_write_l2_entry_using_hash, .read_cam = rtl839x_read_cam, .write_cam = rtl839x_write_cam, - .vlan_port_egr_filter = RTL839X_VLAN_PORT_EGR_FLTR(0), - .vlan_port_igr_filter = RTL839X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_egr_filter = RTL839X_VLAN_PORT_EGR_FLTR, + .vlan_port_igr_filter = RTL839X_VLAN_PORT_IGR_FLTR, .vlan_port_pb = RTL839X_VLAN_PORT_PB_VLAN, .vlan_port_tag_sts_ctrl = RTL839X_VLAN_PORT_TAG_STS_CTRL, .trk_mbr_ctr = rtl839x_trk_mbr_ctr, @@ -1694,4 +1759,7 @@ const struct rtl838x_reg rtl839x_reg = { .l2_learning_setup = rtl839x_l2_learning_setup, .packet_cntr_read = rtl839x_packet_cntr_read, .packet_cntr_clear = rtl839x_packet_cntr_clear, + .route_read = rtl839x_route_read, + .route_write = rtl839x_route_write, + .l3_setup = rtl839x_l3_setup, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c index aa6306c1c6..92426be1f3 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl930x.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only #include +#include + #include "rtl83xx.h" extern struct mutex smi_lock; @@ -412,7 +414,7 @@ static void rtl930x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e) e->valid = true; // the UC_VID field in hardware is used for the VID or for the route id if (e->next_hop) { - e->nh_route_id = r[2] & 0xfff; + e->nh_route_id = r[2] & 0x7ff; e->vid = 0; } else { e->vid = r[2] & 0xfff; @@ -463,7 +465,7 @@ static void rtl930x_fill_l2_row(u32 r[], struct rtl838x_l2_entry *e) r[2] |= (e->age & 0x3) << 17; // the UC_VID field in hardware is used for the VID or for the route id if (e->next_hop) - r[2] |= e->nh_route_id & 0xfff; + r[2] |= e->nh_route_id & 0x7ff; else r[2] |= e->vid & 0xfff; } else { // L2_MULTICAST @@ -529,8 +531,8 @@ static void rtl930x_write_l2_entry_using_hash(u32 hash, u32 pos, struct rtl838x_ u32 idx = (0 << 14) | (hash << 2) | pos; // Access SRAM, with hash and at pos in bucket int i; - pr_info("%s: hash %d, pos %d\n", __func__, hash, pos); - pr_info("%s: index %d -> mac %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, idx, + pr_debug("%s: hash %d, pos %d\n", __func__, hash, pos); + pr_debug("%s: index %d -> mac %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, idx, e->mac[0], e->mac[1], e->mac[2], e->mac[3],e->mac[4],e->mac[5]); rtl930x_fill_l2_row(r, e); @@ -593,80 +595,6 @@ static void dump_l2_entry(struct rtl838x_l2_entry *e) e->stack_dev, e->nh_route_id, e->port); } -/* - * Add an L2 nexthop entry for the L3 routing system in the SoC - * Use VID and MAC in rtl838x_l2_entry to identify either a free slot in the L2 hash table - * or mark an existing entry as a nexthop by setting it's nexthop bit - * Called from the L3 layer - * The index in the L2 hash table is filled into nh->l2_id; - */ -static int rtl930x_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl838x_nexthop *nh) -{ - struct rtl838x_l2_entry e; - u64 seed = rtl930x_l2_hash_seed(nh->mac, nh->vid); - u32 key = rtl930x_l2_hash_key(priv, seed); - int i, idx = -1; - u64 entry; - - pr_info("%s searching for %08llx vid %d with key %d, seed: %016llx\n", - __func__, nh->mac, nh->vid, key, seed); - - e.type = L2_UNICAST; - e.rvid = nh->fid; // Verify its the forwarding ID!!! l2_entry.un.unicast.fid - u64_to_ether_addr(nh->mac, &e.mac[0]); - e.port = RTL930X_PORT_IGNORE; - - // Loop over all entries in the hash-bucket and over the second block on 93xx SoCs - for (i = 0; i < priv->l2_bucket_size; i++) { - entry = rtl930x_read_l2_entry_using_hash(key, i, &e); - pr_info("%s i: %d, entry %016llx, seed %016llx\n", __func__, i, entry, seed); - if (e.valid && e.next_hop) - continue; - if (!e.valid || ((entry & 0x0fffffffffffffffULL) == seed)) { - idx = i > 3 ? ((key >> 14) & 0xffff) | i >> 1 - : ((key << 2) | i) & 0xffff; - break; - } - } - - pr_info("%s: found idx %d and i %d\n", __func__, idx, i); - - if (idx < 0) { - pr_err("%s: No more L2 forwarding entries available\n", __func__); - return -1; - } - - // Found an existing or empty entry, make it a nexthop entry - pr_info("%s BEFORE -> key %d, pos: %d, index: %d\n", __func__, key, i, idx); - dump_l2_entry(&e); - nh->l2_id = idx; - - // Found an existing (e->valid is true) or empty entry, make it a nexthop entry - if (e.valid) { - nh->port = e.port; - nh->fid = e.rvid; - nh->vid = e.vid; - nh->dev_id = e.stack_dev; - } else { - e.valid = true; - e.is_static = false; - e.vid = nh->vid; - e.rvid = nh->fid; - e.port = RTL930X_PORT_IGNORE; - u64_to_ether_addr(nh->mac, &e.mac[0]); - } - e.next_hop = true; - // For nexthop entries, the vid field in the table is used to denote the dest mac_id - e.nh_route_id = nh->mac_id; - pr_info("%s AFTER\n", __func__); - dump_l2_entry(&e); - - rtl930x_write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e); - - // _dal_longan_l2_nexthop_add - return 0; -} - static u64 rtl930x_read_mcast_pmask(int idx) { u32 portmask; @@ -767,9 +695,6 @@ irqreturn_t rtl930x_switch_irq(int irq, void *dev_id) /* Clear status */ sw_w32(ports, RTL930X_ISR_PORT_LINK_STS_CHG); - pr_info("RTL9300 Link change: status: %x, ports %x\n", status, ports); - - rtl9300_dump_debug(); for (i = 0; i < 28; i++) { if (ports & BIT(i)) { @@ -787,41 +712,6 @@ irqreturn_t rtl930x_switch_irq(int irq, void *dev_id) return IRQ_HANDLED; } -int rtl9300_sds_power(int mac, int val) -{ - int sds_num; - u32 mode; - - // TODO: these numbers are hard-coded for the Zyxel XGS1210 12 Switch - pr_info("SerDes: %s %d\n", __func__, mac); - switch (mac) { - case 24: - sds_num = 6; - mode = 0x12; // HISGMII - break; - case 25: - sds_num = 7; - mode = 0x12; // HISGMII - break; - case 26: - sds_num = 8; - mode = 0x1b; // 10GR/1000BX auto - break; - case 27: - sds_num = 9; - mode = 0x1b; // 10GR/1000BX auto - break; - default: - return -1; - } - if (!val) - mode = 0x1f; // OFF - - rtl9300_sds_rst(sds_num, mode); - - return 0; -} - int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val) { u32 v; @@ -1077,6 +967,562 @@ static void rtl930x_init_eee(struct rtl838x_switch_priv *priv, bool enable) priv->eee_enabled = enable; } +#define HASH_PICK(val, lsb, len) ((val & (((1 << len) - 1) << lsb)) >> lsb) + +static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip) +{ + u32 rows[4]; + u32 hash; + u32 s0, s1, pH; + + memset(rows, 0, sizeof(rows)); + + rows[0] = HASH_PICK(ip, 27, 5); + rows[1] = HASH_PICK(ip, 18, 9); + rows[2] = HASH_PICK(ip, 9, 9); + + if (!move_dip) + rows[3] = HASH_PICK(ip, 0, 9); + + if (!algorithm) { + hash = rows[0] ^ rows[1] ^ rows[2] ^ rows[3]; + } else { + s0 = rows[0] + rows[1] + rows[2]; + s1 = (s0 & 0x1ff) + ((s0 & (0x1ff << 9)) >> 9); + pH = (s1 & 0x1ff) + ((s1 & (0x1ff << 9)) >> 9); + hash = pH ^ rows[3]; + } + return hash; +} + +static u32 rtl930x_l3_hash6(struct in6_addr *ip6, int algorithm, bool move_dip) +{ + u32 rows[16]; + u32 hash; + u32 s0, s1, pH; + + rows[0] = (HASH_PICK(ip6->s6_addr[0], 6, 2) << 0); + rows[1] = (HASH_PICK(ip6->s6_addr[0], 0, 6) << 3) | HASH_PICK(ip6->s6_addr[1], 5, 3); + rows[2] = (HASH_PICK(ip6->s6_addr[1], 0, 5) << 4) | HASH_PICK(ip6->s6_addr[2], 4, 4); + rows[3] = (HASH_PICK(ip6->s6_addr[2], 0, 4) << 5) | HASH_PICK(ip6->s6_addr[3], 3, 5); + rows[4] = (HASH_PICK(ip6->s6_addr[3], 0, 3) << 6) | HASH_PICK(ip6->s6_addr[4], 2, 6); + rows[5] = (HASH_PICK(ip6->s6_addr[4], 0, 2) << 7) | HASH_PICK(ip6->s6_addr[5], 1, 7); + rows[6] = (HASH_PICK(ip6->s6_addr[5], 0, 1) << 8) | HASH_PICK(ip6->s6_addr[6], 0, 8); + rows[7] = (HASH_PICK(ip6->s6_addr[7], 0, 8) << 1) | HASH_PICK(ip6->s6_addr[8], 7, 1); + rows[8] = (HASH_PICK(ip6->s6_addr[8], 0, 7) << 2) | HASH_PICK(ip6->s6_addr[9], 6, 2); + rows[9] = (HASH_PICK(ip6->s6_addr[9], 0, 6) << 3) | HASH_PICK(ip6->s6_addr[10], 5, 3); + rows[10] = (HASH_PICK(ip6->s6_addr[10], 0, 5) << 4) | HASH_PICK(ip6->s6_addr[11], 4, 4); + if (!algorithm) { + rows[11] = (HASH_PICK(ip6->s6_addr[11], 0, 4) << 5) + | (HASH_PICK(ip6->s6_addr[12], 3, 5) << 0); + rows[12] = (HASH_PICK(ip6->s6_addr[12], 0, 3) << 6) + | (HASH_PICK(ip6->s6_addr[13], 2, 6) << 0); + rows[13] = (HASH_PICK(ip6->s6_addr[13], 0, 2) << 7) + | (HASH_PICK(ip6->s6_addr[14], 1, 7) << 0); + if (!move_dip) { + rows[14] = (HASH_PICK(ip6->s6_addr[14], 0, 1) << 8) + | (HASH_PICK(ip6->s6_addr[15], 0, 8) << 0); + } + hash = rows[0] ^ rows[1] ^ rows[2] ^ rows[3] ^ rows[4] ^ rows[5] ^ rows[6] + ^ rows[7] ^ rows[8] ^ rows[9] ^ rows[10] ^ rows[11] ^ rows[12] + ^ rows[13] ^ rows[14]; + } else { + rows[11] = (HASH_PICK(ip6->s6_addr[11], 0, 4) << 5); + rows[12] = (HASH_PICK(ip6->s6_addr[12], 3, 5) << 0); + rows[13] = (HASH_PICK(ip6->s6_addr[12], 0, 3) << 6) + | HASH_PICK(ip6->s6_addr[13], 2, 6); + rows[14] = (HASH_PICK(ip6->s6_addr[13], 0, 2) << 7) + | HASH_PICK(ip6->s6_addr[14], 1, 7); + if (!move_dip) { + rows[15] = (HASH_PICK(ip6->s6_addr[14], 0, 1) << 8) + | (HASH_PICK(ip6->s6_addr[15], 0, 8) << 0); + } + s0 = rows[12] + rows[13] + rows[14]; + s1 = (s0 & 0x1ff) + ((s0 & (0x1ff << 9)) >> 9); + pH = (s1 & 0x1ff) + ((s1 & (0x1ff << 9)) >> 9); + hash = rows[0] ^ rows[1] ^ rows[2] ^ rows[3] ^ rows[4] ^ rows[5] ^ rows[6] + ^ rows[7] ^ rows[8] ^ rows[9] ^ rows[10] ^ rows[11] ^ pH ^ rows[15]; + } + return hash; +} + +/* + * Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table + * We currently only support IPv4 and IPv6 unicast route + */ +static void rtl930x_route_read(int idx, struct rtl83xx_route *rt) +{ + u32 v, ip4_m; + bool host_route, default_route; + struct in6_addr ip6_m; + + // Read L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); + + rtl_table_read(r, idx); + // The table has a size of 11 registers + rt->attr.valid = !!(sw_r32(rtl_table_data(r, 0)) & BIT(31)); + if (!rt->attr.valid) + goto out; + + rt->attr.type = (sw_r32(rtl_table_data(r, 0)) >> 29) & 0x3; + + v = sw_r32(rtl_table_data(r, 10)); + host_route = !!(v & BIT(21)); + default_route = !!(v & BIT(20)); + rt->prefix_len = -1; + pr_info("%s: host route %d, default_route %d\n", __func__, host_route, default_route); + + switch (rt->attr.type) { + case 0: // IPv4 Unicast route + rt->dst_ip = sw_r32(rtl_table_data(r, 4)); + ip4_m = sw_r32(rtl_table_data(r, 9)); + pr_info("%s: Read ip4 mask: %08x\n", __func__, ip4_m); + rt->prefix_len = host_route ? 32 : -1; + rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; + if (rt->prefix_len < 0) + rt->prefix_len = inet_mask_len(ip4_m); + break; + case 2: // IPv6 Unicast route + ipv6_addr_set(&rt->dst_ip6, + sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4))); + ipv6_addr_set(&ip6_m, + sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), + sw_r32(rtl_table_data(r, 8)), sw_r32(rtl_table_data(r, 9))); + rt->prefix_len = host_route ? 128 : 0; + rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; + if (rt->prefix_len < 0) + rt->prefix_len = find_last_bit((unsigned long int *)&ip6_m.s6_addr32, + 128); + break; + case 1: // IPv4 Multicast route + case 3: // IPv6 Multicast route + pr_warn("%s: route type not supported\n", __func__); + goto out; + } + + rt->attr.hit = !!(v & BIT(22)); + rt->attr.action = (v >> 18) & 3; + rt->nh.id = (v >> 7) & 0x7ff; + rt->attr.ttl_dec = !!(v & BIT(6)); + rt->attr.ttl_check = !!(v & BIT(5)); + rt->attr.dst_null = !!(v & BIT(4)); + rt->attr.qos_as = !!(v & BIT(3)); + rt->attr.qos_prio = v & 0x7; + pr_info("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); + pr_info("%s: next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + __func__, rt->nh.id, rt->attr.hit, rt->attr.action, + rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); + pr_info("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); +out: + rtl_table_release(r); +} + +static void rtl930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) +{ + int o, b; + // Define network mask + o = prefix_len >> 3; + b = prefix_len & 0x7; + memset(ip6_m->s6_addr, 0xff, o); + ip6_m->s6_addr[o] |= b ? 0xff00 >> b : 0x00; +} + +/* + * Read a host route entry from the table using its index + * We currently only support IPv4 and IPv6 unicast route + */ +static void rtl930x_host_route_read(int idx, struct rtl83xx_route *rt) +{ + u32 v; + // Read L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 1); + + idx = ((idx / 6) * 8) + (idx % 6); + + pr_debug("In %s, physical index %d\n", __func__, idx); + rtl_table_read(r, idx); + // The table has a size of 5 (for UC, 11 for MC) registers + v = sw_r32(rtl_table_data(r, 0)); + rt->attr.valid = !!(v & BIT(31)); + if (!rt->attr.valid) + goto out; + rt->attr.type = (v >> 29) & 0x3; + switch (rt->attr.type) { + case 0: // IPv4 Unicast route + rt->dst_ip = sw_r32(rtl_table_data(r, 4)); + break; + case 2: // IPv6 Unicast route + ipv6_addr_set(&rt->dst_ip6, + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 0))); + break; + case 1: // IPv4 Multicast route + case 3: // IPv6 Multicast route + pr_warn("%s: route type not supported\n", __func__); + goto out; + } + + rt->attr.hit = !!(v & BIT(20)); + rt->attr.dst_null = !!(v & BIT(19)); + rt->attr.action = (v >> 17) & 3; + rt->nh.id = (v >> 6) & 0x7ff; + rt->attr.ttl_dec = !!(v & BIT(5)); + rt->attr.ttl_check = !!(v & BIT(4)); + rt->attr.qos_as = !!(v & BIT(3)); + rt->attr.qos_prio = v & 0x7; + pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); + pr_debug("%s: next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + __func__, rt->nh.id, rt->attr.hit, rt->attr.action, rt->attr.ttl_dec, rt->attr.ttl_check, + rt->attr.dst_null); + pr_debug("%s: Destination: %pI4\n", __func__, &rt->dst_ip); + +out: + rtl_table_release(r); +} + +/* + * Write a host route entry from the table using its index + * We currently only support IPv4 and IPv6 unicast route + */ +static void rtl930x_host_route_write(int idx, struct rtl83xx_route *rt) +{ + u32 v; + // Access L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 1); + // The table has a size of 5 (for UC, 11 for MC) registers + + idx = ((idx / 6) * 8) + (idx % 6); + + pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); + pr_debug("%s: next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + __func__, rt->nh.id, rt->attr.hit, rt->attr.action, rt->attr.ttl_dec, rt->attr.ttl_check, + rt->attr.dst_null); + pr_debug("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); + + v = BIT(31); // Entry is valid + v |= (rt->attr.type & 0x3) << 29; + v |= rt->attr.hit ? BIT(20) : 0; + v |= rt->attr.dst_null ? BIT(19) : 0; + v |= (rt->attr.action & 0x3) << 17; + v |= (rt->nh.id & 0x7ff) << 6; + v |= rt->attr.ttl_dec ? BIT(5) : 0; + v |= rt->attr.ttl_check ? BIT(4) : 0; + v |= rt->attr.qos_as ? BIT(3) : 0; + v |= rt->attr.qos_prio & 0x7; + + sw_w32(v, rtl_table_data(r, 0)); + switch (rt->attr.type) { + case 0: // IPv4 Unicast route + sw_w32(0, rtl_table_data(r, 1)); + sw_w32(0, rtl_table_data(r, 2)); + sw_w32(0, rtl_table_data(r, 3)); + sw_w32(rt->dst_ip, rtl_table_data(r, 4)); + break; + case 2: // IPv6 Unicast route + sw_w32(rt->dst_ip6.s6_addr32[0], rtl_table_data(r, 1)); + sw_w32(rt->dst_ip6.s6_addr32[1], rtl_table_data(r, 2)); + sw_w32(rt->dst_ip6.s6_addr32[2], rtl_table_data(r, 3)); + sw_w32(rt->dst_ip6.s6_addr32[3], rtl_table_data(r, 4)); + break; + case 1: // IPv4 Multicast route + case 3: // IPv6 Multicast route + pr_warn("%s: route type not supported\n", __func__); + goto out; + } + + rtl_table_write(r, idx); + +out: + rtl_table_release(r); +} + +/* + * Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes + * using hardware offload. + */ +static int rtl930x_route_lookup_hw(struct rtl83xx_route *rt) +{ + u32 ip4_m, v; + struct in6_addr ip6_m; + int i; + + if (rt->attr.type == 1 || rt->attr.type == 3) // Hardware only supports UC routes + return -1; + + sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL); + if (rt->attr.type) { // IPv6 + rtl930x_net6_mask(rt->prefix_len, &ip6_m); + for (i = 0; i < 4; i++) + sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0], + RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2)); + } else { // IPv4 + ip4_m = inet_make_mask(rt->prefix_len); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8); + v = rt->dst_ip & ip4_m; + pr_info("%s: searching for %pI4\n", __func__, &v); + sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12); + } + + // Execute CAM lookup in SoC + sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL); + + // Wait until execute bit clears and result is ready + do { + v = sw_r32(RTL930X_L3_HW_LU_CTRL); + } while (v & BIT(15)); + + pr_info("%s: found: %d, index: %d\n", __func__, !!(v & BIT(14)), v & 0x1ff); + + // Test if search successful (BIT 14 set) + if (v & BIT(14)) + return v & 0x1ff; + + return -1; +} + +static int rtl930x_find_l3_slot(struct rtl83xx_route *rt, bool must_exist) +{ + int t, s, slot_width, algorithm, addr, idx; + u32 hash; + struct rtl83xx_route route_entry; + + // IPv6 entries take up 3 slots + slot_width = (rt->attr.type == 0) || (rt->attr.type == 2) ? 1 : 3; + + for (t = 0; t < 2; t++) { + algorithm = (sw_r32(RTL930X_L3_HOST_TBL_CTRL) >> (2 + t)) & 0x1; + hash = rtl930x_l3_hash4(rt->dst_ip, algorithm, false); + + pr_debug("%s: table %d, algorithm %d, hash %04x\n", __func__, t, algorithm, hash); + + for (s = 0; s < 6; s += slot_width) { + addr = (t << 12) | ((hash & 0x1ff) << 3) | s; + pr_debug("%s physical address %d\n", __func__, addr); + idx = ((addr / 8) * 6) + (addr % 8); + pr_debug("%s logical address %d\n", __func__, idx); + + rtl930x_host_route_read(idx, &route_entry); + pr_debug("%s route valid %d, route dest: %pI4, hit %d\n", __func__, + rt->attr.valid, &rt->dst_ip, rt->attr.hit); + if (!must_exist && rt->attr.valid) + return idx; + if (must_exist && route_entry.dst_ip == rt->dst_ip) + return idx; + } + } + + return -1; +} + +/* + * Write a prefix route into the routing table CAM at position idx + * Currently only IPv4 and IPv6 unicast routes are supported + */ +static void rtl930x_route_write(int idx, struct rtl83xx_route *rt) +{ + u32 v, ip4_m; + struct in6_addr ip6_m; + // Access L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 + // The table has a size of 11 registers (20 for MC) + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); + + pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); + pr_debug("%s: nexthop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + __func__, rt->nh.id, rt->attr.hit, rt->attr.action, + rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); + pr_debug("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); + + v = rt->attr.valid ? BIT(31) : 0; + v |= (rt->attr.type & 0x3) << 29; + sw_w32(v, rtl_table_data(r, 0)); + + v = rt->attr.hit ? BIT(22) : 0; + v |= (rt->attr.action & 0x3) << 18; + v |= (rt->nh.id & 0x7ff) << 7; + v |= rt->attr.ttl_dec ? BIT(6) : 0; + v |= rt->attr.ttl_check ? BIT(5) : 0; + v |= rt->attr.dst_null ? BIT(6) : 0; + v |= rt->attr.qos_as ? BIT(6) : 0; + v |= rt->attr.qos_prio & 0x7; + v |= rt->prefix_len == 0 ? BIT(20) : 0; // set default route bit + + // set bit mask for entry type always to 0x3 + sw_w32(0x3 << 29, rtl_table_data(r, 5)); + + switch (rt->attr.type) { + case 0: // IPv4 Unicast route + sw_w32(0, rtl_table_data(r, 1)); + sw_w32(0, rtl_table_data(r, 2)); + sw_w32(0, rtl_table_data(r, 3)); + sw_w32(rt->dst_ip, rtl_table_data(r, 4)); + + v |= rt->prefix_len == 32 ? BIT(21) : 0; // set host-route bit + ip4_m = inet_make_mask(rt->prefix_len); + sw_w32(0, rtl_table_data(r, 6)); + sw_w32(0, rtl_table_data(r, 7)); + sw_w32(0, rtl_table_data(r, 8)); + sw_w32(ip4_m, rtl_table_data(r, 9)); + break; + case 2: // IPv6 Unicast route + sw_w32(rt->dst_ip6.s6_addr32[0], rtl_table_data(r, 1)); + sw_w32(rt->dst_ip6.s6_addr32[1], rtl_table_data(r, 2)); + sw_w32(rt->dst_ip6.s6_addr32[2], rtl_table_data(r, 3)); + sw_w32(rt->dst_ip6.s6_addr32[3], rtl_table_data(r, 4)); + + v |= rt->prefix_len == 128 ? BIT(21) : 0; // set host-route bit + + rtl930x_net6_mask(rt->prefix_len, &ip6_m); + + sw_w32(ip6_m.s6_addr32[0], rtl_table_data(r, 6)); + sw_w32(ip6_m.s6_addr32[1], rtl_table_data(r, 7)); + sw_w32(ip6_m.s6_addr32[2], rtl_table_data(r, 8)); + sw_w32(ip6_m.s6_addr32[3], rtl_table_data(r, 9)); + break; + case 1: // IPv4 Multicast route + case 3: // IPv6 Multicast route + pr_warn("%s: route type not supported\n", __func__); + rtl_table_release(r); + return; + } + sw_w32(v, rtl_table_data(r, 10)); + + pr_debug("%s: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", __func__, + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), + sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), sw_r32(rtl_table_data(r, 8)), + sw_r32(rtl_table_data(r, 9)), sw_r32(rtl_table_data(r, 10))); + + rtl_table_write(r, idx); + rtl_table_release(r); +} + + +/* + * Get the destination MAC and L3 egress interface ID of a nexthop entry from + * the SoC's L3_NEXTHOP table + */ +static void rtl930x_get_l3_nexthop(int idx, u16 *dmac_id, u16 *interface) +{ + u32 v; + // Read L3_NEXTHOP table (3) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); + + rtl_table_read(r, idx); + // The table has a size of 1 register + v = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); + + *dmac_id = (v >> 7) & 0x7fff; + *interface = v & 0x7f; +} + +static int rtl930x_l3_mtu_del(struct rtl838x_switch_priv *priv, int mtu) +{ + int i; + + for (i = 0; i < MAX_INTF_MTUS; i++) { + if (mtu == priv->intf_mtus[i]) + break; + } + if (i >= MAX_INTF_MTUS || !priv->intf_mtu_count[i]) { + pr_err("%s: No MTU slot found for MTU: %d\n", __func__, mtu); + return -EINVAL; + } + + priv->intf_mtu_count[i]--; +} + +static int rtl930x_l3_mtu_add(struct rtl838x_switch_priv *priv, int mtu) +{ + int i, free_mtu; + int mtu_id; + + // Try to find an existing mtu-value or a free slot + free_mtu = MAX_INTF_MTUS; + for (i = 0; i < MAX_INTF_MTUS && priv->intf_mtus[i] != mtu; i++) { + if ((!priv->intf_mtu_count[i]) && (free_mtu == MAX_INTF_MTUS)) + free_mtu = i; + } + i = (i < MAX_INTF_MTUS) ? i : free_mtu; + if (i < MAX_INTF_MTUS) { + mtu_id = i; + } else { + pr_err("%s: No free MTU slot available!\n", __func__); + return -EINVAL; + } + + priv->intf_mtus[i] = mtu; + pr_info("Writing MTU %d to slot %d\n", priv->intf_mtus[i], i); + // Set MTU-value of the slot TODO: distinguish between IPv4/IPv6 routes / slots + sw_w32_mask(0xffff << ((i % 2) * 16), priv->intf_mtus[i] << ((i % 2) * 16), + RTL930X_L3_IP_MTU_CTRL(i)); + sw_w32_mask(0xffff << ((i % 2) * 16), priv->intf_mtus[i] << ((i % 2) * 16), + RTL930X_L3_IP6_MTU_CTRL(i)); + + priv->intf_mtu_count[i]++; + + return mtu_id; +} + +/* + * Creates an interface for a route by setting up the HW tables in the SoC + */ +static int rtl930x_l3_intf_add(struct rtl838x_switch_priv *priv, struct rtl838x_l3_intf *intf) +{ + int i, intf_id, mtu_id; + // number of MTU-values < 16384 + + // Use the same IPv6 mtu as the ip4 mtu for this route if unset + intf->ip6_mtu = intf->ip6_mtu ? intf->ip6_mtu : intf->ip4_mtu; + + mtu_id = rtl930x_l3_mtu_add(priv, intf->ip4_mtu); + pr_info("%s: added mtu %d with mtu-id %d\n", __func__, intf->ip4_mtu, mtu_id); + if (mtu_id < 0) + return -ENOSPC; + intf->ip4_mtu_id = mtu_id; + intf->ip6_mtu_id = mtu_id; + + for (i = 0; i < MAX_INTERFACES; i++) { + if (!priv->interfaces[i]) + break; + } + if (i >= MAX_INTERFACES) { + pr_err("%s: cannot find free interface entry\n", __func__); + return -EINVAL; + } + intf_id = i; + priv->interfaces[i] = kzalloc(sizeof(struct rtl838x_l3_intf), GFP_KERNEL); + if (!priv->interfaces[i]) { + pr_err("%s: no memory to allocate new interface\n", __func__); + return -ENOMEM; + } +} + +/* + * Set the destination MAC and L3 egress interface ID for a nexthop entry in the SoC's + * L3_NEXTHOP table. The nexthop entry is identified by idx. + * dmac_id is the reference to the L2 entry in the L2 forwarding table, special values are + * 0x7ffe: TRAP2CPU + * 0x7ffd: TRAP2MASTERCPU + * 0x7fff: DMAC_ID_DROP + */ +static void rtl930x_set_l3_nexthop(int idx, u16 dmac_id, u16 interface) +{ + // Access L3_NEXTHOP table (3) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); + + pr_info("%s: Writing to L3_NEXTHOP table, index %d, dmac_id %d, interface %d\n", + __func__, idx, dmac_id, interface); + sw_w32(((dmac_id & 0x7fff) << 7) | (interface & 0x7f), rtl_table_data(r, 0)); + + pr_info("%s: %08x\n", __func__, sw_r32(rtl_table_data(r,0))); + rtl_table_write(r, idx); + rtl_table_release(r); +} static void rtl930x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index) { @@ -1618,6 +2064,219 @@ static void rtl930x_pie_init(struct rtl838x_switch_priv *priv) } +/* + * Sets up an egress interface for L3 actions + * Actions for ip4/6_icmp_redirect, ip4/6_pbr_icmp_redirect are: + * 0: FORWARD, 1: DROP, 2: TRAP2CPU, 3: COPY2CPU, 4: TRAP2MASTERCPU 5: COPY2MASTERCPU + * 6: HARDDROP + * idx is the index in the HW interface table: idx < 0x80 + */ +static void rtl930x_set_l3_egress_intf(int idx, struct rtl838x_l3_intf *intf) +{ + u32 u, v; + // Read L3_EGR_INTF table (4) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 4); + + // The table has 2 registers + u = (intf->vid & 0xfff) << 9; + u |= (intf->smac_idx & 0x3f) << 3; + u |= (intf->ip4_mtu_id & 0x7); + + v = (intf->ip6_mtu_id & 0x7) << 28; + v |= (intf->ttl_scope & 0xff) << 20; + v |= (intf->hl_scope & 0xff) << 12; + v |= (intf->ip4_icmp_redirect & 0x7) << 9; + v |= (intf->ip6_icmp_redirect & 0x7)<< 6; + v |= (intf->ip4_pbr_icmp_redirect & 0x7) << 3; + v |= (intf->ip6_pbr_icmp_redirect & 0x7); + + sw_w32(u, rtl_table_data(r, 0)); + sw_w32(v, rtl_table_data(r, 1)); + + pr_info("%s writing to index %d: %08x %08x\n", __func__, idx, u, v); + rtl_table_write(r, idx & 0x7f); + rtl_table_release(r); +} + +/* + * Reads a MAC entry for L3 termination as entry point for routing + * from the hardware table + * idx is the index into the L3_ROUTER_MAC table + */ +static void rtl930x_get_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m) +{ + u32 v, w; + // Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); + + rtl_table_read(r, idx); + // The table has a size of 7 registers, 64 entries + v = sw_r32(rtl_table_data(r, 0)); + w = sw_r32(rtl_table_data(r, 3)); + m->valid = !!(v & BIT(20)); + if (!m->valid) + goto out; + + m->p_type = !!(v & BIT(19)); + m->p_id = (v >> 13) & 0x3f; // trunk id of port + m->vid = v & 0xfff; + m->vid_mask = w & 0xfff; + m->action = sw_r32(rtl_table_data(r, 6)) & 0x7; + m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) + | (sw_r32(rtl_table_data(r, 4))); + m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) + | (sw_r32(rtl_table_data(r, 2))); + // Bits L3_INTF and BMSK_L3_INTF are 0 + +out: + rtl_table_release(r); +} + +/* + * Writes a MAC entry for L3 termination as entry point for routing + * into the hardware table + * idx is the index into the L3_ROUTER_MAC table + */ +static void rtl930x_set_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m) +{ + u32 v, w; + // Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); + + // The table has a size of 7 registers, 64 entries + v = BIT(20); // mac entry valid, port type is 0: individual + v |= (m->p_id & 0x3f) << 13; + v |= (m->vid & 0xfff); // Set the interface_id to the vlan id + + w = m->vid_mask; + w |= (m->p_id_mask & 0x3f) << 13; + + sw_w32(v, rtl_table_data(r, 0)); + sw_w32(w, rtl_table_data(r, 3)); + + // Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 + sw_w32((u32)(m->mac), rtl_table_data(r, 2)); + sw_w32(m->mac >> 32, rtl_table_data(r, 1)); + + // Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 + sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4)); + sw_w32((u32)m->mac_mask, rtl_table_data(r, 5)); + + sw_w32(m->action & 0x7, rtl_table_data(r, 6)); + + pr_debug("%s writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", __func__, idx, + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), + sw_r32(rtl_table_data(r, 6)) + ); + rtl_table_write(r, idx); + rtl_table_release(r); +} + +/* + * Get the Destination-MAC of an L3 egress interface or the Source MAC for routed packets + * from the SoC's L3_EGR_INTF_MAC table + * Indexes 0-2047 are DMACs, 2048+ are SMACs + */ +static u64 rtl930x_get_l3_egress_mac(u32 idx) +{ + u64 mac; + // Read L3_EGR_INTF_MAC table (2) via register RTL9300_TBL_2 + struct table_reg *r = rtl_table_get(RTL9300_TBL_2, 2); + + rtl_table_read(r, idx); + // The table has a size of 2 registers + mac = sw_r32(rtl_table_data(r, 0)); + mac <<= 32; + mac |= sw_r32(rtl_table_data(r, 1)); + rtl_table_release(r); + + return mac; +} +/* + * Set the Destination-MAC of a route or the Source MAC of an L3 egress interface + * in the SoC's L3_EGR_INTF_MAC table + * Indexes 0-2047 are DMACs, 2048+ are SMACs + */ +static void rtl930x_set_l3_egress_mac(u32 idx, u64 mac) +{ + // Access L3_EGR_INTF_MAC table (2) via register RTL9300_TBL_2 + struct table_reg *r = rtl_table_get(RTL9300_TBL_2, 2); + + // The table has a size of 2 registers + sw_w32(mac >> 32, rtl_table_data(r, 0)); + sw_w32(mac, rtl_table_data(r, 1)); + + pr_debug("%s: setting index %d to %016llx\n", __func__, idx, mac); + rtl_table_write(r, idx); + rtl_table_release(r); +} + +/* + * Configure L3 routing settings of the device: + * - MTUs + * - Egress interface + * - The router's MAC address on which routed packets are expected + * - MAC addresses used as source macs of routed packets + */ +int rtl930x_l3_setup(struct rtl838x_switch_priv *priv) +{ + int i; + + // Setup MTU with id 0 for default interface + for (i = 0; i < MAX_INTF_MTUS; i++) + priv->intf_mtu_count[i] = priv->intf_mtus[i] = 0; + + priv->intf_mtu_count[0] = 0; // Needs to stay forever + priv->intf_mtus[0] = DEFAULT_MTU; + sw_w32_mask(0xffff, DEFAULT_MTU, RTL930X_L3_IP_MTU_CTRL(0)); + sw_w32_mask(0xffff, DEFAULT_MTU, RTL930X_L3_IP6_MTU_CTRL(0)); + priv->intf_mtus[1] = DEFAULT_MTU; + sw_w32_mask(0xffff0000, DEFAULT_MTU << 16, RTL930X_L3_IP_MTU_CTRL(0)); + sw_w32_mask(0xffff0000, DEFAULT_MTU << 16, RTL930X_L3_IP6_MTU_CTRL(0)); + + sw_w32_mask(0xffff, DEFAULT_MTU, RTL930X_L3_IP_MTU_CTRL(1)); + sw_w32_mask(0xffff, DEFAULT_MTU, RTL930X_L3_IP6_MTU_CTRL(1)); + sw_w32_mask(0xffff0000, DEFAULT_MTU << 16, RTL930X_L3_IP_MTU_CTRL(1)); + sw_w32_mask(0xffff0000, DEFAULT_MTU << 16, RTL930X_L3_IP6_MTU_CTRL(1)); + + // Clear all source port MACs + for (i = 0; i < MAX_SMACS; i++) + rtl930x_set_l3_egress_mac(L3_EGRESS_DMACS + i, 0ULL); + + // Configure the default L3 hash algorithm + sw_w32_mask(BIT(2), 0, RTL930X_L3_HOST_TBL_CTRL); // Algorithm selection 0 = 0 + sw_w32_mask(0, BIT(3), RTL930X_L3_HOST_TBL_CTRL); // Algorithm selection 1 = 1 + + pr_info("L3_IPUC_ROUTE_CTRL %08x, IPMC_ROUTE %08x, IP6UC_ROUTE %08x, IP6MC_ROUTE %08x\n", + sw_r32(RTL930X_L3_IPUC_ROUTE_CTRL), sw_r32(RTL930X_L3_IPMC_ROUTE_CTRL), + sw_r32(RTL930X_L3_IP6UC_ROUTE_CTRL), sw_r32(RTL930X_L3_IP6MC_ROUTE_CTRL)); + sw_w32_mask(0, 1, RTL930X_L3_IPUC_ROUTE_CTRL); + sw_w32_mask(0, 1, RTL930X_L3_IP6UC_ROUTE_CTRL); + sw_w32_mask(0, 1, RTL930X_L3_IPMC_ROUTE_CTRL); + sw_w32_mask(0, 1, RTL930X_L3_IP6MC_ROUTE_CTRL); + + sw_w32(0x00002001, RTL930X_L3_IPUC_ROUTE_CTRL); + sw_w32(0x00014581, RTL930X_L3_IP6UC_ROUTE_CTRL); + sw_w32(0x00000501, RTL930X_L3_IPMC_ROUTE_CTRL); + sw_w32(0x00012881, RTL930X_L3_IP6MC_ROUTE_CTRL); + + pr_info("L3_IPUC_ROUTE_CTRL %08x, IPMC_ROUTE %08x, IP6UC_ROUTE %08x, IP6MC_ROUTE %08x\n", + sw_r32(RTL930X_L3_IPUC_ROUTE_CTRL), sw_r32(RTL930X_L3_IPMC_ROUTE_CTRL), + sw_r32(RTL930X_L3_IP6UC_ROUTE_CTRL), sw_r32(RTL930X_L3_IP6MC_ROUTE_CTRL)); + + // Trap non-ip traffic to the CPU-port (e.g. ARP so we stay reachable) + sw_w32_mask(0x3 << 8, 0x1 << 8, RTL930X_L3_IP_ROUTE_CTRL); + pr_info("L3_IP_ROUTE_CTRL %08x\n", sw_r32(RTL930X_L3_IP_ROUTE_CTRL)); + + // PORT_ISO_RESTRICT_ROUTE_CTRL ? + + // Do not use prefix route 0 because of HW limitations + set_bit(0, priv->route_use_bm); + + return 0; +} + static u32 rtl930x_packet_cntr_read(int counter) { u32 v; @@ -1709,7 +2368,7 @@ const struct rtl838x_reg rtl930x_reg = { .read_cam = rtl930x_read_cam, .write_cam = rtl930x_write_cam, .vlan_port_egr_filter = RTL930X_VLAN_PORT_EGR_FLTR, - .vlan_port_igr_filter = RTL930X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_igr_filter = RTL930X_VLAN_PORT_IGR_FLTR, .vlan_port_pb = RTL930X_VLAN_PORT_PB_VLAN, .vlan_port_tag_sts_ctrl = RTL930X_VLAN_PORT_TAG_STS_CTRL, .trk_mbr_ctr = rtl930x_trk_mbr_ctr, @@ -1717,6 +2376,8 @@ const struct rtl838x_reg rtl930x_reg = { .init_eee = rtl930x_init_eee, .port_eee_set = rtl930x_port_eee_set, .eee_port_ability = rtl930x_eee_port_ability, + .l2_hash_seed = rtl930x_l2_hash_seed, + .l2_hash_key = rtl930x_l2_hash_key, .read_mcast_pmask = rtl930x_read_mcast_pmask, .write_mcast_pmask = rtl930x_write_mcast_pmask, .pie_init = rtl930x_pie_init, @@ -1726,4 +2387,17 @@ const struct rtl838x_reg rtl930x_reg = { .l2_learning_setup = rtl930x_l2_learning_setup, .packet_cntr_read = rtl930x_packet_cntr_read, .packet_cntr_clear = rtl930x_packet_cntr_clear, + .route_read = rtl930x_route_read, + .route_write = rtl930x_route_write, + .host_route_write = rtl930x_host_route_write, + .l3_setup = rtl930x_l3_setup, + .set_l3_nexthop = rtl930x_set_l3_nexthop, + .get_l3_nexthop = rtl930x_get_l3_nexthop, + .get_l3_egress_mac = rtl930x_get_l3_egress_mac, + .set_l3_egress_mac = rtl930x_set_l3_egress_mac, + .find_l3_slot = rtl930x_find_l3_slot, + .route_lookup_hw = rtl930x_route_lookup_hw, + .get_l3_router_mac = rtl930x_get_l3_router_mac, + .set_l3_router_mac = rtl930x_set_l3_router_mac, + .set_l3_egress_intf = rtl930x_set_l3_egress_intf, }; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c index f98bf7df29..d347b9543e 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl931x.c @@ -384,8 +384,8 @@ const struct rtl838x_reg rtl931x_reg = { .mac_tx_pause_sts = RTL931X_MAC_TX_PAUSE_STS, .read_l2_entry_using_hash = rtl931x_read_l2_entry_using_hash, .read_cam = rtl931x_read_cam, - .vlan_port_egr_filter = RTL931X_VLAN_PORT_EGR_FLTR(0), - .vlan_port_igr_filter = RTL931X_VLAN_PORT_IGR_FLTR(0), + .vlan_port_egr_filter = RTL931X_VLAN_PORT_EGR_FLTR, + .vlan_port_igr_filter = RTL931X_VLAN_PORT_IGR_FLTR, // .vlan_port_pb = does not exist .vlan_port_tag_sts_ctrl = RTL931X_VLAN_PORT_TAG_CTRL, .trk_mbr_ctr = rtl931x_trk_mbr_ctr, From 1cfd45ae0bad3975cd59ff18ce04265b1bccbcd6 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Fri, 10 Sep 2021 15:08:27 +0200 Subject: [PATCH 26/59] realtek: Add debugfs support for RTL9300 Adds support for debugfs on RTL9300, in particular the drop counters. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/common.c | 2 + .../drivers/net/dsa/rtl83xx/debugfs.c | 129 +++++++++++++++++- 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index 2745ead061..9691b8b5c7 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -1570,6 +1570,8 @@ static int __init rtl83xx_sw_probe(struct platform_device *pdev) sw_w32(7, priv->r->spcl_trap_eapol_ctrl); rtl838x_dbgfs_init(priv); + } else { + rtl930x_dbgfs_init(priv); } return 0; diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c index 4f81408453..0a1972aaf6 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/debugfs.c @@ -40,7 +40,11 @@ #define RTL839X_MIR_RSPAN_TX_CTRL (0x69b0) #define RTL839X_MIR_RSPAN_TX_TAG_RM_CTRL (0x2550) #define RTL839X_MIR_RSPAN_TX_TAG_EN_CTRL (0x2554) -#define RTL839X_MIR_SAMPLE_RATE_CTRL (0x2558) +#define RTL839X_MIR_SAMPLE_RATE_CTRL (0x2558) + +#define RTL838X_STAT_PRVTE_DROP_COUNTERS (0x6A00) +#define RTL839X_STAT_PRVTE_DROP_COUNTERS (0x3E00) +#define RTL930X_STAT_PRVTE_DROP_COUNTERS (0xB5B8) int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port); void rtl83xx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); @@ -50,6 +54,58 @@ u32 rtl839x_get_egress_rate(struct rtl838x_switch_priv *priv, int port); int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate); int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate); + +const char *rtl838x_drop_cntr[] = { + "ALE_TX_GOOD_PKTS", "MAC_RX_DROP", "ACL_FWD_DROP", "HW_ATTACK_PREVENTION_DROP", + "RMA_DROP", "VLAN_IGR_FLTR_DROP", "INNER_OUTER_CFI_EQUAL_1_DROP", "PORT_MOVE_DROP", + "NEW_SA_DROP", "MAC_LIMIT_SYS_DROP", "MAC_LIMIT_VLAN_DROP", "MAC_LIMIT_PORT_DROP", + "SWITCH_MAC_DROP", "ROUTING_EXCEPTION_DROP", "DA_LKMISS_DROP", "RSPAN_DROP", + "ACL_LKMISS_DROP", "ACL_DROP", "INBW_DROP", "IGR_METER_DROP", + "ACCEPT_FRAME_TYPE_DROP", "STP_IGR_DROP", "INVALID_SA_DROP", "SA_BLOCKING_DROP", + "DA_BLOCKING_DROP", "L2_INVALID_DPM_DROP", "MCST_INVALID_DPM_DROP", "RX_FLOW_CONTROL_DROP", + "STORM_SPPRS_DROP", "LALS_DROP", "VLAN_EGR_FILTER_DROP", "STP_EGR_DROP", + "SRC_PORT_FILTER_DROP", "PORT_ISOLATION_DROP", "ACL_FLTR_DROP", "MIRROR_FLTR_DROP", + "TX_MAX_DROP", "LINK_DOWN_DROP", "FLOW_CONTROL_DROP", "BRIDGE .1d discards" +}; + +const char *rtl839x_drop_cntr[] = { + "ALE_TX_GOOD_PKTS", "ERROR_PKTS", "EGR_ACL_DROP", "EGR_METER_DROP", + "OAM", "CFM" "VLAN_IGR_FLTR", "VLAN_ERR", + "INNER_OUTER_CFI_EQUAL_1", "VLAN_TAG_FORMAT", "SRC_PORT_SPENDING_TREE", "INBW", + "RMA", "HW_ATTACK_PREVENTION", "PROTO_STORM", "MCAST_SA", + "IGR_ACL_DROP", "IGR_METER_DROP", "DFLT_ACTION_FOR_MISS_ACL_AND_C2SC", "NEW_SA", + "PORT_MOVE", "SA_BLOCKING", "ROUTING_EXCEPTION", "SRC_PORT_SPENDING_TREE_NON_FWDING", + "MAC_LIMIT", "UNKNOW_STORM", "MISS_DROP", "CPU_MAC_DROP", + "DA_BLOCKING", "SRC_PORT_FILTER_BEFORE_EGR_ACL", "VLAN_EGR_FILTER", "SPANNING_TRE", + "PORT_ISOLATION", "OAM_EGRESS_DROP", "MIRROR_ISOLATION", "MAX_LEN_BEFORE_EGR_ACL", + "SRC_PORT_FILTER_BEFORE_MIRROR", "MAX_LEN_BEFORE_MIRROR", "SPECIAL_CONGEST_BEFORE_MIRROR", + "LINK_STATUS_BEFORE_MIRROR", + "WRED_BEFORE_MIRROR", "MAX_LEN_AFTER_MIRROR", "SPECIAL_CONGEST_AFTER_MIRROR", + "LINK_STATUS_AFTER_MIRROR", + "WRED_AFTER_MIRROR" +}; + +const char *rtl930x_drop_cntr[] = { + "OAM_PARSER", "UC_RPF", "DEI_CFI", "MAC_IP_SUBNET_BASED_VLAN", "VLAN_IGR_FILTER", + "L2_UC_MC", "IPV_IP6_MC_BRIDGE", "PTP", "USER_DEF_0_3", "RESERVED", + "RESERVED1", "RESERVED2", "BPDU_RMA", "LACP", "LLDP", + "EAPOL", "XX_RMA", "L3_IPUC_NON_IP", "IP4_IP6_HEADER_ERROR", "L3_BAD_IP", + "L3_DIP_DMAC_MISMATCH", "IP4_IP_OPTION", "IP_UC_MC_ROUTING_LOOK_UP_MISS", "L3_DST_NULL_INTF", + "L3_PBR_NULL_INTF", + "HOST_NULL_INTF", "ROUTE_NULL_INTF", "BRIDGING_ACTION", "ROUTING_ACTION", "IPMC_RPF", + "L2_NEXTHOP_AGE_OUT", "L3_UC_TTL_FAIL", "L3_MC_TTL_FAIL", "L3_UC_MTU_FAIL", "L3_MC_MTU_FAIL", + "L3_UC_ICMP_REDIR", "IP6_MLD_OTHER_ACT", "ND", "IP_MC_RESERVED", "IP6_HBH", + "INVALID_SA", "L2_HASH_FULL", "NEW_SA", "PORT_MOVE_FORBID", "STATIC_PORT_MOVING", + "DYNMIC_PORT_MOVING", "L3_CRC", "MAC_LIMIT", "ATTACK_PREVENT", "ACL_FWD_ACTION", + "OAMPDU", "OAM_MUX", "TRUNK_FILTER", "ACL_DROP", "IGR_BW", + "ACL_METER", "VLAN_ACCEPT_FRAME_TYPE", "MSTP_SRC_DROP_DISABLED_BLOCKING", "SA_BLOCK", "DA_BLOCK", + "STORM_CONTROL", "VLAN_EGR_FILTER", "MSTP_DESTINATION_DROP", "SRC_PORT_FILTER", "PORT_ISOLATION", + "TX_MAX_FRAME_SIZE", "EGR_LINK_STATUS", "MAC_TX_DISABLE", "MAC_PAUSE_FRAME", "MAC_RX_DROP", + "MIRROR_ISOLATE", "RX_FC", "EGR_QUEUE", "HSM_RUNOUT", "ROUTING_DISABLE", "INVALID_L2_NEXTHOP_ENTRY", + "L3_MC_SRC_FLT", "CPUTAG_FLT", "FWD_PMSK_NULL", "IPUC_ROUTING_LOOKUP_MISS", "MY_DEV_DROP", + "STACK_NONUC_BLOCKING_PMSK", "STACK_PORT_NOT_FOUND", "ACL_LOOPBACK_DROP", "IP6_ROUTING_EXT_HEADER" +}; + static ssize_t rtl838x_common_read(char __user *buffer, size_t count, loff_t *ppos, unsigned int value) { @@ -134,6 +190,61 @@ static const struct file_operations stp_state_fops = { .write = stp_state_write, }; +static ssize_t drop_counter_read(struct file *filp, char __user *buffer, size_t count, + loff_t *ppos) +{ + struct rtl838x_switch_priv *priv = filp->private_data; + int i; + const char **d; + u32 v; + char *buf; + int n = 0, len, offset; + int num; + + switch (priv->family_id) { + case RTL8380_FAMILY_ID: + d = rtl838x_drop_cntr; + offset = RTL838X_STAT_PRVTE_DROP_COUNTERS; + num = 40; + break; + case RTL8390_FAMILY_ID: + d = rtl839x_drop_cntr; + offset = RTL839X_STAT_PRVTE_DROP_COUNTERS; + num = 45; + break; + case RTL9300_FAMILY_ID: + d = rtl930x_drop_cntr; + offset = RTL930X_STAT_PRVTE_DROP_COUNTERS; + num = 85; + break; + } + + buf = kmalloc(30 * num, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < num; i++) { + v = sw_r32(offset + (i << 2)) & 0xffff; + n += sprintf(buf + n, "%s: %d\n", d[i], v); + } + + if (count < strlen(buf)) { + kfree(buf); + return -ENOSPC; + } + + len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); + kfree(buf); + + return len; +} + +static const struct file_operations drop_counter_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = drop_counter_read, +}; + static ssize_t age_out_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { @@ -470,7 +581,23 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv) if (ret) goto err; + debugfs_create_file("drop_counters", 0400, rtl838x_dir, priv, &drop_counter_fops); + return; err: rtl838x_dbgfs_cleanup(priv); } + +void rtl930x_dbgfs_init(struct rtl838x_switch_priv *priv) +{ + struct dentry *dbg_dir; + + pr_info("%s called\n", __func__); + dbg_dir = debugfs_lookup(RTL838X_DRIVER_NAME, NULL); + if (!dbg_dir) + dbg_dir = debugfs_create_dir(RTL838X_DRIVER_NAME, NULL); + + priv->dbgfs_dir = dbg_dir; + + debugfs_create_file("drop_counters", 0400, dbg_dir, priv, &drop_counter_fops); +} From 88936e7e8278ef82c0937e47be6b4556b3ef708a Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Fri, 10 Sep 2021 15:09:18 +0200 Subject: [PATCH 27/59] realtek: cleanup PHY driver Removes unnecessary output from the RTL PHY drivers. Signed-off-by: Birger Koblitz --- .../files-5.10/drivers/net/phy/rtl83xx-phy.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c index 3e187228a9..636cda287b 100644 --- a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c +++ b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c @@ -211,7 +211,7 @@ void rtl9300_sds_rst(int sds_num, u32 mode) 0x02A4, 0x02A4, 0x0198, 0x0198 }; u8 lsb[] = { 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 0, 6}; - pr_info("SerDes: %s %d\n", __func__, mode); + pr_info("%s %d\n", __func__, mode); if (sds_num < 0 || sds_num > 11) { pr_err("Wrong SerDes number: %d\n", sds_num); return; @@ -223,7 +223,7 @@ void rtl9300_sds_rst(int sds_num, u32 mode) sw_w32_mask(0x1f << lsb[sds_num], mode << lsb[sds_num], regs[sds_num]); mdelay(10); - pr_info("SDS: 194:%08x 198:%08x 2a0:%08x 2a4:%08x\n", + pr_debug("%s: 194:%08x 198:%08x 2a0:%08x 2a4:%08x\n", __func__, sw_r32(0x194), sw_r32(0x198), sw_r32(0x2a0), sw_r32(0x2a4)); } @@ -276,7 +276,7 @@ int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg) int i; u32 cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 1; - pr_info("%s: phy_addr %d, phy_reg: %d\n", __func__, phy_addr, phy_reg); + pr_debug("%s: phy_addr %d, phy_reg: %d\n", __func__, phy_addr, phy_reg); sw_w32(cmd, RTL930X_SDS_INDACS_CMD); for (i = 0; i < 100; i++) { @@ -288,7 +288,7 @@ int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg) if (i >= 100) return -EIO; - pr_info("%s: returning %04x\n", __func__, sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff); + pr_debug("%s: returning %04x\n", __func__, sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff); return sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff; } @@ -508,7 +508,7 @@ static int rtl8226_config_aneg(struct phy_device *phydev) u32 v; int port = phydev->mdio.addr; - pr_info("In %s\n", __func__); + pr_debug("In %s\n", __func__); if (phydev->autoneg == AUTONEG_ENABLE) { ret = rtl8226_advertise_aneg(phydev); if (ret) @@ -532,11 +532,9 @@ static int rtl8226_config_aneg(struct phy_device *phydev) ret = write_mmd_phy(port, MMD_VEND2, 0xA400, v); } - pr_info("%s: Ret is already: %d\n", __func__, ret); // TODO: ret = __genphy_config_aneg(phydev, ret); out: - pr_info("%s: And ret is now: %d\n", __func__, ret); return ret; } @@ -1727,7 +1725,7 @@ static int rtl8218d_phy_probe(struct phy_device *phydev) struct rtl838x_phy_priv *priv; int addr = phydev->mdio.addr; - pr_info("%s: id: %d\n", __func__, addr); + pr_debug("%s: id: %d\n", __func__, addr); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; From 76f60470a192f8ce585ac3289d3037b54d98ba11 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Mon, 13 Sep 2021 20:44:43 +0200 Subject: [PATCH 28/59] realtek: Fix bug when accessing external PHYs on SoCs older than Revision C RTL8393 SoCs older than Revision C hang on accesses to PHYs with PHY address larger or equal to the CPU-port (52). This will make scanning the MDIO bus hang forever. Since the RTL8390 platform does not support more than 52 PHYs, return -EIO for phy addresses >= 52. Note that the RTL8390 family of SoCs has a fixed mapping between port number and PHY-address. Signed-off-by: Birger Koblitz --- .../drivers/net/dsa/rtl83xx/rtl839x.c | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c index cca8824ce5..3c85e736c9 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c @@ -608,6 +608,10 @@ int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val) if (port > 63 || page > 4095 || reg > 31) return -ENOTSUPP; + // Take bug on RTL839x Rev <= C into account + if (port >= RTL839X_CPU_PORT) + return -EIO; + mutex_lock(&smi_lock); sw_w32_mask(0xffff0000, port << 16, RTL839X_PHYREG_DATA_CTRL); @@ -637,6 +641,10 @@ int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val) if (port > 63 || page > 4095 || reg > 31) return -ENOTSUPP; + // Take bug on RTL839x Rev <= C into account + if (port >= RTL839X_CPU_PORT) + return -EIO; + mutex_lock(&smi_lock); // Set PHY to access @@ -670,6 +678,10 @@ int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val) int err = 0; u32 v; + // Take bug on RTL839x Rev <= C into account + if (port >= RTL839X_CPU_PORT) + return -EIO; + mutex_lock(&smi_lock); // Set PHY to access @@ -701,6 +713,10 @@ int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val) int err = 0; u32 v; + // Take bug on RTL839x Rev <= C into account + if (port >= RTL839X_CPU_PORT) + return -EIO; + mutex_lock(&smi_lock); // Set PHY to access @@ -726,12 +742,15 @@ int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val) void rtl8390_get_version(struct rtl838x_switch_priv *priv) { - u32 info; + u32 info, model; sw_w32_mask(0xf << 28, 0xa << 28, RTL839X_CHIP_INFO); info = sw_r32(RTL839X_CHIP_INFO); - pr_debug("Chip-Info: %x\n", info); - priv->version = RTL8390_VERSION_A; + + model = sw_r32(RTL839X_MODEL_NAME_INFO); + priv->version = RTL8390_VERSION_A + ((model & 0x3f) >> 1); + + pr_info("RTL839X Chip-Info: %x, version %c\n", info, priv->version); } void rtl839x_vlan_profile_dump(int profile) From 4c83dae801a83fdfc07fce8aa68978839a76ae02 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Mon, 27 Sep 2021 19:35:36 +0200 Subject: [PATCH 29/59] realtek: enable Aquantia PHY support Enables Aquantia PHY support in the kernel Signed-off-by: Birger Koblitz --- target/linux/realtek/config-5.10 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 index 1b050fc081..727196e112 100644 --- a/target/linux/realtek/config-5.10 +++ b/target/linux/realtek/config-5.10 @@ -1,3 +1,4 @@ +CONFIG_AQUANTIA_PHY=y CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 From cda0460ad333f15e15ec9bd2516b2ae45f8a4644 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Mon, 27 Sep 2021 20:57:29 +0200 Subject: [PATCH 30/59] realtek: add legacy realtek GPIO driver for rtl9300 support The otto GPIO driver does not work with rtl9300 SoCs. Add the legacy driver again and use that by default in the 9300 .dtsi Signed-off-by: Birger Koblitz --- target/linux/realtek/config-5.10 | 1 + .../include/asm/mach-rtl838x/mach-rtl83xx.h | 7 + .../files-5.10/drivers/gpio/gpio-rtl838x.c | 474 ++++++++++++++++++ .../306-gpio-add-legacy-rtl838x-driver.patch | 25 + 4 files changed, 507 insertions(+) create mode 100644 target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c create mode 100644 target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch diff --git a/target/linux/realtek/config-5.10 b/target/linux/realtek/config-5.10 index 727196e112..2c5ab1706a 100644 --- a/target/linux/realtek/config-5.10 +++ b/target/linux/realtek/config-5.10 @@ -72,6 +72,7 @@ CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_GENERIC=y CONFIG_GPIO_REALTEK_OTTO=y CONFIG_GPIO_RTL8231=y +CONFIG_GPIO_RTL838X=y CONFIG_GRO_CELLS=y CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y diff --git a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h index 0abfc6f4d2..ecec0fec2d 100644 --- a/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h +++ b/target/linux/realtek/files-5.10/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h @@ -214,6 +214,13 @@ #define RTL838X_GPIO_PAB_IMR (GPIO_CTRL_REG_BASE + 0x14) #define RTL838X_GPIO_PC_IMR (GPIO_CTRL_REG_BASE + 0x18) +#define RTL930X_GPIO_CTRL_REG_BASE ((volatile void *) 0xb8003300) +#define RTL930X_GPIO_PABCD_DIR (RTL930X_GPIO_CTRL_REG_BASE + 0x8) +#define RTL930X_GPIO_PABCD_DAT (RTL930X_GPIO_CTRL_REG_BASE + 0xc) +#define RTL930X_GPIO_PABCD_ISR (RTL930X_GPIO_CTRL_REG_BASE + 0x10) +#define RTL930X_GPIO_PAB_IMR (RTL930X_GPIO_CTRL_REG_BASE + 0x14) +#define RTL930X_GPIO_PCD_IMR (RTL930X_GPIO_CTRL_REG_BASE + 0x18) + #define RTL838X_MODEL_NAME_INFO (0x00D4) #define RTL839X_MODEL_NAME_INFO (0x0FF0) #define RTL93XX_MODEL_NAME_INFO (0x0004) diff --git a/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c new file mode 100644 index 0000000000..2009ebcce9 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/gpio/gpio-rtl838x.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +/* RTL8231 registers for LED control */ +#define RTL8231_LED_FUNC0 0x0000 +#define RTL8231_GPIO_PIN_SEL(gpio) ((0x0002) + ((gpio) >> 4)) +#define RTL8231_GPIO_DIR(gpio) ((0x0005) + ((gpio) >> 4)) +#define RTL8231_GPIO_DATA(gpio) ((0x001C) + ((gpio) >> 4)) + +struct rtl838x_gpios { + struct gpio_chip gc; + u32 id; + struct device *dev; + int irq; + int num_leds; + int min_led; + int leds_per_port; + u32 led_mode; + int led_glb_ctrl; + int led_sw_ctrl; + int (*led_sw_p_ctrl)(int port); + int (*led_sw_p_en_ctrl)(int port); + int (*ext_gpio_dir)(int i); + int (*ext_gpio_data)(int i); +}; + +inline int rtl838x_ext_gpio_dir(int i) +{ + return RTL838X_EXT_GPIO_DIR + ((i >>5) << 2); +} + +inline int rtl839x_ext_gpio_dir(int i) +{ + return RTL839X_EXT_GPIO_DIR + ((i >>5) << 2); +} + +inline int rtl838x_ext_gpio_data(int i) +{ + return RTL838X_EXT_GPIO_DATA + ((i >>5) << 2); +} + +inline int rtl839x_ext_gpio_data(int i) +{ + return RTL839X_EXT_GPIO_DATA + ((i >>5) << 2); +} + +inline int rtl838x_led_sw_p_ctrl(int p) +{ + return RTL838X_LED_SW_P_CTRL + (p << 2); +} + +inline int rtl839x_led_sw_p_ctrl(int p) +{ + return RTL839X_LED_SW_P_CTRL + (p << 2); +} + +inline int rtl838x_led_sw_p_en_ctrl(int p) +{ + return RTL838X_LED_SW_P_EN_CTRL + ((p / 10) << 2); +} + +inline int rtl839x_led_sw_p_en_ctrl(int p) +{ + return RTL839X_LED_SW_P_EN_CTRL + ((p / 10) << 2); +} + +extern struct mutex smi_lock; +extern struct rtl83xx_soc_info soc_info; + + +void rtl838x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + int bit; + struct rtl838x_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("rtl838x_set: %d, value: %d\n", offset, value); + /* Internal GPIO of the RTL8380 */ + if (offset < 32) { + if (value) + rtl83xx_w32_mask(0, BIT(offset), RTL838X_GPIO_PABC_DATA); + else + rtl83xx_w32_mask(BIT(offset), 0, RTL838X_GPIO_PABC_DATA); + } + + /* LED driver for PWR and SYS */ + if (offset >= 32 && offset < 64) { + bit = offset - 32; + if (value) + sw_w32_mask(0, BIT(bit), gpios->led_glb_ctrl); + else + sw_w32_mask(BIT(bit), 0, gpios->led_glb_ctrl); + return; + } + + bit = (offset - 64) % 32; + /* First Port-LED */ + if (offset >= 64 && offset < 96 + && offset >= (64 + gpios->min_led) + && offset < (64 + gpios->min_led + gpios->num_leds)) { + if (value) + sw_w32_mask(7, 5, gpios->led_sw_p_ctrl(bit)); + else + sw_w32_mask(7, 0, gpios->led_sw_p_ctrl(bit)); + } + if (offset >= 96 && offset < 128 + && offset >= (96 + gpios->min_led) + && offset < (96 + gpios->min_led + gpios->num_leds)) { + if (value) + sw_w32_mask(7 << 3, 5 << 3, gpios->led_sw_p_ctrl(bit)); + else + sw_w32_mask(7 << 3, 0, gpios->led_sw_p_ctrl(bit)); + } + if (offset >= 128 && offset < 160 + && offset >= (128 + gpios->min_led) + && offset < (128 + gpios->min_led + gpios->num_leds)) { + if (value) + sw_w32_mask(7 << 6, 5 << 6, gpios->led_sw_p_ctrl(bit)); + else + sw_w32_mask(7 << 6, 0, gpios->led_sw_p_ctrl(bit)); + } + __asm__ volatile ("sync"); +} + +void rtl930x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + pr_debug("rtl838x_set: %d, value: %d\n", offset, value); + /* Internal GPIO of the RTL9300 */ + if (value) + rtl83xx_w32_mask(0, BIT(offset), RTL930X_GPIO_PABCD_DAT); + else + rtl83xx_w32_mask(BIT(offset), 0, RTL930X_GPIO_PABCD_DAT); +} + +static int rtl838x_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + pr_debug("%s: %d\n", __func__, offset); + + if (offset < 32) { + rtl83xx_w32_mask(BIT(offset), 0, RTL838X_GPIO_PABC_DIR); + return 0; + } + + /* Internal LED driver does not support input */ + return -ENOTSUPP; +} + +static int rtl930x_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + pr_debug("%s: %d\n", __func__, offset); + + rtl83xx_w32_mask(BIT(offset), 0, RTL930X_GPIO_PABCD_DIR); + return 0; +} + +static int rtl838x_direction_output(struct gpio_chip *gc, unsigned int offset, int value) +{ + pr_debug("%s: %d\n", __func__, offset); + if (offset < 32) + rtl83xx_w32_mask(0, BIT(offset), RTL838X_GPIO_PABC_DIR); + rtl930x_gpio_set(gc, offset, value); + + /* LED for PWR and SYS driver is direction output by default */ + return 0; +} + +static int rtl930x_direction_output(struct gpio_chip *gc, unsigned int offset, int value) +{ + pr_debug("%s: %d\n", __func__, offset); + rtl83xx_w32_mask(0, BIT(offset), RTL930X_GPIO_PABCD_DIR); + rtl930x_gpio_set(gc, offset, value); + + /* LED for PWR and SYS driver is direction output by default */ + return 0; +} + +static int rtl838x_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + u32 v = 0; + + pr_debug("%s: %d\n", __func__, offset); + if (offset < 32) { + v = rtl83xx_r32(RTL838X_GPIO_PABC_DIR); + if (v & BIT(offset)) + return 0; + return 1; + } + + /* LED driver for PWR and SYS is direction output by default */ + if (offset >= 32 && offset < 64) + return 0; + + return 0; +} + +static int rtl930x_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + u32 v = 0; + + v = rtl83xx_r32(RTL930X_GPIO_PABCD_DIR); + if (v & BIT(offset)) + return 0; + return 1; +} + +static int rtl838x_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + u32 v; + struct rtl838x_gpios *gpios = gpiochip_get_data(gc); + + pr_debug("%s: %d\n", __func__, offset); + + /* Internal GPIO of the RTL8380 */ + if (offset < 32) { + v = rtl83xx_r32(RTL838X_GPIO_PABC_DATA); + if (v & BIT(offset)) + return 1; + return 0; + } + + /* LED driver for PWR and SYS */ + if (offset >= 32 && offset < 64) { + v = sw_r32(gpios->led_glb_ctrl); + if (v & BIT(offset-32)) + return 1; + return 0; + } + + return 0; +} + +static int rtl930x_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + u32 v = rtl83xx_r32(RTL930X_GPIO_PABCD_DAT); + if (v & BIT(offset)) + return 1; + return 0; +} + +void rtl8380_led_test(struct rtl838x_gpios *gpios, u32 mask) +{ + int i; + u32 led_gbl = sw_r32(gpios->led_glb_ctrl); + u32 mode_sel, led_p_en; + + if (soc_info.family == RTL8380_FAMILY_ID) { + mode_sel = sw_r32(RTL838X_LED_MODE_SEL); + led_p_en = sw_r32(RTL838X_LED_P_EN_CTRL); + } + + /* 2 Leds for ports 0-23 and 24-27, 3 would be 0x7 */ + sw_w32_mask(0x3f, 0x3 | (0x3 << 3), gpios->led_glb_ctrl); + + if(soc_info.family == RTL8380_FAMILY_ID) { + /* Enable all leds */ + sw_w32(0xFFFFFFF, RTL838X_LED_P_EN_CTRL); + } + /* Enable software control of all leds */ + sw_w32(0xFFFFFFF, gpios->led_sw_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(0)); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(10)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); + + for (i = 0; i < 28; i++) { + if (mask & BIT(i)) + sw_w32(5 | (5 << 3) | (5 << 6), gpios->led_sw_p_ctrl(i)); + } + msleep(3000); + + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(led_p_en, RTL838X_LED_P_EN_CTRL); + /* Disable software control of all leds */ + sw_w32(0x0000000, gpios->led_sw_ctrl); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(0)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(10)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); + + sw_w32(led_gbl, gpios->led_glb_ctrl); + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(mode_sel, RTL838X_LED_MODE_SEL); +} + +void take_port_leds(struct rtl838x_gpios *gpios) +{ + int leds_per_port = gpios->leds_per_port; + int mode = gpios->led_mode; + + pr_info("%s, %d, %x\n", __func__, leds_per_port, mode); + pr_debug("Bootloader settings: %x %x %x\n", + sw_r32(gpios->led_sw_p_en_ctrl(0)), + sw_r32(gpios->led_sw_p_en_ctrl(10)), + sw_r32(gpios->led_sw_p_en_ctrl(20)) + ); + + if (soc_info.family == RTL8380_FAMILY_ID) { + pr_debug("led glb: %x, sel %x\n", + sw_r32(gpios->led_glb_ctrl), sw_r32(RTL838X_LED_MODE_SEL)); + pr_debug("RTL838X_LED_P_EN_CTRL: %x", sw_r32(RTL838X_LED_P_EN_CTRL)); + pr_debug("RTL838X_LED_MODE_CTRL: %x", sw_r32(RTL838X_LED_MODE_CTRL)); + sw_w32_mask(3, 0, RTL838X_LED_MODE_SEL); + sw_w32(mode, RTL838X_LED_MODE_CTRL); + } + + /* Enable software control of all leds */ + sw_w32(0xFFFFFFF, gpios->led_sw_ctrl); + if (soc_info.family == RTL8380_FAMILY_ID) + sw_w32(0xFFFFFFF, RTL838X_LED_P_EN_CTRL); + + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(0)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(10)); + sw_w32(0x0000000, gpios->led_sw_p_en_ctrl(20)); + + sw_w32_mask(0x3f, 0, gpios->led_glb_ctrl); + switch (leds_per_port) { + case 3: + sw_w32_mask(0, 0x7 | (0x7 << 3), gpios->led_glb_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(20)); + /* FALLTHRU */ + case 2: + sw_w32_mask(0, 0x3 | (0x3 << 3), gpios->led_glb_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(10)); + /* FALLTHRU */ + case 1: + sw_w32_mask(0, 0x1 | (0x1 << 3), gpios->led_glb_ctrl); + sw_w32(0xFFFFFFF, gpios->led_sw_p_en_ctrl(0)); + break; + default: + pr_err("No LEDS configured for software control\n"); + } +} + +static const struct of_device_id rtl838x_gpio_of_match[] = { + { .compatible = "realtek,rtl838x-gpio" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, rtl838x_gpio_of_match); + +static int rtl838x_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct rtl838x_gpios *gpios; + int err; + + pr_info("Probing RTL838X GPIOs for %08x\n", soc_info.id); + + if (!np) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); + if (!gpios) + return -ENOMEM; + + gpios->id = soc_info.id; + + switch (gpios->id) { + case 0x8332: + pr_debug("Found RTL8332M GPIO\n"); + break; + case 0x8380: + pr_debug("Found RTL8380M GPIO\n"); + break; + case 0x8381: + pr_debug("Found RTL8381M GPIO\n"); + break; + case 0x8382: + pr_debug("Found RTL8382M GPIO\n"); + break; + case 0x8391: + pr_debug("Found RTL8391 GPIO\n"); + break; + case 0x8393: + pr_debug("Found RTL8393 GPIO\n"); + break; + case 0x9302: + pr_info("Found RTL9302 GPIO\n"); + break; + default: + pr_err("Unknown GPIO chip id (%04x)\n", gpios->id); + return -ENODEV; + } + + if (soc_info.family == RTL8380_FAMILY_ID) { + gpios->led_glb_ctrl = RTL838X_LED_GLB_CTRL; + gpios->led_sw_ctrl = RTL838X_LED_SW_CTRL; + gpios->led_sw_p_ctrl = rtl838x_led_sw_p_ctrl; + gpios->led_sw_p_en_ctrl = rtl838x_led_sw_p_en_ctrl; + gpios->ext_gpio_dir = rtl838x_ext_gpio_dir; + gpios->ext_gpio_data = rtl838x_ext_gpio_data; + gpios->irq = 31; + } + + if (soc_info.family == RTL8390_FAMILY_ID) { + gpios->led_glb_ctrl = RTL839X_LED_GLB_CTRL; + gpios->led_sw_ctrl = RTL839X_LED_SW_CTRL; + gpios->led_sw_p_ctrl = rtl839x_led_sw_p_ctrl; + gpios->led_sw_p_en_ctrl = rtl839x_led_sw_p_en_ctrl; + gpios->ext_gpio_dir = rtl839x_ext_gpio_dir; + gpios->ext_gpio_data = rtl839x_ext_gpio_data; + gpios->irq = 31; + } + + if (soc_info.family == RTL9300_FAMILY_ID) { + gpios->irq = 13; + } + + gpios->gc.label = "rtl838x"; + gpios->gc.parent = dev; + gpios->gc.owner = THIS_MODULE; + gpios->gc.can_sleep = true; + gpios->dev = dev; + gpios->gc.base = 0; + + if (soc_info.family != RTL9300_FAMILY_ID) { + /* 0-31: internal + * 32-63, LED control register + * 64-95: PORT-LED 0 + * 96-127: PORT-LED 1 + * 128-159: PORT-LED 2 + */ + gpios->gc.ngpio = 160; + + gpios->gc.direction_input = rtl838x_direction_input; + gpios->gc.direction_output = rtl838x_direction_output; + gpios->gc.set = rtl838x_gpio_set; + gpios->gc.get = rtl838x_gpio_get; + gpios->gc.get_direction = rtl838x_get_direction; + } else { + gpios->gc.ngpio = 32; + + gpios->gc.direction_input = rtl930x_direction_input; + gpios->gc.direction_output = rtl930x_direction_output; + gpios->gc.set = rtl930x_gpio_set; + gpios->gc.get = rtl930x_gpio_get; + gpios->gc.get_direction = rtl930x_get_direction; + } + + if (of_property_read_bool(np, "take-port-leds")) { + pr_info("A1\n"); + if (of_property_read_u32(np, "leds-per-port", &gpios->leds_per_port)) + gpios->leds_per_port = 2; + if (of_property_read_u32(np, "led-mode", &gpios->led_mode)) + gpios->led_mode = (0x1ea << 15) | 0x1ea; + if (of_property_read_u32(np, "num-leds", &gpios->num_leds)) + gpios->num_leds = 32; + if (of_property_read_u32(np, "min-led", &gpios->min_led)) + gpios->min_led = 0; + take_port_leds(gpios); + } + + err = devm_gpiochip_add_data(dev, &gpios->gc, gpios); + + return err; +} + +static struct platform_driver rtl838x_gpio_driver = { + .driver = { + .name = "rtl838x-gpio", + .of_match_table = rtl838x_gpio_of_match, + }, + .probe = rtl838x_gpio_probe, +}; + +module_platform_driver(rtl838x_gpio_driver); + +MODULE_DESCRIPTION("Realtek RTL838X GPIO API support"); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch b/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch new file mode 100644 index 0000000000..830440cf8d --- /dev/null +++ b/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch @@ -0,0 +1,25 @@ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -514,6 +514,12 @@ + help + Say yes here to support Realtek RTL8231 GPIO expansion chips. + ++config GPIO_RTL838X ++ tristate "RTL838X GPIO" ++ depends on RTL838X ++ help ++ Say yes here to support RTL838X GPIO on RTL93xx SoCs. ++ + config GPIO_SAMA5D2_PIOBU + tristate "SAMA5D2 PIOBU GPIO support" + depends on MFD_SYSCON +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -127,6 +127,7 @@ + obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o + obj-$(CONFIG_GPIO_REG) += gpio-reg.o + obj-$(CONFIG_GPIO_RTL8231) += gpio-rtl8231.o ++obj-$(CONFIG_GPIO_RTL838X) += gpio-rtl838x.o + obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o + obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o + obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o From 401d7ebf2c9bdcc7c1e24900ed9f8acf87d932c8 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 8 Oct 2021 22:18:34 +0100 Subject: [PATCH 31/59] mediatek: enable configfs for DT overlay on mt7622 and mt7623 Enable kernel options to allow loading device tree overlay via configfs at runtime. This is useful for devboards like the BPi-R2 and BPi-R64 which got RasbPi-compatible 40-pin GPIO header which allow all sorts of extensions. Signed-off-by: Daniel Golle --- target/linux/mediatek/mt7622/config-5.10 | 3 +++ target/linux/mediatek/mt7623/config-5.10 | 2 ++ 2 files changed, 5 insertions(+) diff --git a/target/linux/mediatek/mt7622/config-5.10 b/target/linux/mediatek/mt7622/config-5.10 index c8184f99b8..196de77d1b 100644 --- a/target/linux/mediatek/mt7622/config-5.10 +++ b/target/linux/mediatek/mt7622/config-5.10 @@ -90,6 +90,7 @@ 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 @@ -291,6 +292,7 @@ CONFIG_NVMEM=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y +CONFIG_OF_CONFIGFS=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_FLATTREE=y CONFIG_OF_GPIO=y @@ -298,6 +300,7 @@ CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OF_NET=y +CONFIG_OF_OVERLAY=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_PADATA=y CONFIG_PARTITION_PERCPU=y diff --git a/target/linux/mediatek/mt7623/config-5.10 b/target/linux/mediatek/mt7623/config-5.10 index 8c5c6c6e85..d21fe2cdb2 100644 --- a/target/linux/mediatek/mt7623/config-5.10 +++ b/target/linux/mediatek/mt7623/config-5.10 @@ -446,6 +446,7 @@ CONFIG_NVMEM=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y +CONFIG_OF_CONFIGFS=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_FLATTREE=y CONFIG_OF_GPIO=y @@ -454,6 +455,7 @@ CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OF_NET=y +CONFIG_OF_OVERLAY=y CONFIG_OLD_SIGACTION=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_PADATA=y From 7ab94288e052ad17cbbed5c78a5e7194b0cfa116 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 9 Oct 2021 16:44:01 +0100 Subject: [PATCH 32/59] oxnas: switch to Linux 5.10 Linux 5.10 has been there as testing kernel for a while now. Do the switch and drop config and patches for Linux 5.4. Signed-off-by: Daniel Golle --- target/linux/oxnas/Makefile | 3 +- target/linux/oxnas/config-5.4 | 357 ------------------ .../patches-5.4/010-pogoplug-series-3.patch | 82 ---- .../050-ox820-remove-left-overs.patch | 63 ---- .../patches-5.4/100-oxnas-clk-plla-pllb.patch | 273 -------------- .../oxnas/patches-5.4/150-oxnas-restart.patch | 25 -- .../patches-5.4/320-oxnas-phy-pcie.patch | 44 --- .../oxnas/patches-5.4/340-oxnas-pcie.patch | 122 ------ .../oxnas/patches-5.4/500-oxnas-sata.patch | 59 --- .../patches-5.4/510-ox820-libata-leds.patch | 10 - .../oxnas/patches-5.4/800-oxnas-ehci.patch | 73 ---- ...Mangle-bootloader-s-kernel-arguments.patch | 189 ---------- .../oxnas/patches-5.4/999-libata-hacks.patch | 57 --- 13 files changed, 1 insertion(+), 1356 deletions(-) delete mode 100644 target/linux/oxnas/config-5.4 delete mode 100644 target/linux/oxnas/patches-5.4/010-pogoplug-series-3.patch delete mode 100644 target/linux/oxnas/patches-5.4/050-ox820-remove-left-overs.patch delete mode 100644 target/linux/oxnas/patches-5.4/100-oxnas-clk-plla-pllb.patch delete mode 100644 target/linux/oxnas/patches-5.4/150-oxnas-restart.patch delete mode 100644 target/linux/oxnas/patches-5.4/320-oxnas-phy-pcie.patch delete mode 100644 target/linux/oxnas/patches-5.4/340-oxnas-pcie.patch delete mode 100644 target/linux/oxnas/patches-5.4/500-oxnas-sata.patch delete mode 100644 target/linux/oxnas/patches-5.4/510-ox820-libata-leds.patch delete mode 100644 target/linux/oxnas/patches-5.4/800-oxnas-ehci.patch delete mode 100644 target/linux/oxnas/patches-5.4/996-generic-Mangle-bootloader-s-kernel-arguments.patch delete mode 100644 target/linux/oxnas/patches-5.4/999-libata-hacks.patch diff --git a/target/linux/oxnas/Makefile b/target/linux/oxnas/Makefile index 003ed6ecd6..f52a0ceca5 100644 --- a/target/linux/oxnas/Makefile +++ b/target/linux/oxnas/Makefile @@ -7,8 +7,7 @@ SUBTARGETS:=ox810se ox820 FEATURES:=gpio ramdisk rtc squashfs DEVICE_TYPE:=nas -KERNEL_PATCHVER:=5.4 -KERNEL_TESTING_PATCHVER:=5.10 +KERNEL_PATCHVER:=5.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/oxnas/config-5.4 b/target/linux/oxnas/config-5.4 deleted file mode 100644 index f9bc748ca6..0000000000 --- a/target/linux/oxnas/config-5.4 +++ /dev/null @@ -1,357 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_ARCH_HAS_BINFMT_FLAT=y -CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y -CONFIG_ARCH_HAS_DMA_WRITE_COMBINE=y -CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -CONFIG_ARCH_HAS_FORTIFY_SOURCE=y -CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -CONFIG_ARCH_HAS_KCOV=y -CONFIG_ARCH_HAS_KEEPINITRD=y -CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y -CONFIG_ARCH_HAS_PHYS_TO_DMA=y -CONFIG_ARCH_HAS_RESET_CONTROLLER=y -CONFIG_ARCH_HAS_SETUP_DMA_OPS=y -CONFIG_ARCH_HAS_SET_MEMORY=y -CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y -CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y -CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y -CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_CPU_AUTO=y -# CONFIG_ARCH_MULTI_V4 is not set -# CONFIG_ARCH_MULTI_V4T is not set -CONFIG_ARCH_MULTI_V4_V5=y -CONFIG_ARCH_MULTI_V5=y -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OXNAS=y -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_ARCH_SUPPORTS_UPROBES=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y -CONFIG_ARCH_WANT_LIBATA_LEDS=y -CONFIG_ARM=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_ARM_ATAG_DTB_COMPAT=y -# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set -# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_HAS_SG_CHAIN=y -CONFIG_ARM_L1_CACHE_SHIFT=5 -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_PMU=y -# CONFIG_ARM_SMMU is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_UNWIND=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_CMDLINE_PARSER=y -CONFIG_BLK_DEBUG_FS=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=65536 -CONFIG_BLK_PM=y -CONFIG_BLK_SCSI_REQUEST=y -CONFIG_CC_HAS_KASAN_GENERIC=y -CONFIG_CLKDEV_LOOKUP=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMA=y -CONFIG_CMA_ALIGNMENT=8 -CONFIG_CMA_AREAS=7 -# CONFIG_CMA_DEBUG is not set -# CONFIG_CMA_DEBUGFS is not set -CONFIG_CMA_SIZE_MBYTES=64 -# CONFIG_CMA_SIZE_SEL_MAX is not set -CONFIG_CMA_SIZE_SEL_MBYTES=y -# CONFIG_CMA_SIZE_SEL_MIN is not set -# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set -CONFIG_CMDLINE_PARTITION=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_OXNAS=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONTIG_ALLOC=y -CONFIG_COREDUMP=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5TJ=y -CONFIG_CPU_ARM926T=y -# CONFIG_CPU_CACHE_ROUND_ROBIN is not set -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_LEGACY=y -CONFIG_CPU_PM=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_USE_DOMAINS=y -CONFIG_CRASH_CORE=y -CONFIG_CRC16=y -# CONFIG_CRC32_SARWATE is not set -CONFIG_CRC32_SLICEBY8=y -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CRYPTO_RNG2=y -CONFIG_DEBUG_ALIGN_RODATA=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -# CONFIG_DEBUG_USER is not set -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_LZ4=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DECOMPRESS_LZO=y -CONFIG_DECOMPRESS_XZ=y -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_DMA_CMA=y -CONFIG_DMA_REMAP=y -CONFIG_DNOTIFY=y -CONFIG_DTC=y -# CONFIG_DWMAC_DWC_QOS_ETH is not set -CONFIG_DWMAC_GENERIC=y -CONFIG_DWMAC_OXNAS=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_ELF_CORE=y -CONFIG_FAT_FS=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FREEZER=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GPIOLIB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=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_HAVE_ARCH_AUDITSYSCALL=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_CLK_PREPARE=y -CONFIG_HAVE_CONTEXT_TRACKING=y -CONFIG_HAVE_COPY_THREAD_TLS=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_HAVE_DEBUG_KMEMLEAK=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_HAVE_EBPF_JIT=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y -CONFIG_HAVE_MOD_ARCH_SPECIFIC=y -CONFIG_HAVE_NET_DSA=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_PCI=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_RSEQ=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_UID16=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_HID=y -CONFIG_HID_GENERIC=y -CONFIG_HWMON=y -CONFIG_HZ_FIXED=0 -CONFIG_ICPLUS_PHY=y -CONFIG_INET_DIAG=y -# CONFIG_INET_DIAG_DESTROY is not set -# CONFIG_INET_RAW_DIAG is not set -CONFIG_INET_TCP_DIAG=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set -# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -CONFIG_IOMMU_SUPPORT=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -# CONFIG_ISDN is not set -# CONFIG_JFFS2_FS is not set -CONFIG_KALLSYMS=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_XZ is not set -CONFIG_KEXEC=y -CONFIG_KEXEC_CORE=y -# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGER_CPU=y -CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_LEDS_TRIGGER_ONESHOT=y -CONFIG_LIBFDT=y -CONFIG_LOCALVERSION_AUTO=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZ4_DECOMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_MACH_OX810SE is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MEMFD_CREATE=y -CONFIG_MEMORY_ISOLATION=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_KUSER_HELPERS=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NLS=y -CONFIG_NO_HZ=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_NET=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OXNAS_RPS_TIMER=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PAGE_POOL=y -# CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 -CONFIG_PANIC_TIMEOUT=0 -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHY_OXNAS=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_OXNAS=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PM=y -CONFIG_PM_CLK=y -# CONFIG_PM_DEBUG is not set -CONFIG_PM_SLEEP=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_OXNAS=y -CONFIG_PPS=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_RCU_TRACE=y -CONFIG_RD_BZIP2=y -CONFIG_RD_GZIP=y -CONFIG_RD_LZ4=y -CONFIG_RD_LZMA=y -CONFIG_RD_LZO=y -CONFIG_RD_XZ=y -CONFIG_REALTEK_PHY=y -CONFIG_REFCOUNT_FULL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RESET_OXNAS=y -CONFIG_SCHED_DEBUG=y -CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIO=y -CONFIG_SERIO_LIBPS2=y -CONFIG_SERIO_SERPORT=y -CONFIG_SIMPLE_PM_BUS=y -CONFIG_SLUB_DEBUG=y -CONFIG_SOCK_DIAG=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -CONFIG_SRCU=y -CONFIG_STACKTRACE=y -CONFIG_STMMAC_ETH=y -CONFIG_STMMAC_PLATFORM=y -# CONFIG_STMMAC_SELFTESTS is not set -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWPHY=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_OF=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TINY_SRCU=y -CONFIG_TRACE_CLOCK=y -CONFIG_UEVENT_HELPER_PATH="" -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNWINDER_ARM=y -# CONFIG_UNWINDER_FRAME_POINTER is not set -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VERSATILE_FPGA_IRQ=y -CONFIG_VERSATILE_FPGA_IRQ_NR=4 -CONFIG_VFAT_FS=y -# CONFIG_VFP is not set -CONFIG_VM_EVENT_COUNTERS=y -# CONFIG_WATCHDOG is not set -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_XZ_DEC_IA64=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_X86=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/oxnas/patches-5.4/010-pogoplug-series-3.patch b/target/linux/oxnas/patches-5.4/010-pogoplug-series-3.patch deleted file mode 100644 index 44102352af..0000000000 --- a/target/linux/oxnas/patches-5.4/010-pogoplug-series-3.patch +++ /dev/null @@ -1,82 +0,0 @@ -- add compatible string -- add console to bootargs -- add led aliases -- adjust nand partition table ---- ---- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts -+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts -@@ -11,10 +11,10 @@ - / { - model = "Cloud Engines PogoPlug Series 3"; - -- compatible = "cloudengines,pogoplugv3", "oxsemi,ox820"; -+ compatible = "cloudengines,pogoplug-series-3", "cloudengines,pogoplugv3", "oxsemi,ox820"; - - chosen { -- bootargs = "earlyprintk"; -+ bootargs = "earlyprintk console=ttyS0,115200"; - stdout-path = "serial0:115200n8"; - }; - -@@ -27,24 +27,28 @@ - serial0 = &uart0; - gpio0 = &gpio0; - gpio1 = &gpio1; -+ led-boot = &led_status; -+ led-failsafe = &led_warn; -+ led-running = &led_act; -+ led-upgrade = &led_warn; - }; - - leds { - compatible = "gpio-leds"; - -- blue { -+ led_status: blue { - label = "pogoplug:blue"; - gpios = <&gpio0 2 0>; - default-state = "keep"; - }; - -- orange { -+ led_warn: orange { - label = "pogoplug:orange"; - gpios = <&gpio1 16 1>; - default-state = "keep"; - }; - -- green { -+ led_act: green { - label = "pogoplug:green"; - gpios = <&gpio1 17 1>; - default-state = "keep"; -@@ -73,11 +77,27 @@ - nand-ecc-algo = "hamming"; - - partition@0 { -- label = "boot"; -- reg = <0x00000000 0x00e00000>; -+ label = "stage1"; -+ reg = <0x00000000 0x00040000>; - read-only; - }; - -+ partition@40000 { -+ label = "u-boot"; -+ reg = <0x00040000 0x00380000>; -+ read-only; -+ }; -+ -+ partition@3c0000 { -+ label = "u-boot-env"; -+ reg = <0x003c0000 0x00080000>; -+ }; -+ -+ partition@440000 { -+ label = "kernel"; -+ reg = <0x00440000 0x009c0000>; -+ }; -+ - partition@e00000 { - label = "ubi"; - reg = <0x00e00000 0x07200000>; diff --git a/target/linux/oxnas/patches-5.4/050-ox820-remove-left-overs.patch b/target/linux/oxnas/patches-5.4/050-ox820-remove-left-overs.patch deleted file mode 100644 index e30f328792..0000000000 --- a/target/linux/oxnas/patches-5.4/050-ox820-remove-left-overs.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 552ed4955c1fee1109bf5ba137dc35a411a1448c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 1 Jun 2018 02:41:15 +0200 -Subject: [PATCH] arm: ox820: remove left-overs - -Signed-off-by: Daniel Golle ---- - drivers/clk/clk-oxnas.c | 2 -- - include/dt-bindings/clock/oxsemi,ox820.h | 32 +++++++++++------------- - 2 files changed, 14 insertions(+), 20 deletions(-) - ---- a/drivers/clk/clk-oxnas.c -+++ b/drivers/clk/clk-oxnas.c -@@ -29,8 +29,6 @@ struct oxnas_stdclk_data { - struct clk_hw_onecell_data *onecell_data; - struct clk_oxnas_gate **gates; - unsigned int ngates; -- struct clk_oxnas_pll **plls; -- unsigned int nplls; - }; - - /* Regmap offsets */ ---- a/include/dt-bindings/clock/oxsemi,ox820.h -+++ b/include/dt-bindings/clock/oxsemi,ox820.h -@@ -6,24 +6,20 @@ - #ifndef DT_CLOCK_OXSEMI_OX820_H - #define DT_CLOCK_OXSEMI_OX820_H - --/* PLLs */ --#define CLK_820_PLLA 0 --#define CLK_820_PLLB 1 -- - /* Gate Clocks */ --#define CLK_820_LEON 2 --#define CLK_820_DMA_SGDMA 3 --#define CLK_820_CIPHER 4 --#define CLK_820_SD 5 --#define CLK_820_SATA 6 --#define CLK_820_AUDIO 7 --#define CLK_820_USBMPH 8 --#define CLK_820_ETHA 9 --#define CLK_820_PCIEA 10 --#define CLK_820_NAND 11 --#define CLK_820_PCIEB 12 --#define CLK_820_ETHB 13 --#define CLK_820_REF600 14 --#define CLK_820_USBDEV 15 -+#define CLK_820_LEON 0 -+#define CLK_820_DMA_SGDMA 1 -+#define CLK_820_CIPHER 2 -+#define CLK_820_SD 3 -+#define CLK_820_SATA 4 -+#define CLK_820_AUDIO 5 -+#define CLK_820_USBMPH 6 -+#define CLK_820_ETHA 7 -+#define CLK_820_PCIEA 8 -+#define CLK_820_NAND 9 -+#define CLK_820_PCIEB 10 -+#define CLK_820_ETHB 11 -+#define CLK_820_REF600 12 -+#define CLK_820_USBDEV 13 - - #endif /* DT_CLOCK_OXSEMI_OX820_H */ diff --git a/target/linux/oxnas/patches-5.4/100-oxnas-clk-plla-pllb.patch b/target/linux/oxnas/patches-5.4/100-oxnas-clk-plla-pllb.patch deleted file mode 100644 index 29a9036498..0000000000 --- a/target/linux/oxnas/patches-5.4/100-oxnas-clk-plla-pllb.patch +++ /dev/null @@ -1,273 +0,0 @@ ---- a/drivers/clk/clk-oxnas.c -+++ b/drivers/clk/clk-oxnas.c -@@ -5,19 +5,42 @@ - * Copyright (C) 2016 Neil Armstrong - */ - -+#include -+#include - #include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -+#include - - #include - #include - -+#define REF300_DIV_INT_SHIFT 8 -+#define REF300_DIV_FRAC_SHIFT 0 -+#define REF300_DIV_INT(val) ((val) << REF300_DIV_INT_SHIFT) -+#define REF300_DIV_FRAC(val) ((val) << REF300_DIV_FRAC_SHIFT) -+ -+#define PLLB_BYPASS 1 -+#define PLLB_ENSAT 3 -+#define PLLB_OUTDIV 4 -+#define PLLB_REFDIV 8 -+#define PLLB_DIV_INT_SHIFT 8 -+#define PLLB_DIV_FRAC_SHIFT 0 -+#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT) -+#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT) -+ -+#define PLLA_REFDIV_MASK 0x3F -+#define PLLA_REFDIV_SHIFT 8 -+#define PLLA_OUTDIV_MASK 0x7 -+#define PLLA_OUTDIV_SHIFT 4 -+ - /* Standard regmap gate clocks */ - struct clk_oxnas_gate { - struct clk_hw hw; -@@ -36,6 +59,135 @@ struct oxnas_stdclk_data { - #define CLK_SET_REGOFFSET 0x2c - #define CLK_CLR_REGOFFSET 0x30 - -+#define PLLA_CTRL0_REGOFFSET 0x1f0 -+#define PLLA_CTRL1_REGOFFSET 0x1f4 -+#define PLLB_CTRL0_REGOFFSET 0x1001f0 -+#define MHZ (1000 * 1000) -+ -+struct clk_oxnas_pll { -+ struct clk_hw hw; -+ struct device_node *devnode; -+ struct reset_control *rstc; -+ struct regmap *syscon; -+}; -+ -+#define to_clk_oxnas_pll(_hw) container_of(_hw, struct clk_oxnas_pll, hw) -+ -+static unsigned long plla_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct clk_oxnas_pll *plla = to_clk_oxnas_pll(hw); -+ unsigned long fin = parent_rate; -+ unsigned long refdiv, outdiv; -+ unsigned int pll0, fbdiv; -+ -+ BUG_ON(regmap_read(plla->syscon, PLLA_CTRL0_REGOFFSET, &pll0)); -+ -+ refdiv = (pll0 >> PLLA_REFDIV_SHIFT) & PLLA_REFDIV_MASK; -+ refdiv += 1; -+ outdiv = (pll0 >> PLLA_OUTDIV_SHIFT) & PLLA_OUTDIV_MASK; -+ outdiv += 1; -+ -+ BUG_ON(regmap_read(plla->syscon, PLLA_CTRL1_REGOFFSET, &fbdiv)); -+ /* seems we will not be here when pll is bypassed, so ignore this -+ * case */ -+ -+ return fin / MHZ * fbdiv / (refdiv * outdiv) / 32768 * MHZ; -+} -+ -+static const char *pll_clk_parents[] = { -+ "oscillator", -+}; -+ -+static struct clk_ops plla_ops = { -+ .recalc_rate = plla_clk_recalc_rate, -+}; -+ -+static struct clk_init_data clk_plla_init = { -+ .name = "plla", -+ .ops = &plla_ops, -+ .parent_names = pll_clk_parents, -+ .num_parents = ARRAY_SIZE(pll_clk_parents), -+}; -+ -+static int pllb_clk_is_prepared(struct clk_hw *hw) -+{ -+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw); -+ -+ return !!pllb->rstc; -+} -+ -+static int pllb_clk_prepare(struct clk_hw *hw) -+{ -+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw); -+ -+ pllb->rstc = of_reset_control_get(pllb->devnode, NULL); -+ -+ return IS_ERR(pllb->rstc) ? PTR_ERR(pllb->rstc) : 0; -+} -+ -+static void pllb_clk_unprepare(struct clk_hw *hw) -+{ -+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw); -+ -+ BUG_ON(IS_ERR(pllb->rstc)); -+ -+ reset_control_put(pllb->rstc); -+ pllb->rstc = NULL; -+} -+ -+static int pllb_clk_enable(struct clk_hw *hw) -+{ -+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw); -+ -+ BUG_ON(IS_ERR(pllb->rstc)); -+ -+ /* put PLL into bypass */ -+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS)); -+ wmb(); -+ udelay(10); -+ reset_control_assert(pllb->rstc); -+ udelay(10); -+ /* set PLL B control information */ -+ regmap_write_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, 0xffff, -+ (1 << PLLB_ENSAT) | (1 << PLLB_OUTDIV) | (2 << PLLB_REFDIV)); -+ reset_control_deassert(pllb->rstc); -+ udelay(100); -+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), 0); -+ -+ return 0; -+} -+ -+static void pllb_clk_disable(struct clk_hw *hw) -+{ -+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw); -+ -+ BUG_ON(IS_ERR(pllb->rstc)); -+ -+ /* put PLL into bypass */ -+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS)); -+ -+ wmb(); -+ udelay(10); -+ -+ reset_control_assert(pllb->rstc); -+} -+ -+static struct clk_ops pllb_ops = { -+ .prepare = pllb_clk_prepare, -+ .unprepare = pllb_clk_unprepare, -+ .is_prepared = pllb_clk_is_prepared, -+ .enable = pllb_clk_enable, -+ .disable = pllb_clk_disable, -+}; -+ -+static struct clk_init_data clk_pllb_init = { -+ .name = "pllb", -+ .ops = &pllb_ops, -+ .parent_names = pll_clk_parents, -+ .num_parents = ARRAY_SIZE(pll_clk_parents), -+}; -+ - static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw) - { - return container_of(hw, struct clk_oxnas_gate, hw); -@@ -249,3 +401,42 @@ static struct platform_driver oxnas_stdc - }, - }; - builtin_platform_driver(oxnas_stdclk_driver); -+ -+void __init oxnas_init_plla(struct device_node *np) -+{ -+ struct clk *clk; -+ struct clk_oxnas_pll *plla; -+ -+ plla = kmalloc(sizeof(*plla), GFP_KERNEL); -+ BUG_ON(!plla); -+ -+ plla->syscon = syscon_node_to_regmap(of_get_parent(np)); -+ plla->hw.init = &clk_plla_init; -+ plla->devnode = np; -+ plla->rstc = NULL; -+ clk = clk_register(NULL, &plla->hw); -+ BUG_ON(IS_ERR(clk)); -+ /* mark it as enabled */ -+ clk_prepare_enable(clk); -+ of_clk_add_provider(np, of_clk_src_simple_get, clk); -+} -+CLK_OF_DECLARE(oxnas_plla, "plxtech,nas782x-plla", oxnas_init_plla); -+ -+void __init oxnas_init_pllb(struct device_node *np) -+{ -+ struct clk *clk; -+ struct clk_oxnas_pll *pllb; -+ -+ pllb = kmalloc(sizeof(*pllb), GFP_KERNEL); -+ BUG_ON(!pllb); -+ -+ pllb->syscon = syscon_node_to_regmap(of_get_parent(np)); -+ pllb->hw.init = &clk_pllb_init; -+ pllb->devnode = np; -+ pllb->rstc = NULL; -+ -+ clk = clk_register(NULL, &pllb->hw); -+ BUG_ON(IS_ERR(clk)); -+ of_clk_add_provider(np, of_clk_src_simple_get, clk); -+} -+CLK_OF_DECLARE(oxnas_pllb, "plxtech,nas782x-pllb", oxnas_init_pllb); ---- a/arch/arm/boot/dts/ox820.dtsi -+++ b/arch/arm/boot/dts/ox820.dtsi -@@ -61,12 +61,6 @@ - clocks = <&osc>; - }; - -- plla: plla { -- compatible = "fixed-clock"; -- #clock-cells = <0>; -- clock-frequency = <850000000>; -- }; -- - armclk: armclk { - compatible = "fixed-factor-clock"; - #clock-cells = <0>; -@@ -266,6 +260,19 @@ - compatible = "oxsemi,ox820-stdclk", "oxsemi,ox810se-stdclk"; - #clock-cells = <1>; - }; -+ -+ plla: plla { -+ compatible = "plxtech,nas782x-plla"; -+ #clock-cells = <0>; -+ clocks = <&osc>; -+ }; -+ -+ pllb: pllb { -+ compatible = "plxtech,nas782x-pllb"; -+ #clock-cells = <0>; -+ clocks = <&osc>; -+ resets = <&reset RESET_PLLB>; -+ }; - }; - }; - -@@ -287,6 +294,13 @@ - clocks = <&armclk>; - }; - -+ watchdog@620 { -+ compatible = "mpcore_wdt"; -+ reg = <0x620 0x20>; -+ interrupts = ; -+ clocks = <&armclk>; -+ }; -+ - gic: gic@1000 { - compatible = "arm,arm11mp-gic"; - interrupt-controller; diff --git a/target/linux/oxnas/patches-5.4/150-oxnas-restart.patch b/target/linux/oxnas/patches-5.4/150-oxnas-restart.patch deleted file mode 100644 index 79fbd9cdbe..0000000000 --- a/target/linux/oxnas/patches-5.4/150-oxnas-restart.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/drivers/power/reset/Kconfig -+++ b/drivers/power/reset/Kconfig -@@ -123,6 +123,12 @@ config POWER_RESET_OCELOT_RESET - help - This driver supports restart for Microsemi Ocelot SoC. - -+config POWER_RESET_OXNAS -+ bool "OXNAS SoC restart driver" -+ depends on ARCH_OXNAS -+ help -+ Restart support for OXNAS boards. -+ - config POWER_RESET_PIIX4_POWEROFF - tristate "Intel PIIX4 power-off driver" - depends on PCI ---- a/drivers/power/reset/Makefile -+++ b/drivers/power/reset/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-p - obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o - obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o - obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o -+obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o - obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o - obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o - obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o diff --git a/target/linux/oxnas/patches-5.4/320-oxnas-phy-pcie.patch b/target/linux/oxnas/patches-5.4/320-oxnas-phy-pcie.patch deleted file mode 100644 index cf272f76b7..0000000000 --- a/target/linux/oxnas/patches-5.4/320-oxnas-phy-pcie.patch +++ /dev/null @@ -1,44 +0,0 @@ ---- a/arch/arm/boot/dts/ox820.dtsi -+++ b/arch/arm/boot/dts/ox820.dtsi -@@ -247,6 +247,15 @@ - }; - }; - -+ pcie_phy: pcie-phy@a00000 { -+ compatible = "oxsemi,ox820-pcie-phy"; -+ reg = <0xa00000 0x10>; -+ #phy-cells = <0>; -+ resets = <&reset RESET_PCIEPHY>; -+ reset-names = "phy"; -+ status = "disabled"; -+ }; -+ - sys: sys-ctrl@e00000 { - compatible = "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd"; - reg = <0xe00000 0x200000>; ---- a/drivers/phy/Kconfig -+++ b/drivers/phy/Kconfig -@@ -35,6 +35,13 @@ config PHY_LPC18XX_USB_OTG - This driver is need for USB0 support on LPC18xx/43xx and takes - care of enabling and clock setup. - -+config PHY_OXNAS -+ tristate "Oxford Semi. OX820 PCI-E PHY support" -+ depends on HAS_IOMEM && OF && (ARM || COMPILE_TEST) -+ select GENERIC_PHY -+ help -+ This option enables support for OXNAS OX820 SoC PCIE PHY. -+ - config PHY_PISTACHIO_USB - tristate "IMG Pistachio USB2.0 PHY driver" - depends on MACH_PISTACHIO ---- a/drivers/phy/Makefile -+++ b/drivers/phy/Makefile -@@ -6,6 +6,7 @@ - obj-$(CONFIG_GENERIC_PHY) += phy-core.o - obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o - obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o -+obj-$(CONFIG_PHY_OXNAS) += phy-oxnas-pcie.o - obj-$(CONFIG_PHY_XGENE) += phy-xgene.o - obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o - obj-$(CONFIG_ARCH_SUNXI) += allwinner/ diff --git a/target/linux/oxnas/patches-5.4/340-oxnas-pcie.patch b/target/linux/oxnas/patches-5.4/340-oxnas-pcie.patch deleted file mode 100644 index 19065233cf..0000000000 --- a/target/linux/oxnas/patches-5.4/340-oxnas-pcie.patch +++ /dev/null @@ -1,122 +0,0 @@ ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -48,6 +48,11 @@ config PCIE_CADENCE_EP - endpoint mode. This PCIe controller may be embedded into many - different vendors SoCs. - -+config PCIE_OXNAS -+ bool "PLX Oxnas PCIe controller" -+ depends on ARCH_OXNAS -+ select PCIEPORTBUS -+ - endmenu - - config PCIE_XILINX_NWL ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-r - obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o - obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o - obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o -+obj-$(CONFIG_PCIE_OXNAS) += pcie-oxnas.o - obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o - obj-$(CONFIG_VMD) += vmd.o - # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW ---- a/arch/arm/boot/dts/ox820.dtsi -+++ b/arch/arm/boot/dts/ox820.dtsi -@@ -289,7 +289,7 @@ - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; -- ranges = <0 0x47000000 0x1000000>; -+ ranges = <0 0x47000000 0x2000>; - - scu: scu@0 { - compatible = "arm,arm11mp-scu"; -@@ -318,5 +318,86 @@ - <0x100 0x500>; - }; - }; -+ -+ pcie0: pcie-controller@47c00000 { -+ compatible = "plxtech,nas782x-pcie"; -+ device_type = "pci"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ /* flag & space bus address host address size */ -+ ranges = < 0x82000000 0 0x48000000 0x48000000 0 0x2000000 -+ 0xC2000000 0 0x4A000000 0x4A000000 0 0x1E00000 -+ 0x81000000 0 0x4BE00000 0x4BE00000 0 0x0100000 -+ 0x80000000 0 0x4BF00000 0x4BF00000 0 0x0100000>; -+ -+ bus-range = <0x00 0x7f>; -+ -+ /* cfg inbound translator */ -+ reg = <0x47c00000 0x1000>, <0x47d00000 0x100>; -+ -+ phys = <&pcie_phy>; -+ phy-names = "pcie-phy"; -+ -+ #interrupt-cells = <1>; -+ /* wild card mask, match all bus address & interrupt specifier */ -+ /* format: bus address mask, interrupt specifier mask */ -+ /* each bit 1 means need match, 0 means ignored when match */ -+ interrupt-map-mask = <0 0 0 0>; -+ /* format: a list of: bus address, interrupt specifier, -+ * parent interrupt controller & specifier */ -+ interrupt-map = <0 0 0 0 &gic 0 19 0x304>; -+ gpios = <&gpio1 12 0>; -+ clocks = <&stdclk CLK_820_PCIEA>, <&pllb>; -+ clock-names = "pcie", "busclk"; -+ resets = <&reset RESET_PCIEA>; -+ reset-names = "pcie"; -+ -+ plxtech,pcie-hcsl-bit = <2>; -+ plxtech,pcie-ctrl-offset = <0x120>; -+ plxtech,pcie-outbound-offset = <0x138>; -+ status = "disabled"; -+ }; -+ -+ pcie1: pcie-controller@47e00000 { -+ compatible = "plxtech,nas782x-pcie"; -+ device_type = "pci"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ /* flag & space bus address host address size */ -+ ranges = < 0x82000000 0 0x4C000000 0x4C000000 0 0x2000000 -+ 0xC2000000 0 0x4E000000 0x4E000000 0 0x1E00000 -+ 0x81000000 0 0x4FE00000 0x4FE00000 0 0x0100000 -+ 0x80000000 0 0x4FF00000 0x4FF00000 0 0x0100000>; -+ -+ bus-range = <0x80 0xff>; -+ -+ /* cfg inbound translator */ -+ reg = <0x47e00000 0x1000>, <0x47f00000 0x100>; -+ -+ phys = <&pcie_phy>; -+ phy-names = "pcie-phy"; -+ -+ #interrupt-cells = <1>; -+ /* wild card mask, match all bus address & interrupt specifier */ -+ /* format: bus address mask, interrupt specifier mask */ -+ /* each bit 1 means need match, 0 means ignored when match */ -+ interrupt-map-mask = <0 0 0 0>; -+ /* format: a list of: bus address, interrupt specifier, -+ * parent interrupt controller & specifier */ -+ interrupt-map = <0 0 0 0 &gic 0 20 0x304>; -+ -+ /* gpios = <&gpio1 12 0>; */ -+ clocks = <&stdclk CLK_820_PCIEB>, <&pllb>; -+ clock-names = "pcie", "busclk"; -+ resets = <&reset RESET_PCIEB>; -+ reset-names = "pcie"; -+ -+ plxtech,pcie-hcsl-bit = <3>; -+ plxtech,pcie-ctrl-offset = <0x124>; -+ plxtech,pcie-outbound-offset = <0x174>; -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/oxnas/patches-5.4/500-oxnas-sata.patch b/target/linux/oxnas/patches-5.4/500-oxnas-sata.patch deleted file mode 100644 index dda82e7beb..0000000000 --- a/target/linux/oxnas/patches-5.4/500-oxnas-sata.patch +++ /dev/null @@ -1,59 +0,0 @@ ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -508,6 +508,13 @@ config SATA_VITESSE - - If unsure, say N. - -+config SATA_OXNAS -+ tristate "PLXTECH NAS782X SATA support" -+ help -+ This option enables support for Nas782x Serial ATA controller. -+ -+ If unsure, say N. -+ - comment "PATA SFF controllers with BMDMA" - - config PATA_ALI ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -46,6 +46,7 @@ obj-$(CONFIG_SATA_SVW) += sata_svw.o - obj-$(CONFIG_SATA_ULI) += sata_uli.o - obj-$(CONFIG_SATA_VIA) += sata_via.o - obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o -+obj-$(CONFIG_SATA_OXNAS) += sata_oxnas.o - - # SFF PATA w/ BMDMA - obj-$(CONFIG_PATA_ALI) += pata_ali.o ---- a/arch/arm/boot/dts/ox820.dtsi -+++ b/arch/arm/boot/dts/ox820.dtsi -@@ -399,5 +399,20 @@ - plxtech,pcie-outbound-offset = <0x174>; - status = "disabled"; - }; -+ -+ sata: sata@45900000 { -+ compatible = "plxtech,nas782x-sata"; -+ /* ports dmactl sgdma */ -+ reg = <0x45900000 0x20000>, <0x459A0000 0x40>, <0x459B0000 0x20>, -+ /* core phy descriptors (optional) */ -+ <0x459E0000 0x2000>, <0x44900000 0x0C>, <0x50000000 0x1000>; -+ interrupts = ; -+ clocks = <&stdclk CLK_820_SATA>; -+ resets = <&reset RESET_SATA>, <&reset RESET_SATA_LINK>, <&reset RESET_SATA_PHY>; -+ reset-names = "sata", "link", "phy"; -+ nr-ports = <1>; -+ status = "disabled"; -+ }; -+ - }; - }; ---- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts -+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts -@@ -111,3 +111,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_etha_mdio>; - }; -+ -+&sata { -+ status = "okay"; -+}; diff --git a/target/linux/oxnas/patches-5.4/510-ox820-libata-leds.patch b/target/linux/oxnas/patches-5.4/510-ox820-libata-leds.patch deleted file mode 100644 index 05ae9ba44b..0000000000 --- a/target/linux/oxnas/patches-5.4/510-ox820-libata-leds.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/mach-oxnas/Kconfig -+++ b/arch/arm/mach-oxnas/Kconfig -@@ -2,6 +2,7 @@ - menuconfig ARCH_OXNAS - bool "Oxford Semiconductor OXNAS Family SoCs" - select ARCH_HAS_RESET_CONTROLLER -+ select ARCH_WANT_LIBATA_LEDS - select COMMON_CLK_OXNAS - select GPIOLIB - select MFD_SYSCON diff --git a/target/linux/oxnas/patches-5.4/800-oxnas-ehci.patch b/target/linux/oxnas/patches-5.4/800-oxnas-ehci.patch deleted file mode 100644 index 6c0f1cb109..0000000000 --- a/target/linux/oxnas/patches-5.4/800-oxnas-ehci.patch +++ /dev/null @@ -1,73 +0,0 @@ ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -321,6 +321,13 @@ config USB_OCTEON_EHCI - USB 2.0 device support. All CN6XXX based chips with USB are - supported. - -+config USB_EHCI_OXNAS -+ tristate "OXNAS EHCI Module" -+ depends on USB_EHCI_HCD && ARCH_OXNAS -+ select USB_EHCI_ROOT_HUB_TT -+ ---help--- -+ Enable support for the OX820 SOC's on-chip EHCI controller. -+ - endif # USB_EHCI_HCD - - config USB_OXU210HP_HCD ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -49,6 +49,7 @@ obj-$(CONFIG_USB_EHCI_HCD_STI) += ehci-s - obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o - obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o - obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o -+obj-$(CONFIG_USB_EHCI_OXNAS) += ehci-oxnas.o - - obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o - obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o ---- a/arch/arm/boot/dts/ox820.dtsi -+++ b/arch/arm/boot/dts/ox820.dtsi -@@ -106,6 +106,31 @@ - status = "disabled"; - }; - -+ ehci: ehci@40200100 { -+ compatible = "plxtech,nas782x-ehci"; -+ reg = <0x40200100 0xf00>; -+ interrupts = ; -+ clocks = <&stdclk CLK_820_USBMPH>, <&pllb>, <&stdclk CLK_820_REF600>; -+ clock-names = "usb", "refsrc", "phyref"; -+ resets = <&reset RESET_USBHS>, <&reset RESET_USBPHYA>, <&reset RESET_USBPHYB>; -+ reset-names = "host", "phya", "phyb"; -+ oxsemi,sys-ctrl = <&sys>; -+ /* Otherwise ref300 is used, which is derived from sata phy -+ * in that case, usb depends on sata initialization */ -+ /* FIXME: how to make this dependency explicit ? */ -+ oxsemi,ehci_use_pllb; -+ status = "disabled"; -+ -+ ehci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ ehci_port2: port@2 { -+ reg = <2>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ - apb-bridge@44000000 { - #address-cells = <1>; - #size-cells = <1>; ---- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts -+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts -@@ -105,6 +105,10 @@ - }; - }; - -+&ehci { -+ status = "okay"; -+}; -+ - ða { - status = "okay"; - diff --git a/target/linux/oxnas/patches-5.4/996-generic-Mangle-bootloader-s-kernel-arguments.patch b/target/linux/oxnas/patches-5.4/996-generic-Mangle-bootloader-s-kernel-arguments.patch deleted file mode 100644 index 8c83d55b6c..0000000000 --- a/target/linux/oxnas/patches-5.4/996-generic-Mangle-bootloader-s-kernel-arguments.patch +++ /dev/null @@ -1,189 +0,0 @@ -From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 -From: Adrian Panella -Date: Thu, 9 Mar 2017 09:37:17 +0100 -Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments - -The command-line arguments provided by the boot loader will be -appended to a new device tree property: bootloader-args. -If there is a property "append-rootblock" in DT under /chosen -and a root= option in bootloaders command line it will be parsed -and added to DT bootargs with the form: XX. -Only command line ATAG will be processed, the rest of the ATAGs -sent by bootloader will be ignored. -This is usefull in dual boot systems, to get the current root partition -without afecting the rest of the system. - -Signed-off-by: Adrian Panella ---- - arch/arm/Kconfig | 11 +++++ - arch/arm/boot/compressed/atags_to_fdt.c | 72 ++++++++++++++++++++++++++++++++- - init/main.c | 16 ++++++++ - 3 files changed, 98 insertions(+), 1 deletion(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1827,6 +1827,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN - The command-line arguments provided by the boot loader will be - appended to the the device tree bootargs property. - -+config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE -+ bool "Append rootblock parsing bootloader's kernel arguments" -+ help -+ The command-line arguments provided by the boot loader will be -+ appended to a new device tree property: bootloader-args. -+ If there is a property "append-rootblock" in DT under /chosen -+ and a root= option in bootloaders command line it will be parsed -+ and added to DT bootargs with the form: XX. -+ Only command line ATAG will be processed, the rest of the ATAGs -+ sent by bootloader will be ignored. -+ - endchoice - - config CMDLINE ---- a/arch/arm/boot/compressed/atags_to_fdt.c -+++ b/arch/arm/boot/compressed/atags_to_fdt.c -@@ -4,6 +4,8 @@ - - #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) - #define do_extend_cmdline 1 -+#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) -+#define do_extend_cmdline 1 - #else - #define do_extend_cmdline 0 - #endif -@@ -67,6 +69,59 @@ static uint32_t get_cell_size(const void - return cell_size; - } - -+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) -+ -+static char *append_rootblock(char *dest, const char *str, int len, void *fdt) -+{ -+ char *ptr, *end; -+ char *root="root="; -+ int i, l; -+ const char *rootblock; -+ -+ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually -+ ptr = str - 1; -+ -+ do { -+ //first find an 'r' at the begining or after a space -+ do { -+ ptr++; -+ ptr = strchr(ptr, 'r'); -+ if(!ptr) return dest; -+ -+ } while (ptr != str && *(ptr-1) != ' '); -+ -+ //then check for the rest -+ for(i = 1; i <= 4; i++) -+ if(*(ptr+i) != *(root+i)) break; -+ -+ } while (i != 5); -+ -+ end = strchr(ptr, ' '); -+ end = end ? (end - 1) : (strchr(ptr, 0) - 1); -+ -+ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX ) -+ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++); -+ ptr = end + 1; -+ -+ /* if append-rootblock property is set use it to append to command line */ -+ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l); -+ if(rootblock != NULL) { -+ if(*dest != ' ') { -+ *dest = ' '; -+ dest++; -+ len++; -+ } -+ if (len + l + i <= COMMAND_LINE_SIZE) { -+ memcpy(dest, rootblock, l); -+ dest += l - 1; -+ memcpy(dest, ptr, i); -+ dest += i; -+ } -+ } -+ return dest; -+} -+#endif -+ - static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) - { - char cmdline[COMMAND_LINE_SIZE]; -@@ -86,12 +141,21 @@ static void merge_fdt_bootargs(void *fdt - - /* and append the ATAG_CMDLINE */ - if (fdt_cmdline) { -+ -+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) -+ //save original bootloader args -+ //and append ubi.mtd with root partition number to current cmdline -+ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline); -+ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt); -+ -+#else - len = strlen(fdt_cmdline); - if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { - *ptr++ = ' '; - memcpy(ptr, fdt_cmdline, len); - ptr += len; - } -+#endif - } - *ptr = '\0'; - -@@ -166,7 +230,9 @@ int atags_to_fdt(void *atag_list, void * - else - setprop_string(fdt, "/chosen", "bootargs", - atag->u.cmdline.cmdline); -- } else if (atag->hdr.tag == ATAG_MEM) { -+ } -+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE -+ else if (atag->hdr.tag == ATAG_MEM) { - if (memcount >= sizeof(mem_reg_property)/4) - continue; - if (!atag->u.mem.size) -@@ -210,6 +276,10 @@ int atags_to_fdt(void *atag_list, void * - setprop(fdt, "/memory", "reg", mem_reg_property, - 4 * memcount * memsize); - } -+#else -+ -+ } -+#endif - - return fdt_pack(fdt); - } ---- a/init/main.c -+++ b/init/main.c -@@ -104,6 +104,10 @@ - #define CREATE_TRACE_POINTS - #include - -+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) -+#include -+#endif -+ - static int kernel_init(void *); - - extern void init_IRQ(void); -@@ -631,6 +635,18 @@ asmlinkage __visible void __init start_k - page_alloc_init(); - - pr_notice("Kernel command line: %s\n", boot_command_line); -+ -+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) -+ //Show bootloader's original command line for reference -+ if(of_chosen) { -+ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL); -+ if(prop) -+ pr_notice("Bootloader command line (ignored): %s\n", prop); -+ else -+ pr_notice("Bootloader command line not present\n"); -+ } -+#endif -+ - /* parameters may set static keys */ - jump_label_init(); - parse_early_param(); diff --git a/target/linux/oxnas/patches-5.4/999-libata-hacks.patch b/target/linux/oxnas/patches-5.4/999-libata-hacks.patch deleted file mode 100644 index d91f2d6724..0000000000 --- a/target/linux/oxnas/patches-5.4/999-libata-hacks.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- a/drivers/ata/libata-core.c -+++ b/drivers/ata/libata-core.c -@@ -1583,6 +1583,14 @@ unsigned ata_exec_internal_sg(struct ata - return AC_ERR_SYSTEM; - } - -+ if (ap->ops->acquire_hw && !ap->ops->acquire_hw(ap, 0, 0)) { -+ spin_unlock_irqrestore(ap->lock, flags); -+ if (!ap->ops->acquire_hw(ap, 1, (2*HZ))) { -+ return AC_ERR_TIMEOUT; -+ } -+ spin_lock_irqsave(ap->lock, flags); -+ } -+ - /* initialize internal qc */ - qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL); - -@@ -5128,6 +5136,9 @@ struct ata_queued_cmd *ata_qc_new_init(s - if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) - return NULL; - -+ if (ap->ops->qc_new && ap->ops->qc_new(ap)) -+ return NULL; -+ - /* libsas case */ - if (ap->flags & ATA_FLAG_SAS_HOST) { - tag = ata_sas_allocate_tag(ap); -@@ -5173,6 +5184,8 @@ void ata_qc_free(struct ata_queued_cmd * - qc->tag = ATA_TAG_POISON; - if (ap->flags & ATA_FLAG_SAS_HOST) - ata_sas_free_tag(tag, ap); -+ if (ap->ops->qc_free) -+ ap->ops->qc_free(qc); - } - } - ---- a/include/linux/libata.h -+++ b/include/linux/libata.h -@@ -910,6 +910,8 @@ struct ata_port_operations { - enum ata_completion_errors (*qc_prep)(struct ata_queued_cmd *qc); - unsigned int (*qc_issue)(struct ata_queued_cmd *qc); - bool (*qc_fill_rtf)(struct ata_queued_cmd *qc); -+ int (*qc_new)(struct ata_port *ap); -+ void (*qc_free)(struct ata_queued_cmd *qc); - - /* - * Configuration and exception handling -@@ -1000,6 +1002,9 @@ struct ata_port_operations { - void (*phy_reset)(struct ata_port *ap); - void (*eng_timeout)(struct ata_port *ap); - -+ int (*acquire_hw)(struct ata_port *ap, int may_sleep, -+ int timeout_jiffies); -+ - /* - * ->inherits must be the last field and all the preceding - * fields must be pointers. From fb76d543b6db059576c950d16f5ef3a38f5298f6 Mon Sep 17 00:00:00 2001 From: Adrian Schmutzler Date: Sat, 9 Oct 2021 18:44:55 +0200 Subject: [PATCH 33/59] kirkwood: switch to kernel 5.10 This target has testing support for more than half a year now. Time to switch. Signed-off-by: Adrian Schmutzler --- target/linux/kirkwood/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/kirkwood/Makefile b/target/linux/kirkwood/Makefile index 1f5159e444..e972b8e587 100644 --- a/target/linux/kirkwood/Makefile +++ b/target/linux/kirkwood/Makefile @@ -10,8 +10,7 @@ BOARDNAME:=Marvell Kirkwood FEATURES:=usb nand squashfs ramdisk CPU_TYPE:=xscale -KERNEL_PATCHVER:=5.4 -KERNEL_TESTING_PATCHVER:=5.10 +KERNEL_PATCHVER:=5.10 include $(INCLUDE_DIR)/target.mk From 46646efc38b496d95c87d1951aff21d2cff838d5 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 2 Oct 2021 19:57:57 +0200 Subject: [PATCH 34/59] mvebu: mochabin: correct LED labels in DTS LED labels got reversed by accident, so fix it to the usual color:led_name format. Fixes: 78cf3e53b1f4 ("mvebu: add Globalscale MOCHAbin") Signed-off-by: Robert Marko [add Fixes:] Signed-off-by: Adrian Schmutzler --- .../boot/dts/marvell/armada-7040-mochabin.dts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/linux/mvebu/files/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts b/target/linux/mvebu/files/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts index 63f4fd5a69..c198061af7 100644 --- a/target/linux/mvebu/files/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts +++ b/target/linux/mvebu/files/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts @@ -235,48 +235,48 @@ reg = <0x64>; led1_red: led@1 { - label = "led1:red"; + label = "red:led1"; reg = <1>; led-max-microamp = <20000>; }; led1_green: led@2 { - label = "led1:green"; + label = "green:led1"; reg = <2>; }; led1_blue: led@3 { - label = "led1:blue"; + label = "blue:led1"; reg = <3>; }; led2_red: led@4 { - label = "led2:red"; + label = "red:led2"; reg = <4>; }; led2_green: led@5 { - label = "led2:green"; + label = "green:led2"; reg = <5>; }; led2_blue: led@6 { - label = "led2:blue"; + label = "blue:led2"; reg = <6>; }; led3_red: led@7 { - label = "led3:red"; + label = "red:led3"; reg = <7>; }; led3_green: led@8 { - label = "led3:green"; + label = "green:led3"; reg = <8>; }; led3_blue: led@9 { - label = "led3:blue"; + label = "blue:led3"; reg = <9>; }; }; From 5ae2e786395c7f9db0167ebe875be5df9502d8d8 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Sun, 22 Aug 2021 14:58:53 +0200 Subject: [PATCH 35/59] kernel: drop support for mtd-mac-address Now that we have fully switched to nvmem interface we can drop the use of mtd-mac-address patches as it's not used anymore and the new nvmem implementation should be used for any new device. Signed-off-by: Ansuel Smith --- ...address-support-to-of_get_mac_addres.patch | 102 ------------------ ...et-add-mac-address-increment-support.patch | 11 +- ...83-of_net-add-mac-address-to-of-tree.patch | 9 +- ...address-support-to-of_get_mac_addres.patch | 102 ------------------ ...et-add-mac-address-increment-support.patch | 11 +- ...83-of_net-add-mac-address-to-of-tree.patch | 9 +- 6 files changed, 16 insertions(+), 228 deletions(-) delete mode 100644 target/linux/generic/pending-5.10/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch delete mode 100644 target/linux/generic/pending-5.4/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch diff --git a/target/linux/generic/pending-5.10/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch b/target/linux/generic/pending-5.10/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch deleted file mode 100644 index 30e292a25d..0000000000 --- a/target/linux/generic/pending-5.10/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 6f8e5369ae054ec6c9265581d5a7e39738a5cd84 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Tue, 30 Mar 2021 13:16:38 +0200 -Subject: [PATCH 1/2] NET: add mtd-mac-address support to of_get_mac_address() - -Many embedded devices have information such as mac addresses stored inside mtd -devices. This patch allows us to add a property inside a node describing a -network interface. The new property points at a mtd partition with an offset -where the mac address can be found. - -Signed-off-by: John Crispin -Signed-off-by: Felix Fietkau -Signed-off-by: Ansuel Smith ---- - drivers/of/of_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 74 insertions(+), 1 deletion(-) - ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - /** - * of_get_phy_mode - Get phy mode for given device_node -@@ -95,6 +96,52 @@ static int of_get_mac_addr_nvmem(struct - return 0; - } - -+static int of_get_mac_address_mtd(struct device_node *np, u8 *addr) -+{ -+#ifdef CONFIG_MTD -+ struct platform_device *pdev = of_find_device_by_node(np); -+ struct device_node *mtd_np = NULL; -+ size_t retlen; -+ int size, ret; -+ struct mtd_info *mtd; -+ const char *part; -+ const __be32 *list; -+ phandle phandle; -+ u8 mac[ETH_ALEN]; -+ -+ list = of_get_property(np, "mtd-mac-address", &size); -+ if (!list || (size != (2 * sizeof(*list)))) -+ return -ENODEV; -+ -+ phandle = be32_to_cpup(list++); -+ if (phandle) -+ mtd_np = of_find_node_by_phandle(phandle); -+ -+ if (!mtd_np) -+ return -ENODEV; -+ -+ part = of_get_property(mtd_np, "label", NULL); -+ if (!part) -+ part = mtd_np->name; -+ -+ mtd = get_mtd_device_nm(part); -+ if (IS_ERR(mtd)) -+ return -ENODEV; -+ -+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac); -+ put_mtd_device(mtd); -+ -+ if (!is_valid_ether_addr(mac)) -+ return -EINVAL; -+ -+ memcpy(addr, mac, ETH_ALEN); -+ -+ return 0; -+#endif -+ return -EINVAL; -+} -+ -+ - /** - * 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 -@@ -115,6 +162,10 @@ 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. - * -+ * -+ * If a mtd-mac-address property exists, try to fetch the MAC address from the -+ * specified mtd device. -+ * - * Return: 0 on success and errno in case of error. - */ - int of_get_mac_address(struct device_node *np, u8 *addr) -@@ -136,6 +187,10 @@ int of_get_mac_address(struct device_nod - if (!ret) - return 0; - -+ ret = of_get_mac_address_mtd(np, addr); -+ if (!ret) -+ return 0; -+ - return of_get_mac_addr_nvmem(np, addr); - } - EXPORT_SYMBOL(of_get_mac_address); diff --git a/target/linux/generic/pending-5.10/682-of_net-add-mac-address-increment-support.patch b/target/linux/generic/pending-5.10/682-of_net-add-mac-address-increment-support.patch index e48e6311c6..cd5cad38f7 100644 --- a/target/linux/generic/pending-5.10/682-of_net-add-mac-address-increment-support.patch +++ b/target/linux/generic/pending-5.10/682-of_net-add-mac-address-increment-support.patch @@ -20,9 +20,9 @@ Signed-off-by: Ansuel Smith --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c -@@ -166,31 +166,56 @@ static int of_get_mac_address_mtd(struct - * If a mtd-mac-address property exists, try to fetch the MAC address from the - * specified mtd device. +@@ -115,27 +115,52 @@ 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: @@ -63,11 +63,6 @@ Signed-off-by: Ansuel Smith ret = of_get_mac_addr(np, "address", addr); if (!ret) - return 0; -+ goto found; - - ret = of_get_mac_address_mtd(np, addr); - if (!ret) -- return 0; + goto found; + + ret = of_get_mac_addr_nvmem(np, addr); diff --git a/target/linux/generic/pending-5.10/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-5.10/683-of_net-add-mac-address-to-of-tree.patch index 02f7519f74..0cb96025cf 100644 --- a/target/linux/generic/pending-5.10/683-of_net-add-mac-address-to-of-tree.patch +++ b/target/linux/generic/pending-5.10/683-of_net-add-mac-address-to-of-tree.patch @@ -1,7 +1,7 @@ --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c -@@ -141,6 +141,26 @@ static int of_get_mac_address_mtd(struct - return -EINVAL; +@@ -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) @@ -24,10 +24,11 @@ + kfree(prop); + return -ENOMEM; +} - ++ /** * Search the device tree for the best MAC address to use. 'mac-address' is -@@ -216,6 +236,7 @@ found: + * checked first, because that is supposed to contain to "most recent" MAC +@@ -161,6 +182,7 @@ found: if (!of_property_read_u32(np, "mac-address-increment", &mac_inc)) addr[inc_idx] += mac_inc; diff --git a/target/linux/generic/pending-5.4/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch b/target/linux/generic/pending-5.4/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch deleted file mode 100644 index a9e06cdfe1..0000000000 --- a/target/linux/generic/pending-5.4/681-NET-add-mtd-mac-address-support-to-of_get_mac_addres.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 6f8e5369ae054ec6c9265581d5a7e39738a5cd84 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Tue, 30 Mar 2021 13:16:38 +0200 -Subject: [PATCH 1/2] NET: add mtd-mac-address support to of_get_mac_address() - -Many embedded devices have information such as mac addresses stored inside mtd -devices. This patch allows us to add a property inside a node describing a -network interface. The new property points at a mtd partition with an offset -where the mac address can be found. - -Signed-off-by: John Crispin -Signed-off-by: Felix Fietkau -Signed-off-by: Ansuel Smith ---- - drivers/of/of_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 74 insertions(+), 1 deletion(-) - ---- a/drivers/of/of_net.c -+++ b/drivers/of/of_net.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - /** - * of_get_phy_mode - Get phy mode for given device_node -@@ -89,6 +90,52 @@ static int of_get_mac_addr_nvmem(struct - return 0; - } - -+static int of_get_mac_address_mtd(struct device_node *np, u8 *addr) -+{ -+#ifdef CONFIG_MTD -+ struct platform_device *pdev = of_find_device_by_node(np); -+ struct device_node *mtd_np = NULL; -+ size_t retlen; -+ int size, ret; -+ struct mtd_info *mtd; -+ const char *part; -+ const __be32 *list; -+ phandle phandle; -+ u8 mac[ETH_ALEN]; -+ -+ list = of_get_property(np, "mtd-mac-address", &size); -+ if (!list || (size != (2 * sizeof(*list)))) -+ return -ENODEV; -+ -+ phandle = be32_to_cpup(list++); -+ if (phandle) -+ mtd_np = of_find_node_by_phandle(phandle); -+ -+ if (!mtd_np) -+ return -ENODEV; -+ -+ part = of_get_property(mtd_np, "label", NULL); -+ if (!part) -+ part = mtd_np->name; -+ -+ mtd = get_mtd_device_nm(part); -+ if (IS_ERR(mtd)) -+ return -ENODEV; -+ -+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac); -+ put_mtd_device(mtd); -+ -+ if (!is_valid_ether_addr(mac)) -+ return -EINVAL; -+ -+ memcpy(addr, mac, ETH_ALEN); -+ -+ return 0; -+#endif -+ return -EINVAL; -+} -+ -+ - /** - * 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 -@@ -109,6 +156,10 @@ 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. - * -+ * -+ * If a mtd-mac-address property exists, try to fetch the MAC address from the -+ * specified mtd device. -+ * - * Return: 0 on success and errno in case of error. - */ - int of_get_mac_address(struct device_node *np, u8 *addr) -@@ -130,6 +181,10 @@ int of_get_mac_address(struct device_nod - if (!ret) - return 0; - -+ ret = of_get_mac_address_mtd(np, addr); -+ if (!ret) -+ return 0; -+ - return of_get_mac_addr_nvmem(np, addr); - } - EXPORT_SYMBOL(of_get_mac_address); diff --git a/target/linux/generic/pending-5.4/682-of_net-add-mac-address-increment-support.patch b/target/linux/generic/pending-5.4/682-of_net-add-mac-address-increment-support.patch index 35c717ca51..acc7eaf47b 100644 --- a/target/linux/generic/pending-5.4/682-of_net-add-mac-address-increment-support.patch +++ b/target/linux/generic/pending-5.4/682-of_net-add-mac-address-increment-support.patch @@ -20,9 +20,9 @@ Signed-off-by: Ansuel Smith --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c -@@ -160,31 +160,56 @@ static int of_get_mac_address_mtd(struct - * If a mtd-mac-address property exists, try to fetch the MAC address from the - * specified mtd device. +@@ -109,27 +109,52 @@ 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: @@ -63,11 +63,6 @@ Signed-off-by: Ansuel Smith ret = of_get_mac_addr(np, "address", addr); if (!ret) - return 0; -+ goto found; - - ret = of_get_mac_address_mtd(np, addr); - if (!ret) -- return 0; + goto found; + + ret = of_get_mac_addr_nvmem(np, addr); diff --git a/target/linux/generic/pending-5.4/683-of_net-add-mac-address-to-of-tree.patch b/target/linux/generic/pending-5.4/683-of_net-add-mac-address-to-of-tree.patch index ea5883f037..78514dd9e3 100644 --- a/target/linux/generic/pending-5.4/683-of_net-add-mac-address-to-of-tree.patch +++ b/target/linux/generic/pending-5.4/683-of_net-add-mac-address-to-of-tree.patch @@ -1,7 +1,7 @@ --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c -@@ -135,6 +135,26 @@ static int of_get_mac_address_mtd(struct - return -EINVAL; +@@ -89,6 +89,27 @@ static int of_get_mac_addr_nvmem(struct + return 0; } +static int of_add_mac_address(struct device_node *np, u8* addr) @@ -24,10 +24,11 @@ + kfree(prop); + return -ENOMEM; +} - ++ /** * Search the device tree for the best MAC address to use. 'mac-address' is -@@ -210,6 +230,7 @@ found: + * checked first, because that is supposed to contain to "most recent" MAC +@@ -155,6 +176,7 @@ found: if (!of_property_read_u32(np, "mac-address-increment", &mac_inc)) addr[inc_idx] += mac_inc; From 0c2aa7c003ebf61d64e0b349a18731b6bda05023 Mon Sep 17 00:00:00 2001 From: Adrian Schmutzler Date: Sun, 10 Oct 2021 00:51:39 +0200 Subject: [PATCH 36/59] rockchip: switch to kernel 5.10 This target has testing support for more than half a year now. Time to switch. Signed-off-by: Adrian Schmutzler --- target/linux/rockchip/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/rockchip/Makefile b/target/linux/rockchip/Makefile index f7b6995911..0245f02eac 100644 --- a/target/linux/rockchip/Makefile +++ b/target/linux/rockchip/Makefile @@ -7,8 +7,7 @@ BOARDNAME:=Rockchip FEATURES:=ext4 audio usb usbgadget display gpio fpu pci pcie rootfs-part boot-part squashfs SUBTARGETS:=armv8 -KERNEL_PATCHVER=5.4 -KERNEL_TESTING_PATCHVER=5.10 +KERNEL_PATCHVER=5.10 define Target/Description Build firmware image for Rockchip SoC devices. From 91eed5d9fb74e6c740291362ba12e11a2222a9fd Mon Sep 17 00:00:00 2001 From: Adrian Schmutzler Date: Sat, 2 Oct 2021 17:36:48 +0200 Subject: [PATCH 37/59] rockchip: rename "Rock Pi 4" to "Rock Pi 4A" Kernel has added the different variants of the Rock Pi 4 in commit b5edb0467370 ("arm64: dts: rockchip: Mark rock-pi-4 as rock-pi-4a dts"). The former Rock Pi 4 is now Rock Pi 4A. For compatibility with kernel 5.4, this rename has been held back so far. Having switched to kernel 5.10 now, we can finally apply it in our tree as well. Signed-off-by: Adrian Schmutzler --- package/boot/uboot-rockchip/Makefile | 2 +- .../boot/dts/rockchip/rk3399-rock-pi-4.dts | 19 ------------------- target/linux/rockchip/image/armv8.mk | 8 ++++---- .../patches-5.10/105-rockchip-rock-pi-4.patch | 10 ---------- 4 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 target/linux/rockchip/files-5.10/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts delete mode 100644 target/linux/rockchip/patches-5.10/105-rockchip-rock-pi-4.patch diff --git a/package/boot/uboot-rockchip/Makefile b/package/boot/uboot-rockchip/Makefile index f419ec6ca7..b886ef0122 100644 --- a/package/boot/uboot-rockchip/Makefile +++ b/package/boot/uboot-rockchip/Makefile @@ -52,7 +52,7 @@ define U-Boot/rock-pi-4-rk3399 BUILD_SUBTARGET:=armv8 NAME:=Rock Pi 4 BUILD_DEVICES:= \ - radxa_rock-pi-4 + radxa_rock-pi-4a DEPENDS:=+PACKAGE_u-boot-rock-pi-4-rk3399:arm-trusted-firmware-rockchip PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip ATF:=rk3399_bl31.elf diff --git a/target/linux/rockchip/files-5.10/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/target/linux/rockchip/files-5.10/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts deleted file mode 100644 index f6e7710a01..0000000000 --- a/target/linux/rockchip/files-5.10/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2019 Akash Gajjar - * Copyright (c) 2019 Pragnesh Patel - */ - -/* TODO - * Delete this file and migrate RockPi 4 to RockPi 4A after - * removing Kernel 5.4. - */ - - -/dts-v1/; -#include "rk3399-rock-pi-4.dtsi" - -/ { - model = "Radxa ROCK Pi 4"; - compatible = "radxa,rockpi4", "rockchip,rk3399"; -}; diff --git a/target/linux/rockchip/image/armv8.mk b/target/linux/rockchip/image/armv8.mk index ee411d266b..6cc31f1d8c 100644 --- a/target/linux/rockchip/image/armv8.mk +++ b/target/linux/rockchip/image/armv8.mk @@ -32,12 +32,12 @@ define Device/pine64_rockpro64 endef TARGET_DEVICES += pine64_rockpro64 -define Device/radxa_rock-pi-4 +define Device/radxa_rock-pi-4a DEVICE_VENDOR := Radxa - DEVICE_MODEL := ROCK Pi 4 + DEVICE_MODEL := ROCK Pi 4A SOC := rk3399 - SUPPORTED_DEVICES := radxa,rockpi4 + SUPPORTED_DEVICES := radxa,rockpi4a radxa,rockpi4 UBOOT_DEVICE_NAME := rock-pi-4-rk3399 IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata endef -TARGET_DEVICES += radxa_rock-pi-4 +TARGET_DEVICES += radxa_rock-pi-4a diff --git a/target/linux/rockchip/patches-5.10/105-rockchip-rock-pi-4.patch b/target/linux/rockchip/patches-5.10/105-rockchip-rock-pi-4.patch deleted file mode 100644 index 404f64ab95..0000000000 --- a/target/linux/rockchip/patches-5.10/105-rockchip-rock-pi-4.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm64/boot/dts/rockchip/Makefile -+++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -36,6 +36,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-pi - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc-mezzanine.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4a.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4b.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4c.dtb From 20bc4507714fbc5dfbe3632afeb260b071591acb Mon Sep 17 00:00:00 2001 From: John Audia Date: Wed, 6 Oct 2021 11:38:15 -0400 Subject: [PATCH 38/59] kernel: bump 5.10 to 5.10.71 All patches automatically rebased. Build system: x86_64 Build-tested: bcm2711/RPi4B, ipq806x/R7800 Run-tested: bcm2711/RPi4B, ipq806x/R7800 Signed-off-by: John Audia --- include/kernel-version.mk | 4 ++-- .../patches-5.10/910-unaligned_access_hacks.patch | 2 +- ...0006-smsx95xx-fix-crimes-against-truesize.patch | 4 ++-- ...-Pass-the-full-state-to-CRTC-atomic_check.patch | 4 ++-- ...or-Create-a-helper-to-attach-the-hdr_outp.patch | 2 +- ...nector-Add-helper-to-compare-HDR-metadata.patch | 4 ++-- ...0-0689-drm-automatic-legacy-gamma-support.patch | 2 +- .../generic/hack-5.10/901-debloat_sock_diag.patch | 2 +- .../linux/generic/hack-5.10/902-debloat_proc.patch | 2 +- ...jecting-with-source-address-failed-policy.patch | 14 +++++++------- .../760-net-dsa-mv88e6xxx-fix-vlan-setup.patch | 2 +- ...xxx-Request-assisted-learning-on-CPU-port.patch | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 75a1f5f313..caca1d6411 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .150 -LINUX_VERSION-5.10 = .70 +LINUX_VERSION-5.10 = .71 LINUX_KERNEL_HASH-5.4.150 = f424a9bbb05007f04c17f96a2e4f041a8001554a9060d2c291606e8a97c62aa2 -LINUX_KERNEL_HASH-5.10.70 = 75736c33711d7f298889ee4981b18774882045323e5c46af9ad3b022082db232 +LINUX_KERNEL_HASH-5.10.71 = 02e688d27d963f0325f5cd30e383329cf00ab23db46d1586d6e848e3f992a497 remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/target/linux/ath79/patches-5.10/910-unaligned_access_hacks.patch b/target/linux/ath79/patches-5.10/910-unaligned_access_hacks.patch index 338b96447d..1ade1e9181 100644 --- a/target/linux/ath79/patches-5.10/910-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-5.10/910-unaligned_access_hacks.patch @@ -171,7 +171,7 @@ #define UDP_CORK 1 /* Never send partially complete segments */ --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c -@@ -268,8 +268,8 @@ nf_ct_get_tuple(const struct sk_buff *sk +@@ -271,8 +271,8 @@ nf_ct_get_tuple(const struct sk_buff *sk switch (l3num) { case NFPROTO_IPV4: 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 163dd76e1c..a12202d55e 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) { -@@ -1827,7 +1831,8 @@ static int smsc95xx_rx_fixup(struct usbn +@@ -1830,7 +1834,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; } -@@ -1845,7 +1850,8 @@ static int smsc95xx_rx_fixup(struct usbn +@@ -1848,7 +1853,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-0409-drm-atomic-Pass-the-full-state-to-CRTC-atomic_check.patch b/target/linux/bcm27xx/patches-5.10/950-0409-drm-atomic-Pass-the-full-state-to-CRTC-atomic_check.patch index 5724b865c7..df4209f047 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0409-drm-atomic-Pass-the-full-state-to-CRTC-atomic_check.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0409-drm-atomic-Pass-the-full-state-to-CRTC-atomic_check.patch @@ -201,7 +201,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/20201028123222.1732139-1-max --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -5601,17 +5601,19 @@ static void dm_update_crtc_active_planes +@@ -5602,17 +5602,19 @@ static void dm_update_crtc_active_planes } static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, @@ -225,7 +225,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/20201028123222.1732139-1-max WARN_ON(1); return ret; } -@@ -5622,8 +5624,8 @@ static int dm_crtc_helper_atomic_check(s +@@ -5623,8 +5625,8 @@ static int dm_crtc_helper_atomic_check(s * planes are disabled, which is not supported by the hardware. And there is legacy * userspace which stops using the HW cursor altogether in response to the resulting EINVAL. */ diff --git a/target/linux/bcm27xx/patches-5.10/950-0527-drm-connector-Create-a-helper-to-attach-the-hdr_outp.patch b/target/linux/bcm27xx/patches-5.10/950-0527-drm-connector-Create-a-helper-to-attach-the-hdr_outp.patch index 7799301d98..ea71da185f 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0527-drm-connector-Create-a-helper-to-attach-the-hdr_outp.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0527-drm-connector-Create-a-helper-to-attach-the-hdr_outp.patch @@ -22,7 +22,7 @@ Signed-off-by: Maxime Ripard --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -6524,9 +6524,7 @@ void amdgpu_dm_connector_init_helper(str +@@ -6525,9 +6525,7 @@ void amdgpu_dm_connector_init_helper(str if (connector_type == DRM_MODE_CONNECTOR_HDMIA || connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP) { diff --git a/target/linux/bcm27xx/patches-5.10/950-0528-drm-connector-Add-helper-to-compare-HDR-metadata.patch b/target/linux/bcm27xx/patches-5.10/950-0528-drm-connector-Add-helper-to-compare-HDR-metadata.patch index e9f664132e..00e8200e53 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0528-drm-connector-Add-helper-to-compare-HDR-metadata.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0528-drm-connector-Add-helper-to-compare-HDR-metadata.patch @@ -21,7 +21,7 @@ Signed-off-by: Maxime Ripard --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -5472,25 +5472,6 @@ static int fill_hdr_info_packet(const st +@@ -5473,25 +5473,6 @@ static int fill_hdr_info_packet(const st return 0; } @@ -47,7 +47,7 @@ Signed-off-by: Maxime Ripard static int amdgpu_dm_connector_atomic_check(struct drm_connector *conn, struct drm_atomic_state *state) -@@ -5506,7 +5487,7 @@ amdgpu_dm_connector_atomic_check(struct +@@ -5507,7 +5488,7 @@ amdgpu_dm_connector_atomic_check(struct if (!crtc) return 0; diff --git a/target/linux/bcm27xx/patches-5.10/950-0689-drm-automatic-legacy-gamma-support.patch b/target/linux/bcm27xx/patches-5.10/950-0689-drm-automatic-legacy-gamma-support.patch index b1cb34e485..d7e598691d 100644 --- a/target/linux/bcm27xx/patches-5.10/950-0689-drm-automatic-legacy-gamma-support.patch +++ b/target/linux/bcm27xx/patches-5.10/950-0689-drm-automatic-legacy-gamma-support.patch @@ -42,7 +42,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/20201211114237.213288-2-tomi --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -4988,7 +4988,6 @@ static void dm_disable_vblank(struct drm +@@ -4989,7 +4989,6 @@ static void dm_disable_vblank(struct drm static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = dm_crtc_reset_state, .destroy = amdgpu_dm_crtc_destroy, diff --git a/target/linux/generic/hack-5.10/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.10/901-debloat_sock_diag.patch index 88895b4572..78446d38c4 100644 --- a/target/linux/generic/hack-5.10/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-5.10/901-debloat_sock_diag.patch @@ -77,7 +77,7 @@ Signed-off-by: Felix Fietkau struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) { struct dst_entry *dst = __sk_dst_get(sk); -@@ -1816,9 +1830,11 @@ static void __sk_free(struct sock *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); diff --git a/target/linux/generic/hack-5.10/902-debloat_proc.patch b/target/linux/generic/hack-5.10/902-debloat_proc.patch index 6f7a1876cd..e84b6d1787 100644 --- a/target/linux/generic/hack-5.10/902-debloat_proc.patch +++ b/target/linux/generic/hack-5.10/902-debloat_proc.patch @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -3682,6 +3682,8 @@ static __net_initdata struct pernet_oper +@@ -3702,6 +3702,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/pending-5.10/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.10/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index ebff78a192..2daf1c9641 100644 --- a/target/linux/generic/pending-5.10/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.10/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6079,6 +6110,8 @@ static int ip6_route_dev_notify(struct n +@@ -6080,6 +6111,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 -@@ -6090,6 +6123,7 @@ static int ip6_route_dev_notify(struct n +@@ -6091,6 +6124,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 } -@@ -6281,6 +6315,8 @@ static int __net_init ip6_route_net_init +@@ -6282,6 +6316,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); -@@ -6291,11 +6327,21 @@ static int __net_init ip6_route_net_init +@@ -6292,11 +6328,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); -@@ -6322,6 +6368,8 @@ out: +@@ -6323,6 +6369,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: -@@ -6341,6 +6389,7 @@ static void __net_exit ip6_route_net_exi +@@ -6342,6 +6390,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); -@@ -6418,6 +6467,9 @@ void __init ip6_route_init_special_entri +@@ -6419,6 +6468,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.10/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch b/target/linux/generic/pending-5.10/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch index 42b91fe4c3..f961dc9e56 100644 --- a/target/linux/generic/pending-5.10/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch +++ b/target/linux/generic/pending-5.10/760-net-dsa-mv88e6xxx-fix-vlan-setup.patch @@ -17,7 +17,7 @@ Signed-off-by: DENG Qingfang --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -2857,6 +2857,7 @@ static int mv88e6xxx_setup(struct dsa_sw +@@ -2860,6 +2860,7 @@ static int mv88e6xxx_setup(struct dsa_sw chip->ds = ds; ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); diff --git a/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch index f7ebbd9ae6..493d412249 100644 --- a/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +++ b/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -17,7 +17,7 @@ Signed-off-by: Tobias Waldekranz --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -5419,6 +5419,7 @@ static int mv88e6xxx_register_switch(str +@@ -5422,6 +5422,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; From e672d1b387604b71058b5c9edc9234fc7efebb25 Mon Sep 17 00:00:00 2001 From: John Audia Date: Sat, 9 Oct 2021 12:22:14 -0400 Subject: [PATCH 39/59] kernel: bump 5.10 to 5.10.72 All patches automatically rebased. Build system: x86_64 Build-tested: bcm2711/RPi4B Run-tested: bcm2711/RPi4B Signed-off-by: John Audia --- include/kernel-version.mk | 4 ++-- .../generic/hack-5.10/720-net-phy-add-aqr-phys.patch | 10 +++++----- .../generic/pending-5.10/834-ledtrig-libata.patch | 10 +++++----- target/linux/oxnas/patches-5.10/999-libata-hacks.patch | 8 ++++---- .../306-gpio-add-legacy-rtl838x-driver.patch | 4 ++-- .../704-include-linux-add-phy-hsgmii-mode.patch | 8 ++++---- ...x-phy-increase-phy-address-number-for-rtl839x.patch | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index caca1d6411..0325cf318d 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .150 -LINUX_VERSION-5.10 = .71 +LINUX_VERSION-5.10 = .72 LINUX_KERNEL_HASH-5.4.150 = f424a9bbb05007f04c17f96a2e4f041a8001554a9060d2c291606e8a97c62aa2 -LINUX_KERNEL_HASH-5.10.71 = 02e688d27d963f0325f5cd30e383329cf00ab23db46d1586d6e848e3f992a497 +LINUX_KERNEL_HASH-5.10.72 = b4d635afe7646ac6a6617c738e747ba0a6006675cd9735d18f672f8b1fba4c7c remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/target/linux/generic/hack-5.10/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.10/720-net-phy-add-aqr-phys.patch index 73afb245b4..4d4420aa2f 100644 --- a/target/linux/generic/hack-5.10/720-net-phy-add-aqr-phys.patch +++ b/target/linux/generic/hack-5.10/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 @@ +@@ -330,6 +332,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 @@ +@@ -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); @@ -79,7 +79,7 @@ Signed-off-by: Birger Koblitz fw_major, fw_minor, build_id, prov_id); } -@@ -632,6 +677,24 @@ +@@ -632,6 +677,24 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { @@ -104,7 +104,7 @@ Signed-off-by: Birger Koblitz PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), .name = "Aquantia AQCS109", .probe = aqr107_probe, -@@ -657,6 +720,24 @@ +@@ -657,6 +720,24 @@ static struct phy_driver aqr_driver[] = .ack_interrupt = aqr_ack_interrupt, .read_status = aqr_read_status, }, @@ -129,7 +129,7 @@ Signed-off-by: Birger Koblitz }; module_phy_driver(aqr_driver); -@@ -667,8 +748,10 @@ +@@ -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) }, diff --git a/target/linux/generic/pending-5.10/834-ledtrig-libata.patch b/target/linux/generic/pending-5.10/834-ledtrig-libata.patch index 107f2c4914..fddec74d96 100644 --- a/target/linux/generic/pending-5.10/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-5.10/834-ledtrig-libata.patch @@ -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 -@@ -4517,6 +4530,9 @@ struct ata_queued_cmd *ata_qc_new_init(s +@@ -4545,6 +4558,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; -@@ -5295,6 +5311,9 @@ struct ata_port *ata_port_alloc(struct a +@@ -5323,6 +5339,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; -@@ -5330,6 +5349,12 @@ static void ata_host_release(struct kref +@@ -5358,6 +5377,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; } -@@ -5736,7 +5761,23 @@ int ata_host_register(struct ata_host *h +@@ -5764,7 +5789,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 { +@@ -883,6 +886,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/oxnas/patches-5.10/999-libata-hacks.patch b/target/linux/oxnas/patches-5.10/999-libata-hacks.patch index 2751c9fe88..e34891cbb6 100644 --- a/target/linux/oxnas/patches-5.10/999-libata-hacks.patch +++ b/target/linux/oxnas/patches-5.10/999-libata-hacks.patch @@ -15,7 +15,7 @@ /* initialize internal qc */ qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL); -@@ -4524,6 +4532,9 @@ struct ata_queued_cmd *ata_qc_new_init(s +@@ -4552,6 +4560,9 @@ struct ata_queued_cmd *ata_qc_new_init(s if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) return NULL; @@ -25,7 +25,7 @@ /* libsas case */ if (ap->flags & ATA_FLAG_SAS_HOST) { tag = ata_sas_allocate_tag(ap); -@@ -4569,6 +4580,8 @@ void ata_qc_free(struct ata_queued_cmd * +@@ -4597,6 +4608,8 @@ void ata_qc_free(struct ata_queued_cmd * qc->tag = ATA_TAG_POISON; if (ap->flags & ATA_FLAG_SAS_HOST) ata_sas_free_tag(tag, ap); @@ -36,7 +36,7 @@ --- a/include/linux/libata.h +++ b/include/linux/libata.h -@@ -911,6 +911,8 @@ struct ata_port_operations { +@@ -912,6 +912,8 @@ struct ata_port_operations { enum ata_completion_errors (*qc_prep)(struct ata_queued_cmd *qc); unsigned int (*qc_issue)(struct ata_queued_cmd *qc); bool (*qc_fill_rtf)(struct ata_queued_cmd *qc); @@ -45,7 +45,7 @@ /* * Configuration and exception handling -@@ -1001,6 +1003,9 @@ struct ata_port_operations { +@@ -1002,6 +1004,9 @@ struct ata_port_operations { void (*phy_reset)(struct ata_port *ap); void (*eng_timeout)(struct ata_port *ap); diff --git a/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch b/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch index 830440cf8d..1ea8add32b 100644 --- a/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch +++ b/target/linux/realtek/patches-5.10/306-gpio-add-legacy-rtl838x-driver.patch @@ -1,6 +1,6 @@ --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -514,6 +514,12 @@ +@@ -514,6 +514,12 @@ config GPIO_RTL8231 help Say yes here to support Realtek RTL8231 GPIO expansion chips. @@ -15,7 +15,7 @@ depends on MFD_SYSCON --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -127,6 +127,7 @@ +@@ -127,6 +127,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc3 obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o obj-$(CONFIG_GPIO_REG) += gpio-reg.o obj-$(CONFIG_GPIO_RTL8231) += gpio-rtl8231.o diff --git a/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch b/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch index 9a61a70c44..d47e7bad50 100644 --- a/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch +++ b/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch @@ -1,15 +1,15 @@ --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -93,6 +93,7 @@ - PHY_INTERFACE_MODE_SMII, +@@ -133,6 +133,7 @@ typedef enum { PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, PHY_INTERFACE_MODE_MOCA, + PHY_INTERFACE_MODE_HSGMII, PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_TRGMII, PHY_INTERFACE_MODE_1000BASEX, -@@ -163,6 +164,8 @@ - return "xgmii"; +@@ -199,6 +200,8 @@ static inline const char *phy_modes(phy_ + return "xlgmii"; case PHY_INTERFACE_MODE_MOCA: return "moca"; + case PHY_INTERFACE_MODE_HSGMII: diff --git a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch index d36299d43b..64e6b5d309 100644 --- a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch +++ b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch @@ -1,6 +1,6 @@ --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -226,7 +226,7 @@ static inline const char *phy_modes(phy_ +@@ -229,7 +229,7 @@ static inline const char *phy_modes(phy_ #define PHY_INIT_TIMEOUT 100000 #define PHY_FORCE_TIMEOUT 10 From 416eef7209f3d7c7ab27c90dc4d851d78fff2d44 Mon Sep 17 00:00:00 2001 From: John Audia Date: Thu, 7 Oct 2021 06:24:12 -0400 Subject: [PATCH 40/59] kernel: bump 5.4 to 5.4.151 All patches automatically rebased. Signed-off-by: John Audia --- include/kernel-version.mk | 4 ++-- .../generic/hack-5.4/901-debloat_sock_diag.patch | 2 +- .../linux/generic/hack-5.4/902-debloat_proc.patch | 2 +- ...jecting-with-source-address-failed-policy.patch | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 0325cf318d..5c9b5256ae 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -6,10 +6,10 @@ ifdef CONFIG_TESTING_KERNEL KERNEL_PATCHVER:=$(KERNEL_TESTING_PATCHVER) endif -LINUX_VERSION-5.4 = .150 +LINUX_VERSION-5.4 = .151 LINUX_VERSION-5.10 = .72 -LINUX_KERNEL_HASH-5.4.150 = f424a9bbb05007f04c17f96a2e4f041a8001554a9060d2c291606e8a97c62aa2 +LINUX_KERNEL_HASH-5.4.151 = bbe73fb83c31a6a7269de85b6b2bbd54dd31e6613f4edab20bb7a6f37cf53313 LINUX_KERNEL_HASH-5.10.72 = b4d635afe7646ac6a6617c738e747ba0a6006675cd9735d18f672f8b1fba4c7c remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) diff --git a/target/linux/generic/hack-5.4/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.4/901-debloat_sock_diag.patch index 7c9046c6e3..0abb672639 100644 --- a/target/linux/generic/hack-5.4/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-5.4/901-debloat_sock_diag.patch @@ -69,7 +69,7 @@ Signed-off-by: Felix Fietkau struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) { struct dst_entry *dst = __sk_dst_get(sk); -@@ -1742,9 +1755,11 @@ static void __sk_free(struct sock *sk) +@@ -1760,9 +1773,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.4/902-debloat_proc.patch b/target/linux/generic/hack-5.4/902-debloat_proc.patch index f8ee3f083b..042588a623 100644 --- a/target/linux/generic/hack-5.4/902-debloat_proc.patch +++ b/target/linux/generic/hack-5.4/902-debloat_proc.patch @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -3623,6 +3623,8 @@ static __net_initdata struct pernet_oper +@@ -3643,6 +3643,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/pending-5.4/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.4/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index c7053fc686..0b95eee494 100644 --- a/target/linux/generic/pending-5.4/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.4/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6028,6 +6059,8 @@ static int ip6_route_dev_notify(struct n +@@ -6029,6 +6060,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 -@@ -6039,6 +6072,7 @@ static int ip6_route_dev_notify(struct n +@@ -6040,6 +6073,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 } -@@ -6231,6 +6265,8 @@ static int __net_init ip6_route_net_init +@@ -6232,6 +6266,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); -@@ -6241,11 +6277,21 @@ static int __net_init ip6_route_net_init +@@ -6242,11 +6278,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); -@@ -6269,6 +6315,8 @@ out: +@@ -6270,6 +6316,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: -@@ -6288,6 +6336,7 @@ static void __net_exit ip6_route_net_exi +@@ -6289,6 +6337,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); -@@ -6365,6 +6414,9 @@ void __init ip6_route_init_special_entri +@@ -6366,6 +6415,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); From b5893a4128ad0c8551c051f563b8e451c3331820 Mon Sep 17 00:00:00 2001 From: John Audia Date: Sat, 9 Oct 2021 13:44:30 -0400 Subject: [PATCH 41/59] kernel: bump 5.4 to 5.4.152 All patches automatically rebased. Signed-off-by: John Audia --- include/kernel-version.mk | 4 ++-- .../linux/generic/pending-5.4/834-ledtrig-libata.patch | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 5c9b5256ae..734dbeda92 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -6,10 +6,10 @@ ifdef CONFIG_TESTING_KERNEL KERNEL_PATCHVER:=$(KERNEL_TESTING_PATCHVER) endif -LINUX_VERSION-5.4 = .151 +LINUX_VERSION-5.4 = .152 LINUX_VERSION-5.10 = .72 -LINUX_KERNEL_HASH-5.4.151 = bbe73fb83c31a6a7269de85b6b2bbd54dd31e6613f4edab20bb7a6f37cf53313 +LINUX_KERNEL_HASH-5.4.152 = 8044c7134c5eed21af9662f1c5399a5d8781b5bc2d8979e9ad06b4435a0a5ed5 LINUX_KERNEL_HASH-5.10.72 = b4d635afe7646ac6a6617c738e747ba0a6006675cd9735d18f672f8b1fba4c7c remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) diff --git a/target/linux/generic/pending-5.4/834-ledtrig-libata.patch b/target/linux/generic/pending-5.4/834-ledtrig-libata.patch index cb049af0a5..f33ceec126 100644 --- a/target/linux/generic/pending-5.4/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-5.4/834-ledtrig-libata.patch @@ -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 -@@ -5121,6 +5134,9 @@ struct ata_queued_cmd *ata_qc_new_init(s +@@ -5149,6 +5162,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; -@@ -6057,6 +6073,9 @@ struct ata_port *ata_port_alloc(struct a +@@ -6085,6 +6101,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; -@@ -6092,6 +6111,12 @@ static void ata_host_release(struct kref +@@ -6120,6 +6139,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; } -@@ -6555,7 +6580,23 @@ int ata_host_register(struct ata_host *h +@@ -6583,7 +6608,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 -@@ -881,6 +884,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 From 56ea2bf2eec431ccd3c566190a444ad63db39b65 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 9 Oct 2021 23:09:46 -1000 Subject: [PATCH 42/59] build: prereq detect Python 3.10 for `python3` binary While the binary `python3.10` is correctly detected by the build system the default `python3` binary is currently not detected if pointing to a Python 3.10 installation. Fix this by extending the grep regex. Signed-off-by: Paul Spooren --- include/prereq-build.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/prereq-build.mk b/include/prereq-build.mk index e1993444f7..ce6873cf52 100644 --- a/include/prereq-build.mk +++ b/include/prereq-build.mk @@ -162,7 +162,7 @@ $(eval $(call SetupHostCommand,python,Please install Python >= 3.6, \ python3.8 -V 2>&1 | grep 'Python 3', \ python3.7 -V 2>&1 | grep 'Python 3', \ python3.6 -V 2>&1 | grep 'Python 3', \ - python3 -V 2>&1 | grep -E 'Python 3\.[6-9]\.?')) + python3 -V 2>&1 | grep -E 'Python 3\.([6-9]|10)\.?')) $(eval $(call SetupHostCommand,python3,Please install Python >= 3.6, \ python3.10 -V 2>&1 | grep 'Python 3', \ @@ -170,7 +170,7 @@ $(eval $(call SetupHostCommand,python3,Please install Python >= 3.6, \ python3.8 -V 2>&1 | grep 'Python 3', \ python3.7 -V 2>&1 | grep 'Python 3', \ python3.6 -V 2>&1 | grep 'Python 3', \ - python3 -V 2>&1 | grep -E 'Python 3\.[6-9]\.?')) + python3 -V 2>&1 | grep -E 'Python 3\.([6-9]|10)\.?')) $(eval $(call TestHostCommand,python3-distutils, \ Please install the Python3 distutils module, \ From 2a6cab09b940aa3b0176147f74ad5d3c69660a4b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 3 Oct 2021 00:59:31 +0200 Subject: [PATCH 43/59] apm821xx: move CONFIG_DMA* to the generic apm821xx config Both NAND and SATA targets need the DMA engine in one way or another. Due to a kernel config refresh various existing symbols got removed from the apm821xx main config file as well. (That being said, they are still included because the built-in crpyto4xx depends on these.) Signed-off-by: Christian Lamparter --- target/linux/apm821xx/config-5.10 | 29 +++++++---------------- target/linux/apm821xx/nand/config-default | 5 ---- target/linux/apm821xx/sata/config-default | 5 ---- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/target/linux/apm821xx/config-5.10 b/target/linux/apm821xx/config-5.10 index b729bee903..bb9753d0b4 100644 --- a/target/linux/apm821xx/config-5.10 +++ b/target/linux/apm821xx/config-5.10 @@ -1,11 +1,10 @@ # CONFIG_40x is not set CONFIG_44x=y -CONFIG_460EX=y CONFIG_4xx=y CONFIG_4xx_SOC=y # CONFIG_ADVANCED_OPTIONS is not set CONFIG_APM821xx=y -CONFIG_APOLLO3G=y +# CONFIG_APOLLO3G is not set # CONFIG_ARCHES is not set CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y @@ -41,13 +40,8 @@ CONFIG_CPU_BIG_ENDIAN=y CONFIG_CRC16=y # CONFIG_CRC32_SARWATE is not set CONFIG_CRC32_SLICEBY8=y -CONFIG_CRYPTO_ACOMP2=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_CCM=y CONFIG_CRYPTO_CFB=y -CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DEV_PPC4XX=y CONFIG_CRYPTO_DRBG=y @@ -55,20 +49,14 @@ CONFIG_CRYPTO_DRBG_HMAC=y CONFIG_CRYPTO_DRBG_MENU=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_ESSIV=y -CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_GHASH=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HW=y CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 CONFIG_CRYPTO_LIB_SHA256=y CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y CONFIG_CRYPTO_MD5_PPC=y -CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_OFB=y CONFIG_CRYPTO_RNG=y @@ -79,9 +67,14 @@ CONFIG_CRYPTO_SHA1_PPC=y CONFIG_CRYPTO_SHA256=y CONFIG_DATA_SHIFT=12 CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y CONFIG_DMA_REMAP=y CONFIG_DTC=y +CONFIG_DW_DMAC=y +CONFIG_DW_DMAC_CORE=y # CONFIG_E200 is not set CONFIG_EARLY_PRINTK=y # CONFIG_EBONY is not set @@ -95,13 +88,6 @@ CONFIG_FREEZER=y # CONFIG_FSL_LBC is not set CONFIG_FW_CACHE=y CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GCC_PLUGINS=y -# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set -# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set -# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set -# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set -# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set -# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_BUG=y @@ -163,6 +149,7 @@ CONFIG_LZO_DECOMPRESS=y # CONFIG_MATH_EMULATION is not set CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MIGRATION=y CONFIG_MMU_GATHER_PAGE_SIZE=y diff --git a/target/linux/apm821xx/nand/config-default b/target/linux/apm821xx/nand/config-default index 060f2abf06..931290d1b6 100644 --- a/target/linux/apm821xx/nand/config-default +++ b/target/linux/apm821xx/nand/config-default @@ -1,11 +1,6 @@ CONFIG_AT803X_PHY=y CONFIG_AR8216_PHY=y -CONFIG_DMADEVICES=y -CONFIG_DMA_ENGINE=y -CONFIG_DW_DMAC_CORE=y -CONFIG_DW_DMAC=y # CONFIG_SATA_DWC_OLD_DMA is not set -# CONFIG_DW_DMAC_PCI is not set CONFIG_IKAREM=y CONFIG_ATA=y CONFIG_ATA_SFF=y diff --git a/target/linux/apm821xx/sata/config-default b/target/linux/apm821xx/sata/config-default index c3f41c785b..9a0a8179cc 100644 --- a/target/linux/apm821xx/sata/config-default +++ b/target/linux/apm821xx/sata/config-default @@ -1,12 +1,7 @@ CONFIG_APOLLO3G=y CONFIG_BROADCOM_PHY=y CONFIG_EXT4_FS=y -CONFIG_DMADEVICES=y -CONFIG_DMA_ENGINE=y -CONFIG_DW_DMAC_CORE=y -CONFIG_DW_DMAC=y # CONFIG_SATA_DWC_OLD_DMA is not set -# CONFIG_DW_DMAC_PCI is not set CONFIG_ATA=y CONFIG_ATA_SFF=y CONFIG_ATA_BMDMA=y From 4ee9b3f462166f179f18e10b7b2e6f655473bb05 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 29 Sep 2021 19:13:55 -1000 Subject: [PATCH 44/59] apm821xx: switch to Kernel 5.10 Signed-off-by: Paul Spooren --- target/linux/apm821xx/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/apm821xx/Makefile b/target/linux/apm821xx/Makefile index 9c7f276dc0..7d31ac8d67 100644 --- a/target/linux/apm821xx/Makefile +++ b/target/linux/apm821xx/Makefile @@ -9,8 +9,7 @@ CPU_TYPE:=464fp FEATURES:=fpu dt gpio ramdisk squashfs usb SUBTARGETS:=nand sata -KERNEL_PATCHVER:=5.4 -KERNEL_TESTING_PATCHVER:=5.10 +KERNEL_PATCHVER:=5.10 define Target/Description Build images for AppliedMicro APM821xx based boards. From 7a6a3494450c4e3a41dd8cc8f3cadb525d5e966b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 3 Oct 2021 00:19:58 +0200 Subject: [PATCH 45/59] apm821xx: WNDAP620 + WNDAP660: reorganize partitions for 5.10 Due to 5.10 increased kernel size, the current 4MiB-ish kernel partition got too small. Luckily, netgear's uboot environment is setup to read 0x60000 bytes from the kernel partition location. ... While at it: also do some cleanups in the DTS in there. The original (re-)installation described in commit d82d84694e60 ("apm821xx: add support for the Netgear WNDAP620 and WNDAP660") seemed to be still working for now. What I noticed though is that the bigger initramfs images needed to use a different destination address (1000000) to prevent it overwriting itself during decompression. i.e: # tftp 1000000 openwrt-...-wndap620-initramfs-kernel.bin # bootm However, in case of the WNDAP620+660 the factory.img image can be written directly to the flash through uboot. Signed-off-by: Christian Lamparter --- target/linux/apm821xx/dts/netgear-wndap6x0.dtsi | 10 +++++----- target/linux/apm821xx/image/nand.mk | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi b/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi index fc428bca0f..88284d0237 100644 --- a/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi +++ b/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi @@ -61,12 +61,12 @@ * offset (0x110000) for an uImage binary. */ label = "kernel"; - reg = <0x00110000 0x003f0000>; + reg = <0x00110000 0x005f0000>; }; - partition@500000 { + partition@700000 { label = "ubi"; - reg = <0x00500000 0x016d0000>; + reg = <0x00700000 0x014d0000>; }; partition@1bd0000 { @@ -83,13 +83,13 @@ partition@1be0000 { label = "var"; - reg = <0x01be0000 0x0400000>; + reg = <0x01be0000 0x00400000>; read-only; }; partition@1fe0000 { label = "manudata"; - reg = <0x01fe0000 0x20000 >; + reg = <0x01fe0000 0x00020000>; read-only; }; }; diff --git a/target/linux/apm821xx/image/nand.mk b/target/linux/apm821xx/image/nand.mk index 26676c8d8b..76b1386241 100644 --- a/target/linux/apm821xx/image/nand.mk +++ b/target/linux/apm821xx/image/nand.mk @@ -68,11 +68,14 @@ define Device/netgear_wndap6x0 DTB_SIZE := 32768 IMAGE_SIZE := 27392k IMAGES := sysupgrade.bin factory.img - KERNEL_SIZE := 4032k + KERNEL_SIZE := 6080k KERNEL := dtb | kernel-bin | gzip | MuImage-initramfs gzip IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata IMAGE/factory.img := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi UBINIZE_OPTS := -E 5 + DEVICE_COMPAT_VERSION := 2.0 + DEVICE_COMPAT_MESSAGE := kernel and ubi partitions had to be resized. \ + Upgrade via sysupgrade mechanism is not possible. endef define Device/netgear_wndap620 From 4293fc32b73dc927b7dcc683a20e8e59dea92963 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 Oct 2021 13:32:09 +0200 Subject: [PATCH 46/59] gemini: splash banner on framebuffer console The D-Link DIR-685 has a small screen with a framebuffer console, so if we have this, when we start, display the banner on this framebuffer console so the user know they are running OpenWRT as root filesystem. Signed-off-by: Linus Walleij --- target/linux/gemini/base-files/etc/board.d/03_splash | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 target/linux/gemini/base-files/etc/board.d/03_splash diff --git a/target/linux/gemini/base-files/etc/board.d/03_splash b/target/linux/gemini/base-files/etc/board.d/03_splash new file mode 100644 index 0000000000..0c50ff7342 --- /dev/null +++ b/target/linux/gemini/base-files/etc/board.d/03_splash @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# OpenWRT splash screen if using framebuffer console + +if [ ! -d /sys/class/graphics/fbcon ] ; then + exit 0 +fi + +echo 0 > /sys/class/graphics/fbcon/cursor_blink +cat /etc/banner > /dev/tty0 From 44f89614c668c0065437ccc4b8c152b3cf2af04b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 10 Oct 2021 00:21:39 +0200 Subject: [PATCH 47/59] apm821xx: disable MX60(W) due to kernel size disables the MX60(W) from being built by the builders for now. But there's an effort to bring it back: Signed-off-by: Christian Lamparter --- target/linux/apm821xx/image/nand.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/apm821xx/image/nand.mk b/target/linux/apm821xx/image/nand.mk index 76b1386241..b48bff7924 100644 --- a/target/linux/apm821xx/image/nand.mk +++ b/target/linux/apm821xx/image/nand.mk @@ -41,6 +41,7 @@ endef TARGET_DEVICES += meraki_mr24 define Device/meraki_mx60 + DEFAULT := n DEVICE_VENDOR := Cisco Meraki DEVICE_MODEL := MX60/MX60W DEVICE_PACKAGES := kmod-spi-gpio kmod-usb-ledtrig-usbport kmod-usb-dwc2 \ From e166ee4ff123b18bc7248cda9596aa9ed7886a53 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 10 Oct 2021 00:39:41 +0200 Subject: [PATCH 48/59] apm821xx: disable and move kernel CONFIG_ symbols try to reduce the kernel size by disabling and moving options from the common kernel configuration to the SATA target that doesn't have the constraints. For NAND this has become necessary because as with 5.10 some devices outgrew their kernels. Though, in my tests this didn't help much: just a smidgen over 100kib was saved on the uncompressed kernel. ... running make kernel_oldconfig also removed some other config symbols, mostly those that already set from elsewhere or became obsolete in the meantime. Signed-off-by: Christian Lamparter --- target/linux/apm821xx/config-5.10 | 33 ++--------------------- target/linux/apm821xx/sata/config-default | 15 +++++++++++ 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/target/linux/apm821xx/config-5.10 b/target/linux/apm821xx/config-5.10 index bb9753d0b4..22d34c3fce 100644 --- a/target/linux/apm821xx/config-5.10 +++ b/target/linux/apm821xx/config-5.10 @@ -25,7 +25,6 @@ CONFIG_AUDIT_ARCH=y # CONFIG_BAMBOO is not set # CONFIG_BLK_DEV_INITRD is not set CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y CONFIG_BLUESTONE=y CONFIG_BOOKE=y CONFIG_BOOKE_WDT=y @@ -40,33 +39,20 @@ CONFIG_CPU_BIG_ENDIAN=y CONFIG_CRC16=y # CONFIG_CRC32_SARWATE is not set CONFIG_CRC32_SLICEBY8=y -CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_CFB=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DEV_PPC4XX=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ESSIV=y CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HW=y CONFIG_CRYPTO_JITTERENTROPY=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 CONFIG_CRYPTO_LIB_SHA256=y CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_MD5_PPC=y +# CONFIG_CRYPTO_MD5_PPC is not set CONFIG_CRYPTO_NULL2=y -CONFIG_CRYPTO_OFB=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SEQIV=y -CONFIG_CRYPTO_SHA1_PPC=y -CONFIG_CRYPTO_SHA256=y +# CONFIG_CRYPTO_SHA1_PPC is not set CONFIG_DATA_SHIFT=12 -CONFIG_DEBUG_MISC=y CONFIG_DMADEVICES=y CONFIG_DMA_DIRECT_REMAP=y CONFIG_DMA_ENGINE=y @@ -84,9 +70,7 @@ CONFIG_EDAC_SUPPORT=y CONFIG_EXTRA_TARGETS="uImage" CONFIG_FIXED_PHY=y CONFIG_FORCE_PCI=y -CONFIG_FREEZER=y # CONFIG_FSL_LBC is not set -CONFIG_FW_CACHE=y CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ATOMIC64=y @@ -184,7 +168,6 @@ CONFIG_PAGE_OFFSET=0xc0000000 CONFIG_PCI=y CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_PME=y CONFIG_PCI_DISABLE_COMMON_QUIRKS=y CONFIG_PCI_DOMAINS=y CONFIG_PCI_MSI=y @@ -195,18 +178,10 @@ CONFIG_PHYLIB=y CONFIG_PHYSICAL_START=0x00000000 CONFIG_PHYS_64BIT=y CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_PM=y # CONFIG_PMU_SYSFS is not set -CONFIG_PM_AUTOSLEEP=y -CONFIG_PM_CLK=y -CONFIG_PM_SLEEP=y -CONFIG_PM_WAKELOCKS=y -CONFIG_PM_WAKELOCKS_GC=y -CONFIG_PM_WAKELOCKS_LIMIT=100 CONFIG_PPC=y CONFIG_PPC32=y CONFIG_PPC44x_SIMPLE=y -CONFIG_PPC4xx_CPM=y CONFIG_PPC4xx_GPIO=y CONFIG_PPC4xx_MSI=y CONFIG_PPC4xx_PCI_EXPRESS=y @@ -242,16 +217,12 @@ CONFIG_RSEQ=y # CONFIG_SAM440EP is not set # CONFIG_SCOM_DEBUGFS is not set # CONFIG_SEQUOIA is not set -CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SGL_ALLOC=y CONFIG_SPARSE_IRQ=y CONFIG_SRCU=y -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y CONFIG_SWPHY=y CONFIG_SYSCTL_EXCEPTION_TRACE=y # CONFIG_TAISHAN is not set diff --git a/target/linux/apm821xx/sata/config-default b/target/linux/apm821xx/sata/config-default index 9a0a8179cc..e8e595641d 100644 --- a/target/linux/apm821xx/sata/config-default +++ b/target/linux/apm821xx/sata/config-default @@ -9,10 +9,15 @@ CONFIG_SATA_PMP=y CONFIG_GENERIC_PHY=y CONFIG_SATA_DWC=y # CONFIG_SATA_DWC_DEBUG is not set +CONFIG_CRYPTO_MD5_PPC=y +CONFIG_CRYPTO_SHA1_PPC=y CONFIG_EXT4_FS=y CONFIG_F2FS_FS=y +CONFIG_FREEZER=y +CONFIG_FW_CACHE=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y +CONFIG_BLK_PM=y CONFIG_GPIOLIB=y CONFIG_GPIO_GENERIC=y CONFIG_GPIO_GENERIC_PLATFORM=y @@ -30,9 +35,19 @@ CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y # CONFIG_MD_RAID10 is not set # CONFIG_MD_RAID456 is not set +CONFIG_PM=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_CLK=y +CONFIG_PM_SLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_GC=y +CONFIG_PM_WAKELOCKS_LIMIT=100 CONFIG_PPC_EARLY_DEBUG=y CONFIG_PPC_EARLY_DEBUG_44x=y # CONFIG_PPC_EARLY_DEBUG_MEMCONS is not set CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x4 CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300 +CONFIG_PPC4xx_CPM=y CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y From f536f5ebddd9c532a08ac4a9be3ef0c02f7bfeb8 Mon Sep 17 00:00:00 2001 From: Chris Blake Date: Fri, 24 Sep 2021 08:42:03 -0500 Subject: [PATCH 49/59] gpio-cdev: add nu801 userspace driver This adds a userspace interpretation of the nu801 driver used by Meraki hardware. Previously this was a driver that was added per target, but as multiple targets now have this driver, we should move to something that can be shared by all targets since no driver exists upstream. Co-developed-by: Christian Lamparter Signed-off-by: Chris Blake Signed-off-by: Christian Lamparter --- package/system/gpio-cdev/nu801/Makefile | 41 +++++++++++++++++++ .../system/gpio-cdev/nu801/files/nu801.init | 15 +++++++ 2 files changed, 56 insertions(+) create mode 100644 package/system/gpio-cdev/nu801/Makefile create mode 100755 package/system/gpio-cdev/nu801/files/nu801.init diff --git a/package/system/gpio-cdev/nu801/Makefile b/package/system/gpio-cdev/nu801/Makefile new file mode 100644 index 0000000000..a03d746634 --- /dev/null +++ b/package/system/gpio-cdev/nu801/Makefile @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +include $(TOPDIR)/rules.mk + +PKG_NAME:=nu801 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/chunkeey/nu801.git +PKG_SOURCE_VERSION:=794a588fce3150129bb2e5bb37590c7daceb8927 + +PKG_MAINTAINER:=Christian Lamparter +PKG_LICENSE:=GPL-3.0-or-later +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/nu801 + SECTION:=utils + CATEGORY:=Utilities + SUBMENU:=Userspace GPIO Drivers + DEPENDS:=@!LINUX_5_4 +kmod-leds-uleds + KCONFIG:= \ + CONFIG_GPIO_CDEV=y + TITLE:=NU801 LED Driver +endef + +define Package/nu801/description +This package contains a userspace driver to power the NUMEN Tech. NU801 LED Driver. +endef + +define Package/nu801/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/nu801 $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/nu801.init $(1)/etc/init.d/nu801 + +endef + +$(eval $(call BuildPackage,nu801)) diff --git a/package/system/gpio-cdev/nu801/files/nu801.init b/package/system/gpio-cdev/nu801/files/nu801.init new file mode 100755 index 0000000000..5613a92f6e --- /dev/null +++ b/package/system/gpio-cdev/nu801/files/nu801.init @@ -0,0 +1,15 @@ +#!/bin/sh /etc/rc.common +# SPDX-License-Identifier: GPL-2.0-or-later + +START=15 +STOP=94 +USE_PROCD=1 + +start_service() { + . /lib/functions.sh + + procd_open_instance + procd_set_param command /usr/sbin/nu801 "$(board_name)" + procd_set_param respawn 5 1 5 + procd_close_instance +} From fe9e5fbd7527ad4ff4f5b955823216038a80557d Mon Sep 17 00:00:00 2001 From: Chris Blake Date: Fri, 1 Oct 2021 09:38:56 -0500 Subject: [PATCH 50/59] x86: add support for Meraki MX100 This commit will add support for the Meraki MX100 in OpenWRT. Specs: * CPU: Intel Xeon E3-1200 Series 1.5GHz 2C/4T * Memory: 4GB DDR3 1600 ECC * Storage: 1GB USB NAND, 1TB SATA HDD * Wireless: None * Wired: 10x 1Gb RJ45, 2x 1Gb SFP UART: The UART header is named CONN11 and is found in the center of the mainboard. The pinout from Pin 1 (marked with a black triangle) to pin 4 is below: Pin 1: VCC Pin 2: TX Pin 3: RX Pin 4: GND Note that VCC is not required for UART on this device. Booting: 1. Flash/burn one of the images from this repo to a flash drive. 2. Take the top off the MX100, and unplug the SATA cable from the HDD. 3. Hook up UART to the MX100, plug in the USB drive, and then power up the device. 4. At the BIOS prompt, quickly press F7 and then scroll to the Save & Exit tab. 5. Scroll down to Boot Override, and select the UEFI entry for your jumpdrive. Note: UEFI booting will fail if the SATA cable for the HDD is plugged in. The issue is explained under the Flashing instructions. Flashing: 1. Ensure the MX100 is powered down, and not plugged into power. 2. Take the top off the MX100, and unplug the SATA cable from the HDD. 3. Using the Mini USB female port found by the SATA port on the motherboard, flash one of the images to the system. Example: `dd if=image of=/dev/sdb conv=fdatasync` where sdb is the USB device for the MX100's NAND. 4. Unplug the Mini USB, hook up UART to the MX100, and then power up the device. 5. At the BIOS prompt, quickly press F7 and then scroll to the Boot tab. 6. Change the boot order and set UEFI: USB DISK 2.0 as first, and USB DISK 2.0 as second. Disable the other boot options. 7. Go to Save & Exit, and then select Save Changes and Reset Note that OpenWRT will fail to boot in UEFI mode when the SATA hard drive is plugged in. To fix this, boot with the SATA disk unplugged and then run the following command: `sed -i "s|hd0,gpt1|hd1,gpt1|g" boot/grub/grub.cfg` Once the above is ran, OpenWRT will boot when the HDD is plugged into SATA. The reason this happens is the UEFI implementation for the MX100 will always set anything on SATA to HD0 instead of the onboard USB storage, so we have to accomidate it since OpenWRT's GRUB does not support detecting a boot disk via UUID. Signed-off-by: Chris Blake --- .../linux/x86/base-files/etc/board.d/01_leds | 4 + .../x86/base-files/etc/board.d/02_network | 3 + .../x86/base-files/lib/upgrade/platform.sh | 10 + target/linux/x86/modules.mk | 20 ++ ..._ich-Enable-GPIO-driver-for-DH89xxCC.patch | 32 ++ ...x86-add-meraki-mx100-platform-driver.patch | 300 ++++++++++++++++++ 6 files changed, 369 insertions(+) create mode 100644 target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch create mode 100644 target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch diff --git a/target/linux/x86/base-files/etc/board.d/01_leds b/target/linux/x86/base-files/etc/board.d/01_leds index 79e1191080..74ad2d59fe 100644 --- a/target/linux/x86/base-files/etc/board.d/01_leds +++ b/target/linux/x86/base-files/etc/board.d/01_leds @@ -7,6 +7,10 @@ board_config_update case "$(board_name)" in +cisco-mx100-hw) + ucidef_set_led_usbport "usb" "USB" "mx100:green:usb" "1-1-port2" + ucidef_set_led_default "diag" "DIAG" "mx100:green:tricolor" "1" + ;; pc-engines-apu1|pc-engines-apu2|pc-engines-apu3) ucidef_set_led_netdev "wan" "WAN" "apu:green:3" "eth0" ucidef_set_led_netdev "lan" "LAN" "apu:green:2" "br-lan" diff --git a/target/linux/x86/base-files/etc/board.d/02_network b/target/linux/x86/base-files/etc/board.d/02_network index 30035dcbe9..2a07518096 100644 --- a/target/linux/x86/base-files/etc/board.d/02_network +++ b/target/linux/x86/base-files/etc/board.d/02_network @@ -8,6 +8,9 @@ board_config_update case "$(board_name)" in +cisco-mx100-hw) + ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth4 eth5 eth7 eth8 eth9 eth10 eth11" "eth6" + ;; pc-engines-apu1|pc-engines-apu2|pc-engines-apu3) ucidef_set_interfaces_lan_wan "eth1 eth2" "eth0" ;; diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh index d8f2eba97e..94bf80b144 100644 --- a/target/linux/x86/base-files/lib/upgrade/platform.sh +++ b/target/linux/x86/base-files/lib/upgrade/platform.sh @@ -65,6 +65,16 @@ platform_do_bootloader_upgrade() { "/dev/$diskdev" \ && touch /tmp/boot/boot/grub/upgraded + case "$(board_name)" in + cisco-mx100-hw) + # If the MX100 is booted UEFI AND the SATA HDD exists, we need to change + # grub's root= to hd1 for it to boot correctly, otherwise we can keep it hd0. + if [ -d /sys/firmware/efi ] && [ "$(ls -a /dev/sd[a-z] | wc -w)" -gt 1 ] ; then + sed -i "s|hd0,${parttable}1|hd1,${parttable}1|g" /tmp/boot/boot/grub/grub.cfg + fi + ;; + esac + umount /tmp/boot fi } diff --git a/target/linux/x86/modules.mk b/target/linux/x86/modules.mk index d31e4535df..0071ebda41 100644 --- a/target/linux/x86/modules.mk +++ b/target/linux/x86/modules.mk @@ -82,3 +82,23 @@ define KernelPackage/pcengines-apuv2/description endef $(eval $(call KernelPackage,pcengines-apuv2)) + + +define KernelPackage/meraki-mx100 + SUBMENU:=$(OTHER_MENU) + TITLE:=Cisco Meraki MX100 Platform Driver + DEPENDS:=@TARGET_x86 @!LINUX_5_4 +kmod-tg3 +kmod-gpio-button-hotplug +kmod-leds-gpio \ + +kmod-usb-ledtrig-usbport +nu801 +kmod-itco-wdt + KCONFIG:=CONFIG_MERAKI_MX100 + FILES:=$(LINUX_DIR)/drivers/platform/x86/meraki-mx100.ko + AUTOLOAD:=$(call AutoLoad,60,meraki-mx100,1) +endef + +define KernelPackage/meraki-mx100/description + This driver provides support for the front button and LEDs on + the Cisco Meraki MX100 (Tinkerbell) 1U appliance. Note this also + selects the gpio-cdev nu801 userspace driver to support the Status + LED, as well as other required platform drivers. +endef + +$(eval $(call KernelPackage,meraki-mx100)) diff --git a/target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch b/target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch new file mode 100644 index 0000000000..0f0a3958da --- /dev/null +++ b/target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch @@ -0,0 +1,32 @@ +From ef0eea5b151aefe1efea78e2fa7c507ff3c56bf0 Mon Sep 17 00:00:00 2001 +From: Chris Blake +Date: Mon, 7 Jun 2021 18:35:35 -0500 +Subject: mfd: lpc_ich: Enable GPIO driver for DH89xxCC + +Based on the Intel Datasheet for the DH89xxCC PCH, the GPIO driver +is the same as ICH_v5_GPIO, minus the fact the DH89xxCC also has +blink support. However, blink support isn't supported by the GPIO +driver so we should use ICH_v5_GPIO. Tested and working on a Meraki +MX100-HW. + +Signed-off-by: Chris Blake +Co-developed-by: Christian Lamparter +Signed-off-by: Lee Jones +--- + drivers/mfd/lpc_ich.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c +index 3bbb29a7e7a57..f10e53187f67a 100644 +--- a/drivers/mfd/lpc_ich.c ++++ b/drivers/mfd/lpc_ich.c +@@ -489,6 +489,7 @@ static struct lpc_ich_info lpc_chipset_info[] = { + [LPC_DH89XXCC] = { + .name = "DH89xxCC", + .iTCO_version = 2, ++ .gpio_version = ICH_V5_GPIO, + }, + [LPC_PPT] = { + .name = "Panther Point", +-- +cgit 1.2.3-1.el7 diff --git a/target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch b/target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch new file mode 100644 index 0000000000..c05b61a994 --- /dev/null +++ b/target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch @@ -0,0 +1,300 @@ +From 636a1e697555e73c28cdd6952a409edbfdd16475 Mon Sep 17 00:00:00 2001 +From: Chris Blake +Date: Mon, 9 Aug 2021 19:40:21 -0500 +Subject: platform/x86: add meraki-mx100 platform driver + +This adds platform support for the Cisco Meraki MX100 (Tinkerbell) +network appliance. This sets up the network LEDs and Reset +button. + +Depends-on: ef0eea5b151ae ("mfd: lpc_ich: Enable GPIO driver for DH89xxCC") +Co-developed-by: Christian Lamparter +Signed-off-by: Christian Lamparter +Signed-off-by: Chris Blake +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20210810004021.2538308-1-chrisrblake93@gmail.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +--- + drivers/platform/x86/Kconfig | 13 ++ + drivers/platform/x86/Makefile | 3 + + drivers/platform/x86/meraki-mx100.c | 230 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 246 insertions(+) + create mode 100644 drivers/platform/x86/meraki-mx100.c + +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 6ad35158ae4ef..432d72170b003 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -302,6 +302,19 @@ config ASUS_NB_WMI + If you have an ACPI-WMI compatible Asus Notebook, say Y or M + here. + ++config MERAKI_MX100 ++ tristate "Cisco Meraki MX100 Platform Driver" ++ depends on GPIOLIB ++ depends on GPIO_ICH ++ depends on LEDS_CLASS ++ select LEDS_GPIO ++ help ++ This driver provides support for the front button and LEDs on ++ the Cisco Meraki MX100 (Tinkerbell) 1U appliance. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called meraki-mx100. ++ + config EEEPC_LAPTOP + tristate "Eee PC Hotkey Driver" + depends on ACPI +diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile +index 5edfdc2ea7f29..9bb3c3f773864 100644 +--- a/drivers/platform/x86/Makefile ++++ b/drivers/platform/x86/Makefile +@@ -39,6 +39,9 @@ obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o + obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o + obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o + ++# Cisco/Meraki ++obj-$(CONFIG_MERAKI_MX100) += meraki-mx100.o ++ + # Dell + obj-$(CONFIG_X86_PLATFORM_DRIVERS_DELL) += dell/ + +diff --git a/drivers/platform/x86/meraki-mx100.c b/drivers/platform/x86/meraki-mx100.c +new file mode 100644 +index 0000000000000..3751ed36a980a +--- /dev/null ++++ b/drivers/platform/x86/meraki-mx100.c +@@ -0,0 +1,230 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++/* ++ * Cisco Meraki MX100 (Tinkerbell) board platform driver ++ * ++ * Based off of arch/x86/platform/meraki/tink.c from the ++ * Meraki GPL release meraki-firmware-sources-r23-20150601 ++ * ++ * Format inspired by platform/x86/pcengines-apuv2.c ++ * ++ * Copyright (C) 2021 Chris Blake ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TINK_GPIO_DRIVER_NAME "gpio_ich" ++ ++/* LEDs */ ++static const struct gpio_led tink_leds[] = { ++ { ++ .name = "mx100:green:internet", ++ .default_trigger = "default-on", ++ }, ++ { ++ .name = "mx100:green:lan2", ++ }, ++ { ++ .name = "mx100:green:lan3", ++ }, ++ { ++ .name = "mx100:green:lan4", ++ }, ++ { ++ .name = "mx100:green:lan5", ++ }, ++ { ++ .name = "mx100:green:lan6", ++ }, ++ { ++ .name = "mx100:green:lan7", ++ }, ++ { ++ .name = "mx100:green:lan8", ++ }, ++ { ++ .name = "mx100:green:lan9", ++ }, ++ { ++ .name = "mx100:green:lan10", ++ }, ++ { ++ .name = "mx100:green:lan11", ++ }, ++ { ++ .name = "mx100:green:ha", ++ }, ++ { ++ .name = "mx100:orange:ha", ++ }, ++ { ++ .name = "mx100:green:usb", ++ }, ++ { ++ .name = "mx100:orange:usb", ++ }, ++}; ++ ++static const struct gpio_led_platform_data tink_leds_pdata = { ++ .num_leds = ARRAY_SIZE(tink_leds), ++ .leds = tink_leds, ++}; ++ ++static struct gpiod_lookup_table tink_leds_table = { ++ .dev_id = "leds-gpio", ++ .table = { ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 11, ++ NULL, 0, GPIO_ACTIVE_LOW), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 18, ++ NULL, 1, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 20, ++ NULL, 2, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 22, ++ NULL, 3, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 23, ++ NULL, 4, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 32, ++ NULL, 5, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 34, ++ NULL, 6, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 35, ++ NULL, 7, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 36, ++ NULL, 8, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 37, ++ NULL, 9, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 48, ++ NULL, 10, GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 16, ++ NULL, 11, GPIO_ACTIVE_LOW), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 7, ++ NULL, 12, GPIO_ACTIVE_LOW), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 21, ++ NULL, 13, GPIO_ACTIVE_LOW), ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 19, ++ NULL, 14, GPIO_ACTIVE_LOW), ++ {} /* Terminating entry */ ++ } ++}; ++ ++/* Reset Button */ ++static struct gpio_keys_button tink_buttons[] = { ++ { ++ .desc = "Reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .active_low = 1, ++ .debounce_interval = 100, ++ }, ++}; ++ ++static const struct gpio_keys_platform_data tink_buttons_pdata = { ++ .buttons = tink_buttons, ++ .nbuttons = ARRAY_SIZE(tink_buttons), ++ .poll_interval = 20, ++ .rep = 0, ++ .name = "mx100-keys", ++}; ++ ++static struct gpiod_lookup_table tink_keys_table = { ++ .dev_id = "gpio-keys-polled", ++ .table = { ++ GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 60, ++ NULL, 0, GPIO_ACTIVE_LOW), ++ {} /* Terminating entry */ ++ } ++}; ++ ++/* Board setup */ ++static const struct dmi_system_id tink_systems[] __initconst = { ++ { ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Cisco"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MX100-HW"), ++ }, ++ }, ++ {} /* Terminating entry */ ++}; ++MODULE_DEVICE_TABLE(dmi, tink_systems); ++ ++static struct platform_device *tink_leds_pdev; ++static struct platform_device *tink_keys_pdev; ++ ++static struct platform_device * __init tink_create_dev( ++ const char *name, const void *pdata, size_t sz) ++{ ++ struct platform_device *pdev; ++ ++ pdev = platform_device_register_data(NULL, ++ name, PLATFORM_DEVID_NONE, pdata, sz); ++ if (IS_ERR(pdev)) ++ pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev)); ++ ++ return pdev; ++} ++ ++static int __init tink_board_init(void) ++{ ++ int ret; ++ ++ if (!dmi_first_match(tink_systems)) ++ return -ENODEV; ++ ++ /* ++ * We need to make sure that GPIO60 isn't set to native mode as is default since it's our ++ * Reset Button. To do this, write to GPIO_USE_SEL2 to have GPIO60 set to GPIO mode. ++ * This is documented on page 1609 of the PCH datasheet, order number 327879-005US ++ */ ++ outl(inl(0x530) | BIT(28), 0x530); ++ ++ gpiod_add_lookup_table(&tink_leds_table); ++ gpiod_add_lookup_table(&tink_keys_table); ++ ++ tink_leds_pdev = tink_create_dev("leds-gpio", ++ &tink_leds_pdata, sizeof(tink_leds_pdata)); ++ if (IS_ERR(tink_leds_pdev)) { ++ ret = PTR_ERR(tink_leds_pdev); ++ goto err; ++ } ++ ++ tink_keys_pdev = tink_create_dev("gpio-keys-polled", ++ &tink_buttons_pdata, sizeof(tink_buttons_pdata)); ++ if (IS_ERR(tink_keys_pdev)) { ++ ret = PTR_ERR(tink_keys_pdev); ++ platform_device_unregister(tink_leds_pdev); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ gpiod_remove_lookup_table(&tink_keys_table); ++ gpiod_remove_lookup_table(&tink_leds_table); ++ return ret; ++} ++module_init(tink_board_init); ++ ++static void __exit tink_board_exit(void) ++{ ++ platform_device_unregister(tink_keys_pdev); ++ platform_device_unregister(tink_leds_pdev); ++ gpiod_remove_lookup_table(&tink_keys_table); ++ gpiod_remove_lookup_table(&tink_leds_table); ++} ++module_exit(tink_board_exit); ++ ++MODULE_AUTHOR("Chris Blake "); ++MODULE_DESCRIPTION("Cisco Meraki MX100 Platform Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:meraki-mx100"); +-- +cgit 1.2.3-1.el7 From 81d694e30b4926fea057bd3e46d996a8f098b95a Mon Sep 17 00:00:00 2001 From: Szabolcs Hubai Date: Sun, 10 Oct 2021 01:32:30 +0200 Subject: [PATCH 51/59] ipq40xx: use zImage for GL.iNet GL-B1300, GL-S1300 to shrink below 4096k In the "ipq40xx: switch to Kernel 5.10" discussion at GitHub, Adrian noted [0] that these GL.iNet Conexa series devices, GL-B1300 and GL-S1300 failed their image generation [1] as their gzipped uImage kernel went above 4096k. While notifying the vendor about this problem [2], I tested all U-Boot releases from GL.iNet: - they really fail to boot kernel above 4096k - they don't support lzma: "Unimplemented compression type 3" - but they boot zImage Using zImage (xz compression) the kernel is 2909k which is more than a megabyte away from the KERNEL_SIZE := 4096k limit. The gzip compressed version would be 4116k. [0]: https://github.com/openwrt/openwrt/pull/4620#issuecomment-932765776 [1]: commit 7b1fa276f5a2 ("ipq40xx: add testing support for kernel 5.10") [2]: https://forum.gl-inet.com/t/ipq40xx-kernel-size-and-u-boot-v5-10-is-too-big-for-4-mb/17619 Signed-off-by: Szabolcs Hubai --- target/linux/ipq40xx/image/generic.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk index 18f5d238c7..e0cfa07541 100644 --- a/target/linux/ipq40xx/image/generic.mk +++ b/target/linux/ipq40xx/image/generic.mk @@ -495,7 +495,7 @@ endef TARGET_DEVICES += glinet_gl-ap1300 define Device/glinet_gl-b1300 - $(call Device/FitImage) + $(call Device/FitzImage) DEVICE_VENDOR := GL.iNet DEVICE_MODEL := GL-B1300 BOARD_NAME := gl-b1300 @@ -507,7 +507,7 @@ endef TARGET_DEVICES += glinet_gl-b1300 define Device/glinet_gl-s1300 - $(call Device/FitImage) + $(call Device/FitzImage) DEVICE_VENDOR := GL.iNet DEVICE_MODEL := GL-S1300 SOC := qcom-ipq4029 From 7c0fb874436c0613a042c8b07aa00621d08f4eaa Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 9 Oct 2021 12:24:44 -0700 Subject: [PATCH 52/59] tools/meson: fix usage with SDK The python path cannot be embedded in the meson binary as it changes with the SDK. Signed-off-by: Rosen Penev --- include/meson.mk | 2 +- tools/meson/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/meson.mk b/include/meson.mk index 9862f0e662..12e38b9e71 100644 --- a/include/meson.mk +++ b/include/meson.mk @@ -56,7 +56,7 @@ MESON_CPU:="$(CPU_TYPE)$(if $(CPU_SUBTYPE),+$(CPU_SUBTYPE))" endif define Meson - $(2) $(STAGING_DIR_HOST)/bin/meson $(1) + $(2) $(STAGING_DIR_HOST)/bin/$(PYTHON) $(STAGING_DIR_HOST)/bin/meson $(1) endef define Meson/CreateNativeFile diff --git a/tools/meson/Makefile b/tools/meson/Makefile index 0cf0efba47..1aab5d8fcb 100644 --- a/tools/meson/Makefile +++ b/tools/meson/Makefile @@ -21,7 +21,7 @@ endef define Host/Install $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin - $(HOST_BUILD_DIR)/packaging/create_zipapp.py $(HOST_BUILD_DIR) --interpreter $(STAGING_DIR_HOST)/bin/$(PYTHON) --outfile $(STAGING_DIR_HOST)/bin/meson + $(HOST_BUILD_DIR)/packaging/create_zipapp.py $(HOST_BUILD_DIR) --outfile $(STAGING_DIR_HOST)/bin/meson $(INSTALL_DIR) $(STAGING_DIR_HOST)/lib/meson $(INSTALL_CONF) files/openwrt-cross.txt.in $(STAGING_DIR_HOST)/lib/meson/ $(INSTALL_CONF) files/openwrt-native.txt.in $(STAGING_DIR_HOST)/lib/meson/ From 80b7a8a7f5a0a88fde6dd19f097df4d7cac9ff04 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 10 Oct 2021 22:06:51 +0200 Subject: [PATCH 53/59] Revert "gpio-cdev: add nu801 userspace driver" This reverts commit f536f5ebddd9c532a08ac4a9be3ef0c02f7bfeb8. As Hauke commented, this causes builder failures on 5.4 kernels. This revert includes changes to the mx100 kernel modules dependency as well as the uci led definitions. Tested-by: Chris Blake Signed-off-by: Christian Lamparter --- package/system/gpio-cdev/nu801/Makefile | 41 ------------------- .../system/gpio-cdev/nu801/files/nu801.init | 15 ------- .../linux/x86/base-files/etc/board.d/01_leds | 2 +- target/linux/x86/modules.mk | 2 +- 4 files changed, 2 insertions(+), 58 deletions(-) delete mode 100644 package/system/gpio-cdev/nu801/Makefile delete mode 100755 package/system/gpio-cdev/nu801/files/nu801.init diff --git a/package/system/gpio-cdev/nu801/Makefile b/package/system/gpio-cdev/nu801/Makefile deleted file mode 100644 index a03d746634..0000000000 --- a/package/system/gpio-cdev/nu801/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later - -include $(TOPDIR)/rules.mk - -PKG_NAME:=nu801 -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/chunkeey/nu801.git -PKG_SOURCE_VERSION:=794a588fce3150129bb2e5bb37590c7daceb8927 - -PKG_MAINTAINER:=Christian Lamparter -PKG_LICENSE:=GPL-3.0-or-later -PKG_LICENSE_FILES:=LICENSE - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -define Package/nu801 - SECTION:=utils - CATEGORY:=Utilities - SUBMENU:=Userspace GPIO Drivers - DEPENDS:=@!LINUX_5_4 +kmod-leds-uleds - KCONFIG:= \ - CONFIG_GPIO_CDEV=y - TITLE:=NU801 LED Driver -endef - -define Package/nu801/description -This package contains a userspace driver to power the NUMEN Tech. NU801 LED Driver. -endef - -define Package/nu801/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/nu801 $(1)/usr/sbin/ - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/nu801.init $(1)/etc/init.d/nu801 - -endef - -$(eval $(call BuildPackage,nu801)) diff --git a/package/system/gpio-cdev/nu801/files/nu801.init b/package/system/gpio-cdev/nu801/files/nu801.init deleted file mode 100755 index 5613a92f6e..0000000000 --- a/package/system/gpio-cdev/nu801/files/nu801.init +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh /etc/rc.common -# SPDX-License-Identifier: GPL-2.0-or-later - -START=15 -STOP=94 -USE_PROCD=1 - -start_service() { - . /lib/functions.sh - - procd_open_instance - procd_set_param command /usr/sbin/nu801 "$(board_name)" - procd_set_param respawn 5 1 5 - procd_close_instance -} diff --git a/target/linux/x86/base-files/etc/board.d/01_leds b/target/linux/x86/base-files/etc/board.d/01_leds index 74ad2d59fe..42974d8290 100644 --- a/target/linux/x86/base-files/etc/board.d/01_leds +++ b/target/linux/x86/base-files/etc/board.d/01_leds @@ -9,7 +9,7 @@ board_config_update case "$(board_name)" in cisco-mx100-hw) ucidef_set_led_usbport "usb" "USB" "mx100:green:usb" "1-1-port2" - ucidef_set_led_default "diag" "DIAG" "mx100:green:tricolor" "1" + ucidef_set_led_default "diag" "DIAG" "mx100:green:ha" "1" ;; pc-engines-apu1|pc-engines-apu2|pc-engines-apu3) ucidef_set_led_netdev "wan" "WAN" "apu:green:3" "eth0" diff --git a/target/linux/x86/modules.mk b/target/linux/x86/modules.mk index 0071ebda41..4005ee97ef 100644 --- a/target/linux/x86/modules.mk +++ b/target/linux/x86/modules.mk @@ -88,7 +88,7 @@ define KernelPackage/meraki-mx100 SUBMENU:=$(OTHER_MENU) TITLE:=Cisco Meraki MX100 Platform Driver DEPENDS:=@TARGET_x86 @!LINUX_5_4 +kmod-tg3 +kmod-gpio-button-hotplug +kmod-leds-gpio \ - +kmod-usb-ledtrig-usbport +nu801 +kmod-itco-wdt + +kmod-usb-ledtrig-usbport +kmod-itco-wdt KCONFIG:=CONFIG_MERAKI_MX100 FILES:=$(LINUX_DIR)/drivers/platform/x86/meraki-mx100.ko AUTOLOAD:=$(call AutoLoad,60,meraki-mx100,1) From 977bf5e9802bf4543e6356e391851b13ee32a1f9 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 4 Oct 2021 18:37:34 -0700 Subject: [PATCH 54/59] tools/ccache: update to 4.4.2 Refreshed patch. Disable hiredis backend since it seems to default to it now. Signed-off-by: Rosen Penev --- tools/ccache/Makefile | 5 +++-- tools/ccache/patches/100-honour-copts.patch | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/ccache/Makefile b/tools/ccache/Makefile index 7c85d549e9..081cc46dd0 100644 --- a/tools/ccache/Makefile +++ b/tools/ccache/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/target.mk PKG_NAME:=ccache -PKG_VERSION:=4.3 +PKG_VERSION:=4.4.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://github.com/ccache/ccache/releases/download/v$(PKG_VERSION) -PKG_HASH:=504a0f2184465c306826f035b4bc00bae7500308d6af4abbfb50e33a694989b4 +PKG_HASH:=9200cafbaa5fd62c2600fccb40a18214e57747825e6cdcd76688b4b61c2dcba0 include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/cmake.mk @@ -22,6 +22,7 @@ CMAKE_HOST_OPTIONS += \ -DCMAKE_CXX_COMPILER_LAUNCHER="" \ -DCMAKE_SKIP_RPATH=FALSE \ -DCMAKE_INSTALL_RPATH="${STAGING_DIR_HOST}/lib" \ + -DREDIS_STORAGE_BACKEND=OFF ifneq (docs-$(CONFIG_BUILD_DOCUMENTATION),docs-y) CMAKE_HOST_OPTIONS += -DENABLE_DOCUMENTATION=OFF diff --git a/tools/ccache/patches/100-honour-copts.patch b/tools/ccache/patches/100-honour-copts.patch index 0dcc6598f5..55422985b7 100644 --- a/tools/ccache/patches/100-honour-copts.patch +++ b/tools/ccache/patches/100-honour-copts.patch @@ -1,6 +1,6 @@ --- a/src/ccache.cpp +++ b/src/ccache.cpp -@@ -1756,6 +1756,7 @@ calculate_result_name(Context& ctx, +@@ -1633,6 +1633,7 @@ calculate_result_and_manifest_key(Contex "CPLUS_INCLUDE_PATH", "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH", // clang From b45ff2d0238ba696eab7c34126b2a1935a1b8cb6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Oct 2021 12:00:49 +0200 Subject: [PATCH 55/59] scripts/rstrip.sh: do not strip .o files with STRIP_KMOD Fixes packaging of eBPF modules Signed-off-by: Felix Fietkau --- scripts/rstrip.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/rstrip.sh b/scripts/rstrip.sh index 59f8624df2..e47960a941 100755 --- a/scripts/rstrip.sh +++ b/scripts/rstrip.sh @@ -27,6 +27,7 @@ find $TARGETS -type f -a -exec file {} \; | \ while read F S; do echo "$SELF: $F: $S" [ "${S}" = "relocatable" ] && { + [ "${F##*.}" == "o" ] && continue eval "$STRIP_KMOD $F" } || { b=$(stat -c '%a' $F) From 978e822db354daf974811f2717c6013fa3eb8079 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Oct 2021 11:48:49 +0200 Subject: [PATCH 56/59] mac80211: backport AP mode TWT support Required for an upcoming mt76 update Signed-off-by: Felix Fietkau --- ...eee80211-add-TWT-element-definitions.patch | 112 ++++ ...ce-individual-TWT-support-in-AP-mode.patch | 580 ++++++++++++++++++ .../500-mac80211_configure_antenna_gain.patch | 2 +- 3 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 package/kernel/mac80211/patches/subsys/389-ieee80211-add-TWT-element-definitions.patch create mode 100644 package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch diff --git a/package/kernel/mac80211/patches/subsys/389-ieee80211-add-TWT-element-definitions.patch b/package/kernel/mac80211/patches/subsys/389-ieee80211-add-TWT-element-definitions.patch new file mode 100644 index 0000000000..369619938e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/389-ieee80211-add-TWT-element-definitions.patch @@ -0,0 +1,112 @@ +From: Lorenzo Bianconi +Date: Mon, 23 Aug 2021 20:02:38 +0200 +Subject: [PATCH] ieee80211: add TWT element definitions + +Introduce TWT definitions and TWT Information element structure +in ieee80211.h + +Tested-by: Peter Chiu +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/71d8b581fe4b5abc5b92f8d77ac2de3e2f7591b6.1629741512.git.lorenzo@kernel.org +Signed-off-by: Johannes Berg +--- + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -1088,6 +1088,48 @@ struct ieee80211_ext { + } u; + } __packed __aligned(2); + ++#define IEEE80211_TWT_CONTROL_NDP BIT(0) ++#define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1) ++#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3) ++#define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) ++#define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) ++ ++#define IEEE80211_TWT_REQTYPE_REQUEST BIT(0) ++#define IEEE80211_TWT_REQTYPE_SETUP_CMD GENMASK(3, 1) ++#define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) ++#define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) ++#define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) ++#define IEEE80211_TWT_REQTYPE_FLOWID GENMASK(9, 7) ++#define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP GENMASK(14, 10) ++#define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) ++ ++enum ieee80211_twt_setup_cmd { ++ TWT_SETUP_CMD_REQUEST, ++ TWT_SETUP_CMD_SUGGEST, ++ TWT_SETUP_CMD_DEMAND, ++ TWT_SETUP_CMD_GROUPING, ++ TWT_SETUP_CMD_ACCEPT, ++ TWT_SETUP_CMD_ALTERNATE, ++ TWT_SETUP_CMD_DICTATE, ++ TWT_SETUP_CMD_REJECT, ++}; ++ ++struct ieee80211_twt_params { ++ __le16 req_type; ++ __le64 twt; ++ u8 min_twt_dur; ++ __le16 mantissa; ++ u8 channel; ++} __packed; ++ ++struct ieee80211_twt_setup { ++ u8 dialog_token; ++ u8 element_id; ++ u8 length; ++ u8 control; ++ u8 params[]; ++} __packed; ++ + struct ieee80211_mgmt { + __le16 frame_control; + __le16 duration; +@@ -1252,6 +1294,10 @@ struct ieee80211_mgmt { + __le16 toa_error; + u8 variable[0]; + } __packed ftm; ++ struct { ++ u8 action_code; ++ u8 variable[]; ++ } __packed s1g; + } u; + } __packed action; + } u; +@@ -2880,6 +2926,7 @@ enum ieee80211_eid { + WLAN_EID_AID_RESPONSE = 211, + WLAN_EID_S1G_BCN_COMPAT = 213, + WLAN_EID_S1G_SHORT_BCN_INTERVAL = 214, ++ WLAN_EID_S1G_TWT = 216, + WLAN_EID_S1G_CAPABILITIES = 217, + WLAN_EID_VENDOR_SPECIFIC = 221, + WLAN_EID_QOS_PARAMETER = 222, +@@ -2948,6 +2995,7 @@ enum ieee80211_category { + WLAN_CATEGORY_FST = 18, + WLAN_CATEGORY_UNPROT_DMG = 20, + WLAN_CATEGORY_VHT = 21, ++ WLAN_CATEGORY_S1G = 22, + WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, + WLAN_CATEGORY_VENDOR_SPECIFIC = 127, + }; +@@ -3021,6 +3069,20 @@ enum ieee80211_key_len { + WLAN_KEY_LEN_BIP_GMAC_256 = 32, + }; + ++enum ieee80211_s1g_actioncode { ++ WLAN_S1G_AID_SWITCH_REQUEST, ++ WLAN_S1G_AID_SWITCH_RESPONSE, ++ WLAN_S1G_SYNC_CONTROL, ++ WLAN_S1G_STA_INFO_ANNOUNCE, ++ WLAN_S1G_EDCA_PARAM_SET, ++ WLAN_S1G_EL_OPERATION, ++ WLAN_S1G_TWT_SETUP, ++ WLAN_S1G_TWT_TEARDOWN, ++ WLAN_S1G_SECT_GROUP_ID_LIST, ++ WLAN_S1G_SECT_ID_FEEDBACK, ++ WLAN_S1G_TWT_INFORMATION = 11, ++}; ++ + #define IEEE80211_WEP_IV_LEN 4 + #define IEEE80211_WEP_ICV_LEN 4 + #define IEEE80211_CCMP_HDR_LEN 8 diff --git a/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch new file mode 100644 index 0000000000..dbd98b96cc --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch @@ -0,0 +1,580 @@ +From: Lorenzo Bianconi +Date: Mon, 23 Aug 2021 20:02:39 +0200 +Subject: [PATCH] mac80211: introduce individual TWT support in AP mode + +Introduce TWT action frames parsing support to mac80211. +Currently just individual TWT agreement are support in AP mode. +Whenever the AP receives a TWT action frame from an associated client, +after performing sanity checks, it will notify the underlay driver with +requested parameters in order to check if they are supported and if there +is enough room for a new agreement. The driver is expected to set the +agreement result and report it to mac80211. + +Drivers supporting this have two new callbacks: + - add_twt_setup (mandatory) + - twt_teardown_request (optional) + +mac80211 will send an action frame reply according to the result +reported by the driver. + +Tested-by: Peter Chiu +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/257512f2e22ba42b9f2624942a128dd8f141de4b.1629741512.git.lorenzo@kernel.org +[use le16p_replace_bits(), minor cleanups, use (void *) casts, + fix to use ieee80211_get_he_iftype_cap() correctly] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4219,6 +4219,11 @@ struct ieee80211_ops { + void (*sta_set_decap_offload)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enabled); ++ void (*add_twt_setup)(struct ieee80211_hw *hw, ++ struct ieee80211_sta *sta, ++ struct ieee80211_twt_setup *twt); ++ void (*twt_teardown_request)(struct ieee80211_hw *hw, ++ struct ieee80211_sta *sta, u8 flowid); + }; + + /** +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1429,4 +1429,40 @@ static inline void drv_sta_set_decap_off + trace_drv_return_void(local); + } + ++static inline void drv_add_twt_setup(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ struct ieee80211_twt_setup *twt) ++{ ++ struct ieee80211_twt_params *twt_agrt; ++ ++ might_sleep(); ++ ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ twt_agrt = (void *)twt->params; ++ ++ trace_drv_add_twt_setup(local, sta, twt, twt_agrt); ++ local->ops->add_twt_setup(&local->hw, sta, twt); ++ trace_drv_return_void(local); ++} ++ ++static inline void drv_twt_teardown_request(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ u8 flowid) ++{ ++ might_sleep(); ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ if (!local->ops->twt_teardown_request) ++ return; ++ ++ trace_drv_twt_teardown_request(local, sta, flowid); ++ local->ops->twt_teardown_request(&local->hw, sta, flowid); ++ trace_drv_return_void(local); ++} ++ + #endif /* __MAC80211_DRIVER_OPS */ +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -954,6 +954,7 @@ struct ieee80211_sub_if_data { + + struct work_struct work; + struct sk_buff_head skb_queue; ++ struct sk_buff_head status_queue; + + u8 needed_rx_chains; + enum ieee80211_smps_mode smps_mode; +@@ -2093,6 +2094,11 @@ ieee80211_he_op_ie_to_bss_conf(struct ie + + /* S1G */ + void ieee80211_s1g_sta_rate_init(struct sta_info *sta); ++bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb); ++void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb); ++void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb); + + /* Spectrum management */ + void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -563,6 +563,7 @@ static void ieee80211_do_stop(struct iee + */ + ieee80211_free_keys(sdata, true); + skb_queue_purge(&sdata->skb_queue); ++ skb_queue_purge(&sdata->status_queue); + } + + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); +@@ -1070,6 +1071,7 @@ int ieee80211_add_virtual_monitor(struct + } + + skb_queue_head_init(&sdata->skb_queue); ++ skb_queue_head_init(&sdata->status_queue); + INIT_WORK(&sdata->work, ieee80211_iface_work); + + return 0; +@@ -1442,6 +1444,24 @@ static void ieee80211_if_setup_no_queue( + #endif + } + ++static void ieee80211_iface_process_status(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (void *)skb->data; ++ ++ if (ieee80211_is_action(mgmt->frame_control) && ++ mgmt->u.action.category == WLAN_CATEGORY_S1G) { ++ switch (mgmt->u.action.u.s1g.action_code) { ++ case WLAN_S1G_TWT_TEARDOWN: ++ case WLAN_S1G_TWT_SETUP: ++ ieee80211_s1g_status_twt_action(sdata, skb); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ + static void ieee80211_iface_work(struct work_struct *work) + { + struct ieee80211_sub_if_data *sdata = +@@ -1519,6 +1539,16 @@ static void ieee80211_iface_work(struct + WARN_ON(1); + break; + } ++ } else if (ieee80211_is_action(mgmt->frame_control) && ++ mgmt->u.action.category == WLAN_CATEGORY_S1G) { ++ switch (mgmt->u.action.u.s1g.action_code) { ++ case WLAN_S1G_TWT_TEARDOWN: ++ case WLAN_S1G_TWT_SETUP: ++ ieee80211_s1g_rx_twt_action(sdata, skb); ++ break; ++ default: ++ break; ++ } + } else if (ieee80211_is_ext(mgmt->frame_control)) { + if (sdata->vif.type == NL80211_IFTYPE_STATION) + ieee80211_sta_rx_queued_ext(sdata, skb); +@@ -1574,6 +1604,16 @@ static void ieee80211_iface_work(struct + kfree_skb(skb); + } + ++ /* process status queue */ ++ while ((skb = skb_dequeue(&sdata->status_queue))) { ++ kcov_remote_start_common(skb_get_kcov_handle(skb)); ++ ++ ieee80211_iface_process_status(sdata, skb); ++ kfree_skb(skb); ++ ++ kcov_remote_stop(); ++ } ++ + /* then other type-dependent work */ + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: +@@ -1637,6 +1677,7 @@ static void ieee80211_setup_sdata(struct + } + + skb_queue_head_init(&sdata->skb_queue); ++ skb_queue_head_init(&sdata->status_queue); + INIT_WORK(&sdata->work, ieee80211_iface_work); + INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); + INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work); +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3208,6 +3208,68 @@ ieee80211_rx_h_mgmt_check(struct ieee802 + return RX_CONTINUE; + } + ++static bool ++ieee80211_process_rx_twt_action(struct ieee80211_rx_data *rx) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)rx->skb->data; ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); ++ struct ieee80211_sub_if_data *sdata = rx->sdata; ++ const struct ieee80211_sta_he_cap *hecap; ++ struct ieee80211_supported_band *sband; ++ ++ /* TWT actions are only supported in AP for the moment */ ++ if (sdata->vif.type != NL80211_IFTYPE_AP) ++ return false; ++ ++ if (!rx->local->ops->add_twt_setup) ++ return false; ++ ++ sband = rx->local->hw.wiphy->bands[status->band]; ++ hecap = ieee80211_get_he_iftype_cap(sband, ++ ieee80211_vif_type_p2p(&sdata->vif)); ++ if (!hecap) ++ return false; ++ ++ if (!(hecap->he_cap_elem.mac_cap_info[0] & ++ IEEE80211_HE_MAC_CAP0_TWT_RES)) ++ return false; ++ ++ if (!rx->sta) ++ return false; ++ ++ switch (mgmt->u.action.u.s1g.action_code) { ++ case WLAN_S1G_TWT_SETUP: { ++ struct ieee80211_twt_setup *twt; ++ ++ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + ++ 1 + /* action code */ ++ sizeof(struct ieee80211_twt_setup) + ++ 2 /* TWT req_type agrt */) ++ break; ++ ++ twt = (void *)mgmt->u.action.u.s1g.variable; ++ if (twt->element_id != WLAN_EID_S1G_TWT) ++ break; ++ ++ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + ++ 4 + /* action code + token + tlv */ ++ twt->length) ++ break; ++ ++ return true; /* queue the frame */ ++ } ++ case WLAN_S1G_TWT_TEARDOWN: ++ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + 2) ++ break; ++ ++ return true; /* queue the frame */ ++ default: ++ break; ++ } ++ ++ return false; ++} ++ + static ieee80211_rx_result debug_noinline + ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + { +@@ -3487,6 +3549,17 @@ ieee80211_rx_h_action(struct ieee80211_r + !mesh_path_sel_is_hwmp(sdata)) + break; + goto queue; ++ case WLAN_CATEGORY_S1G: ++ switch (mgmt->u.action.u.s1g.action_code) { ++ case WLAN_S1G_TWT_SETUP: ++ case WLAN_S1G_TWT_TEARDOWN: ++ if (ieee80211_process_rx_twt_action(rx)) ++ goto queue; ++ break; ++ default: ++ break; ++ } ++ break; + } + + return RX_CONTINUE; +--- a/net/mac80211/s1g.c ++++ b/net/mac80211/s1g.c +@@ -6,6 +6,7 @@ + #include + #include + #include "ieee80211_i.h" ++#include "driver-ops.h" + + void ieee80211_s1g_sta_rate_init(struct sta_info *sta) + { +@@ -14,3 +15,182 @@ void ieee80211_s1g_sta_rate_init(struct + sta->rx_stats.last_rate = + STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G); + } ++ ++bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ ++ if (likely(!ieee80211_is_action(mgmt->frame_control))) ++ return false; ++ ++ if (likely(mgmt->u.action.category != WLAN_CATEGORY_S1G)) ++ return false; ++ ++ return mgmt->u.action.u.s1g.action_code == WLAN_S1G_TWT_SETUP; ++} ++ ++static void ++ieee80211_s1g_send_twt_setup(struct ieee80211_sub_if_data *sdata, const u8 *da, ++ const u8 *bssid, struct ieee80211_twt_setup *twt) ++{ ++ int len = IEEE80211_MIN_ACTION_SIZE + 4 + twt->length; ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_mgmt *mgmt; ++ struct sk_buff *skb; ++ ++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); ++ if (!skb) ++ return; ++ ++ skb_reserve(skb, local->hw.extra_tx_headroom); ++ mgmt = skb_put_zero(skb, len); ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | ++ IEEE80211_STYPE_ACTION); ++ memcpy(mgmt->da, da, ETH_ALEN); ++ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); ++ memcpy(mgmt->bssid, bssid, ETH_ALEN); ++ ++ mgmt->u.action.category = WLAN_CATEGORY_S1G; ++ mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_SETUP; ++ memcpy(mgmt->u.action.u.s1g.variable, twt, 3 + twt->length); ++ ++ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | ++ IEEE80211_TX_INTFL_MLME_CONN_TX | ++ IEEE80211_TX_CTL_REQ_TX_STATUS; ++ ieee80211_tx_skb(sdata, skb); ++} ++ ++static void ++ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata, ++ const u8 *da, const u8 *bssid, u8 flowid) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_mgmt *mgmt; ++ struct sk_buff *skb; ++ u8 *id; ++ ++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + ++ IEEE80211_MIN_ACTION_SIZE + 2); ++ if (!skb) ++ return; ++ ++ skb_reserve(skb, local->hw.extra_tx_headroom); ++ mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE + 2); ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | ++ IEEE80211_STYPE_ACTION); ++ memcpy(mgmt->da, da, ETH_ALEN); ++ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); ++ memcpy(mgmt->bssid, bssid, ETH_ALEN); ++ ++ mgmt->u.action.category = WLAN_CATEGORY_S1G; ++ mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_TEARDOWN; ++ id = (u8 *)mgmt->u.action.u.s1g.variable; ++ *id = flowid; ++ ++ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | ++ IEEE80211_TX_CTL_REQ_TX_STATUS; ++ ieee80211_tx_skb(sdata, skb); ++} ++ ++static void ++ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (void *)skb->data; ++ struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable; ++ struct ieee80211_twt_params *twt_agrt = (void *)twt->params; ++ ++ twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST); ++ ++ /* broadcast TWT not supported yet */ ++ if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) { ++ le16p_replace_bits(&twt_agrt->req_type, ++ TWT_SETUP_CMD_REJECT, ++ IEEE80211_TWT_REQTYPE_SETUP_CMD); ++ goto out; ++ } ++ ++ drv_add_twt_setup(sdata->local, sdata, &sta->sta, twt); ++out: ++ ieee80211_s1g_send_twt_setup(sdata, mgmt->sa, sdata->vif.addr, twt); ++} ++ ++static void ++ieee80211_s1g_rx_twt_teardown(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ ++ drv_twt_teardown_request(sdata->local, sdata, &sta->sta, ++ mgmt->u.action.u.s1g.variable[0]); ++} ++ ++static void ++ieee80211_s1g_tx_twt_setup_fail(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable; ++ struct ieee80211_twt_params *twt_agrt = (void *)twt->params; ++ u8 flowid = le16_get_bits(twt_agrt->req_type, ++ IEEE80211_TWT_REQTYPE_FLOWID); ++ ++ drv_twt_teardown_request(sdata->local, sdata, &sta->sta, flowid); ++ ++ ieee80211_s1g_send_twt_teardown(sdata, mgmt->sa, sdata->vif.addr, ++ flowid); ++} ++ ++void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ struct ieee80211_local *local = sdata->local; ++ struct sta_info *sta; ++ ++ mutex_lock(&local->sta_mtx); ++ ++ sta = sta_info_get_bss(sdata, mgmt->sa); ++ if (!sta) ++ goto out; ++ ++ switch (mgmt->u.action.u.s1g.action_code) { ++ case WLAN_S1G_TWT_SETUP: ++ ieee80211_s1g_rx_twt_setup(sdata, sta, skb); ++ break; ++ case WLAN_S1G_TWT_TEARDOWN: ++ ieee80211_s1g_rx_twt_teardown(sdata, sta, skb); ++ break; ++ default: ++ break; ++ } ++ ++out: ++ mutex_unlock(&local->sta_mtx); ++} ++ ++void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ struct ieee80211_local *local = sdata->local; ++ struct sta_info *sta; ++ ++ mutex_lock(&local->sta_mtx); ++ ++ sta = sta_info_get_bss(sdata, mgmt->da); ++ if (!sta) ++ goto out; ++ ++ switch (mgmt->u.action.u.s1g.action_code) { ++ case WLAN_S1G_TWT_SETUP: ++ /* process failed twt setup frames */ ++ ieee80211_s1g_tx_twt_setup_fail(sdata, sta, skb); ++ break; ++ default: ++ break; ++ } ++ ++out: ++ mutex_unlock(&local->sta_mtx); ++} +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -705,13 +705,26 @@ static void ieee80211_report_used_skb(st + /* Check to see if packet is a TDLS teardown packet */ + if (ieee80211_is_data(hdr->frame_control) && + (ieee80211_get_tdls_action(skb, hdr_size) == +- WLAN_TDLS_TEARDOWN)) ++ WLAN_TDLS_TEARDOWN)) { + ieee80211_tdls_td_tx_handle(local, sdata, skb, + info->flags); +- else ++ } else if (ieee80211_s1g_is_twt_setup(skb)) { ++ if (!acked) { ++ struct sk_buff *qskb; ++ ++ qskb = skb_clone(skb, GFP_ATOMIC); ++ if (qskb) { ++ skb_queue_tail(&sdata->status_queue, ++ qskb); ++ ieee80211_queue_work(&local->hw, ++ &sdata->work); ++ } ++ } ++ } else { + ieee80211_mgd_conn_tx_status(sdata, + hdr->frame_control, + acked); ++ } + } + + rcu_read_unlock(); +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -2804,6 +2804,73 @@ DEFINE_EVENT(sta_flag_evt, drv_sta_set_d + TP_ARGS(local, sdata, sta, enabled) + ); + ++TRACE_EVENT(drv_add_twt_setup, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sta *sta, ++ struct ieee80211_twt_setup *twt, ++ struct ieee80211_twt_params *twt_agrt), ++ ++ TP_ARGS(local, sta, twt, twt_agrt), ++ ++ TP_STRUCT__entry( ++ LOCAL_ENTRY ++ STA_ENTRY ++ __field(u8, dialog_token) ++ __field(u8, control) ++ __field(__le16, req_type) ++ __field(__le64, twt) ++ __field(u8, duration) ++ __field(__le16, mantissa) ++ __field(u8, channel) ++ ), ++ ++ TP_fast_assign( ++ LOCAL_ASSIGN; ++ STA_ASSIGN; ++ __entry->dialog_token = twt->dialog_token; ++ __entry->control = twt->control; ++ __entry->req_type = twt_agrt->req_type; ++ __entry->twt = twt_agrt->twt; ++ __entry->duration = twt_agrt->min_twt_dur; ++ __entry->mantissa = twt_agrt->mantissa; ++ __entry->channel = twt_agrt->channel; ++ ), ++ ++ TP_printk( ++ LOCAL_PR_FMT STA_PR_FMT ++ " token:%d control:0x%02x req_type:0x%04x" ++ " twt:%llu duration:%d mantissa:%d channel:%d", ++ LOCAL_PR_ARG, STA_PR_ARG, __entry->dialog_token, ++ __entry->control, le16_to_cpu(__entry->req_type), ++ le64_to_cpu(__entry->twt), __entry->duration, ++ le16_to_cpu(__entry->mantissa), __entry->channel ++ ) ++); ++ ++TRACE_EVENT(drv_twt_teardown_request, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sta *sta, u8 flowid), ++ ++ TP_ARGS(local, sta, flowid), ++ ++ TP_STRUCT__entry( ++ LOCAL_ENTRY ++ STA_ENTRY ++ __field(u8, flowid) ++ ), ++ ++ TP_fast_assign( ++ LOCAL_ASSIGN; ++ STA_ASSIGN; ++ __entry->flowid = flowid; ++ ), ++ ++ TP_printk( ++ LOCAL_PR_FMT STA_PR_FMT " flowid:%d", ++ LOCAL_PR_ARG, STA_PR_ARG, __entry->flowid ++ ) ++); ++ + #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ + + #undef TRACE_INCLUDE_PATH diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch index 2755efb194..6f13f64208 100644 --- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch @@ -87,7 +87,7 @@ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1434,6 +1434,7 @@ struct ieee80211_local { +@@ -1435,6 +1435,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */ From 4f2fd0215b4a125d84ccedde6d6fa323e56bd404 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Oct 2021 13:26:39 +0200 Subject: [PATCH 57/59] mt76: update to the latest version 74dedf9352c5 mt76: mt7615: fix skb use-after-free on mac reset 7201290eda43 mt76: mt7921: Fix out of order process by invalid event pkt ca1b57e9971a mt76: mt7915: add a missing HT flag for GI parsing 4932c5d80153 of: net: pass the dst buffer to of_get_mac_address() 51d9eb3e6f52 mt76: mt7915: fix endianness warnings in mu radiotap 833ca13014ab mt76: mt7921: Add mt7922 support 8f8ed44d026e mt76: mt7915: add control knobs for thermal throttling 16f18bab6b11 mt76: mt7915: send EAPOL frames at lowest rate affea639c586 mt76: mt7921: send EAPOL frames at lowest rate ac00fed412d4 mt76: mt7915: fix potential overflow of eeprom page index [update] e576ddb76dfa mt76: mt7915: switch proper tx arbiter mode in testmode 222847c3d5eb mt76: mt7915: fix bit fields for HT rate idx d04814366c83 mt76: add support for setting mcast rate 4602acc9271a mt76: mt7921: fix dma hang in rmmod ec2cf3bf96fd mt76: connac: fix GTK rekey offload failure on WPA mixed mode 2fdb9d621431 mt76: connac: add support for limiting to maximum regulatory Tx power 489ace63d42c mt76: mt7921: get rid of monitor_vif 22da8d28fcc8 mt76: mt7921: get rid of mt7921_mac_set_beacon_filter c94130519786 mt76: mt7921: introduce mt7921_mcu_set_beacon_filter utility routine 51cff39d7ad3 mt76: overwrite default reg_ops if necessary da11c1c6edef mt76: mt7615: move mt7615_mcu_set_p2p_oppps in mt76_connac module 47f50b0aa4b8 mt76: mt7921: report HE MU radiotap 4f48ba4b0254 mt76: mt7915: checkpatch cleanup bc7ee7d7bdea mt76: mt7915: add HE-LTF into fixed rate command 6a19e40820aa mt76: mt7921: continue to probe driver when fw already downloaded 8b3d8e2de084 mt76: mt7921: fix firmware usage of RA info using legacy rates 17305a54b166 mt76: mt7921: fix kernel warning from cfg80211_calculate_bitrate 801c15577293 mt76: mt7921: fix endianness warnings in mt7921_mac_decode_he_mu_radiotap 0182a5b99a7a mt76: mt7915: update mac timing settings e2ee9d0a33ed mt76: use IEEE80211_OFFLOAD_ENCAP_ENABLED instead of MT_DRV_AMSDU_OFFLOAD fa6504aceb4f Revert "mt76: mt7915: checkpatch cleanup" 56b842b72a72 mt76: mt7915: fix wmm index on DBDC cards 8044311f5de5 mt76: mt7915: fix potential NPE in TXS processing 28da4baec7c5 mt76: mt7915: fix he_mcs capabilities for 160mhz f7088ebe7452 mt76: mt7915: add LED support ee019046284d mt76: mt7915: introduce bss coloring support 9848094e4bb5 mt76: mt7921: Fix fall-through warning for Clang 5710d0643418 mt76: add a bound check in mt76_calculate_default_rate() a509cf2b654e mt76: mt7921: move mt7921_queue_rx_skb to mac.c 5a0f2382fcfe mt76: mt7915: rework debugfs queue info 62ffc31f4d7b mt76: mt7915: rename debugfs tx-queues 4750b5c918e5 mt76: mt7921: always wake device if necessary in debugfs ac6adf74b3f2 mt76: mt7921: update mib counters dumping phy stats eb75b9266ce6 net:wireless:mt76: fix boolreturn.cocci warnings d7c4698435b3 mt76: mt7921: fix the inconsistent state between bind and unbind 9dcfba3169c4 mt76: switch from 'pci_' to 'dma_' API d8b5e42c9a73 mt76: fill boottime_ns in Rx path 8ee6446075f2 mt76: disable BH around napi_schedule() calls e17d730bf2f6 mt76: mt7915: add LED support [update to v3] 80fe40c9457e mt76: mt7915: enable configured beacon tx rate c8f0d1d81d05 mt76: mt7915: fix hwmon temp sensor mem use-after-free 3b9ba7e02076 mt76: mt7615: fix hwmon temp sensor mem use-after-free 5e82eceb45cb mt76: mt7921: start reworking tx rate reporting eb66b5c9ff77 mt76: mt7921: add support for tx status reporting c8010f170e76 mt76: mt7921: report tx rate directly from tx status 4dc7f3db572b mt76: mt7921: remove mcu rate reporting code db89c6f86724 mt76: mt7921: remove mt7921_sta_stats 6bb8b4267dbe mt76: move spin_lock_bh to spin_lock in tasklet 0eacf41985da mt76: mt7915: honor all possible error conditions in mt7915_mcu_init() 4dfff296ee6e mt76: mt7915: fix possible infinite loop release semaphore 537ed88dd2d0 mt76: mt7921: robustify hardware initialization flow e0b846159221 mt76: mt7921: fix retrying release semaphore without end c55dedcea268 mt76: mt7915: add ethtool stats support d1d5e8cd3a3e mt76: mt7915: add tx stats gathered from tx-status callbacks 1687189d68b7 mt76: mt7915: add some per-station tx stats to ethtool f4dde5f765af mt76: mt7915: add tx mu/su counters to mib 9752bf0643c9 mt76: mt7915: add more MIB registers 4727415017c9 mt76: mt7915: add mib counters to ethtool stats 4ca80a749e7f mt76: connac: set 6G phymode in mt76_connac_get_phy_mode{,v2} 3f2a5d39631e mt76: connac: enable 6GHz band for hw scan 817a41826bd7 mt76: connac: add 6GHz support to mt76_connac_mcu_set_channel_domain a6ab81c21080 mt76: connac: set 6G phymode in single-sku support ca4f47028a44 mt76: connac: add 6GHz support to mt76_connac_mcu_sta_tlv d2e192ea81e2 mt76: connac: add 6GHz support to mt76_connac_mcu_uni_add_bss c3dd12b4c8ae mt76: connac: enable hw amsdu @ 6GHz 91ed2b256c20 mt76: add 6GHz support de8c4f92621f mt76: mt7921: add 6GHz support f143aedc1d57 mt76: introduce packet_id idr bcc8d9e03a5d mt76: remove mt76_wcid pointer from mt76_tx_status_check signature ccbd84763153 mt76: substitute sk_buff_head status_list with spinlock_t status_lock 69bb59df894c mt76: schedule status timeout at dma completion 03a992645310 mt76: support reading EEPROM data embedded in fdt 75615480b3fe mt76: introduce __mt76_mcu_send_firmware routine e8e2eae41f94 mt76: drop MCU header size from buffer size in __mt76_mcu_send_firmware 4c455e8b1a20 mt76: mt7915: introduce __mt7915_get_tsf routine 9d49c611a2d7 mt76: mt7915: introduce mt7915_mcu_twt_agrt_update mcu command f44ca79c9aed mt76: mt7915: introduce mt7915_mac_add_twt_setup routine 2f9555a2f18f mt76: mt7915: enable twt responder capability 440e2db8d541 mt76: mt7915: add twt_stats knob in debugfs eb5f640f8afa mt76: debugfs: improve queue node readability 53d7eb3b4884 mt76: mt7615: fix monitor mode tear down crash 2aa3d4414826 mt76: mt7921: add delay config for sched scan 47e8e96e8e4d mt76: use a separate CCMP PN receive counter for management frames 5560b08f8e2d mt76: do not access 802.11 header in ccmp check for 802.3 rx skbs Signed-off-by: Felix Fietkau --- package/kernel/mt76/Makefile | 6 +- ...the-dst-buffer-to-of_get_mac_address.patch | 206 ------------------ 2 files changed, 3 insertions(+), 209 deletions(-) delete mode 100644 package/kernel/mt76/patches/001-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 431c57a240..824b775084 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-07-15 -PKG_SOURCE_VERSION:=bbebea7d6dc64313132226adc3f7369d36e9359d -PKG_MIRROR_HASH:=17cd74e72c1f6c8742b698bf6772afacc6fba71b233af8c4d59530600cf44d5b +PKG_SOURCE_DATE:=2021-10-11 +PKG_SOURCE_VERSION:=5560b08f8e2dfe92aa920a9cf3c5655a309dd25b +PKG_MIRROR_HASH:=36359a85325a60230838e38e087f9aecc49cf7abca0ef55b2dbee86cf9194425 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 diff --git a/package/kernel/mt76/patches/001-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch b/package/kernel/mt76/patches/001-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch deleted file mode 100644 index 66075f2771..0000000000 --- a/package/kernel/mt76/patches/001-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch +++ /dev/null @@ -1,206 +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(-) - -diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c -index 665b54c5c8ae5..6d895738222ad 100644 ---- a/eeprom.c -+++ b/eeprom.c -@@ -91,15 +91,9 @@ void - { - struct mt76_dev *dev = phy->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(phy->macaddr, mac); --#endif -+ of_get_mac_address(np, phy->macaddr); - - if (!is_valid_ether_addr(phy->macaddr)) { - eth_random_addr(phy->macaddr); --- -cgit 1.2.3-1.el7 - From af9d31aacc286786a8765a44c2000d2eba02e61c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Oct 2021 16:40:20 +0200 Subject: [PATCH 58/59] mac80211: remove kcov bits from TWT backport patch Our backports version does not have support for kcov in mac80211 Fixes build errors on some platforms Signed-off-by: Felix Fietkau --- ...c80211-introduce-individual-TWT-support-in-AP-mode.patch | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch index dbd98b96cc..cdee132f15 100644 --- a/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch +++ b/package/kernel/mac80211/patches/subsys/390-mac80211-introduce-individual-TWT-support-in-AP-mode.patch @@ -164,18 +164,14 @@ Signed-off-by: Johannes Berg } else if (ieee80211_is_ext(mgmt->frame_control)) { if (sdata->vif.type == NL80211_IFTYPE_STATION) ieee80211_sta_rx_queued_ext(sdata, skb); -@@ -1574,6 +1604,16 @@ static void ieee80211_iface_work(struct +@@ -1574,6 +1604,12 @@ static void ieee80211_iface_work(struct kfree_skb(skb); } + /* process status queue */ + while ((skb = skb_dequeue(&sdata->status_queue))) { -+ kcov_remote_start_common(skb_get_kcov_handle(skb)); -+ + ieee80211_iface_process_status(sdata, skb); + kfree_skb(skb); -+ -+ kcov_remote_stop(); + } + /* then other type-dependent work */ From 9d994f35b4acc5243209d837b0730f9543ed533e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 11 Oct 2021 21:54:13 +0200 Subject: [PATCH 59/59] mt76: update to the latest version 1af0242d1241 mt76: mt7915: replace a 64 bit divsion with a call to div_u64_rem Signed-off-by: Felix Fietkau --- package/kernel/mt76/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 824b775084..511960ce9b 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -9,8 +9,8 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git PKG_SOURCE_DATE:=2021-10-11 -PKG_SOURCE_VERSION:=5560b08f8e2dfe92aa920a9cf3c5655a309dd25b -PKG_MIRROR_HASH:=36359a85325a60230838e38e087f9aecc49cf7abca0ef55b2dbee86cf9194425 +PKG_SOURCE_VERSION:=1af0242d1241cba761415c492e5ed9673beaa13f +PKG_MIRROR_HASH:=39346f1ef24fbd62f447fc116e1ed411dc2b60787a3df9edfe048adc79150232 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0