From 1e95f9b3ea8375931bf82b8d102b9410d6eafcfa Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 18 Feb 2020 00:36:28 +0100 Subject: [PATCH] ath79: Make upstream ag71xx driver work * Fix some bugs in the driver * Add missing clock and reset references in dts * Rename mdio-bus to mdio so the driver find it Signed-off-by: Hauke Mehrtens --- target/linux/ath79/dts/ar934x.dtsi | 8 ++- target/linux/ath79/dts/ath79.dtsi | 4 +- ...location-errors-in-ag71xx_rings_init.patch | 61 ++++++++++++++++ ...xx_hw_disable-in-case-phy_conenct-fa.patch | 45 ++++++++++++ ...-ag71xx_link_adjust-only-when-needed.patch | 69 +++++++++++++++++++ 5 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 target/linux/ath79/patches-5.4/200-ag71xx-Handle-allocation-errors-in-ag71xx_rings_init.patch create mode 100644 target/linux/ath79/patches-5.4/201-ag71xx-Call-ag71xx_hw_disable-in-case-phy_conenct-fa.patch create mode 100644 target/linux/ath79/patches-5.4/202-ag71xx-Run-ag71xx_link_adjust-only-when-needed.patch diff --git a/target/linux/ath79/dts/ar934x.dtsi b/target/linux/ath79/dts/ar934x.dtsi index e8c21fb710..0451960a60 100644 --- a/target/linux/ath79/dts/ar934x.dtsi +++ b/target/linux/ath79/dts/ar934x.dtsi @@ -232,6 +232,8 @@ pll-handle = <&pll>; resets = <&rst 9>, <&rst 22>; reset-names = "mac", "mdio"; + clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>; + clock-names = "eth", "mdio"; }; &mdio1 { @@ -272,8 +274,10 @@ ð1 { compatible = "qca,ar9340-eth", "syscon"; - resets = <&rst 13>; - reset-names = "mac"; + resets = <&rst 13>, <&rst 23>; + reset-names = "mac", "mdio"; + clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>; + clock-names = "eth", "mdio"; phy-mode = "gmii"; fixed-link { diff --git a/target/linux/ath79/dts/ath79.dtsi b/target/linux/ath79/dts/ath79.dtsi index c351272025..1d1424590c 100644 --- a/target/linux/ath79/dts/ath79.dtsi +++ b/target/linux/ath79/dts/ath79.dtsi @@ -49,7 +49,7 @@ interrupts = <4>; phy-mode = "mii"; - mdio0: mdio-bus { + mdio0: mdio { status = "disabled"; compatible = "qca,ath79-mdio"; @@ -72,7 +72,7 @@ interrupts = <5>; phy-mode = "mii"; - mdio1: mdio-bus { + mdio1: mdio { status = "disabled"; compatible = "qca,ath79-mdio"; diff --git a/target/linux/ath79/patches-5.4/200-ag71xx-Handle-allocation-errors-in-ag71xx_rings_init.patch b/target/linux/ath79/patches-5.4/200-ag71xx-Handle-allocation-errors-in-ag71xx_rings_init.patch new file mode 100644 index 0000000000..6631cb8e17 --- /dev/null +++ b/target/linux/ath79/patches-5.4/200-ag71xx-Handle-allocation-errors-in-ag71xx_rings_init.patch @@ -0,0 +1,61 @@ +From 2cee757eaf5cc6175bc0ac7b0b808794124ec40a Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 17 Feb 2020 23:40:14 +0100 +Subject: [PATCH 1/3] ag71xx: Handle allocation errors in ag71xx_rings_init() + +Free the allocated resources in ag71xx_rings_init() in case +ag71xx_ring_rx_init() returns an error. + +This is only a potential problem, I did not ran into this one. + +Signed-off-by: Hauke Mehrtens +Fixes: d51b6ce441d3 ("net: ethernet: add ag71xx driver") +--- + drivers/net/ethernet/atheros/ag71xx.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -1133,6 +1133,7 @@ static int ag71xx_rings_init(struct ag71 + struct ag71xx_ring *tx = &ag->tx_ring; + struct ag71xx_ring *rx = &ag->rx_ring; + int ring_size, tx_size; ++ int ret; + + ring_size = BIT(tx->order) + BIT(rx->order); + tx_size = BIT(tx->order); +@@ -1145,9 +1146,8 @@ static int ag71xx_rings_init(struct ag71 + ring_size * AG71XX_DESC_SIZE, + &tx->descs_dma, GFP_KERNEL); + if (!tx->descs_cpu) { +- kfree(tx->buf); +- tx->buf = NULL; +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto err_free_buf; + } + + rx->buf = &tx->buf[tx_size]; +@@ -1155,7 +1155,21 @@ static int ag71xx_rings_init(struct ag71 + rx->descs_dma = tx->descs_dma + tx_size * AG71XX_DESC_SIZE; + + ag71xx_ring_tx_init(ag); +- return ag71xx_ring_rx_init(ag); ++ ret = ag71xx_ring_rx_init(ag); ++ if (ret) ++ goto err_free_dma; ++ ++ return 0; ++ ++err_free_dma: ++ dma_free_coherent(&ag->pdev->dev, ring_size * AG71XX_DESC_SIZE, ++ tx->descs_cpu, tx->descs_dma); ++ rx->buf = NULL; ++err_free_buf: ++ kfree(tx->buf); ++ tx->buf = NULL; ++ ++ return ret; + } + + static void ag71xx_rings_free(struct ag71xx *ag) diff --git a/target/linux/ath79/patches-5.4/201-ag71xx-Call-ag71xx_hw_disable-in-case-phy_conenct-fa.patch b/target/linux/ath79/patches-5.4/201-ag71xx-Call-ag71xx_hw_disable-in-case-phy_conenct-fa.patch new file mode 100644 index 0000000000..16d60a4e0c --- /dev/null +++ b/target/linux/ath79/patches-5.4/201-ag71xx-Call-ag71xx_hw_disable-in-case-phy_conenct-fa.patch @@ -0,0 +1,45 @@ +From 2f8c5a68d0030ae5e65fca1bf5ca44929d5b3b06 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 17 Feb 2020 23:50:23 +0100 +Subject: [PATCH 2/3] ag71xx: Call ag71xx_hw_disable() in case phy_conenct + fails + +When the ag71xx_phy_connect() failed only parts of the actions done +previously in this function wrere reverted, because only +ag71xx_rings_cleanup() was called. My system crashed the next time +open() was called because napi_disable() was not called again and this +resulted in two calls to napi_enable(), which is not allowed. + +Fix this by disabling the device again. + +Signed-off-by: Hauke Mehrtens +Fixes: d51b6ce441d3 ("net: ethernet: add ag71xx driver") +--- + drivers/net/ethernet/atheros/ag71xx.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -1263,18 +1263,18 @@ static int ag71xx_open(struct net_device + + ret = ag71xx_hw_enable(ag); + if (ret) +- goto err; ++ return ret; + + ret = ag71xx_phy_connect(ag); + if (ret) +- goto err; ++ goto err_hw_disable; + + phy_start(ndev->phydev); + + return 0; + +-err: +- ag71xx_rings_cleanup(ag); ++err_hw_disable: ++ ag71xx_hw_disable(ag); + return ret; + } + diff --git a/target/linux/ath79/patches-5.4/202-ag71xx-Run-ag71xx_link_adjust-only-when-needed.patch b/target/linux/ath79/patches-5.4/202-ag71xx-Run-ag71xx_link_adjust-only-when-needed.patch new file mode 100644 index 0000000000..00f34dffa1 --- /dev/null +++ b/target/linux/ath79/patches-5.4/202-ag71xx-Run-ag71xx_link_adjust-only-when-needed.patch @@ -0,0 +1,69 @@ +From d42c6bf2752a46bdf3931bd6e56db419742fbb20 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 17 Feb 2020 23:55:22 +0100 +Subject: [PATCH 3/3] ag71xx: Run ag71xx_link_adjust() only when needed + +My system printed this line every second: + ag71xx 19000000.eth eth0: Link is Up - 1Gbps/Full - flow control off +The function ag71xx_phy_link_adjust() was called by the PHY layer every +second even when nothing changed. + +With this patch the old status is stored and the real +ag71xx_link_adjust() function is only called when when something really +changed. This way the update and also this print is only done once any +more. + +Signed-off-by: Hauke Mehrtens +Fixes: d51b6ce441d3 ("net: ethernet: add ag71xx driver") +--- + drivers/net/ethernet/atheros/ag71xx.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -307,6 +307,10 @@ struct ag71xx { + u32 msg_enable; + const struct ag71xx_dcfg *dcfg; + ++ unsigned int link; ++ unsigned int speed; ++ int duplex; ++ + /* From this point onwards we're not looking at per-packet fields. */ + void __iomem *mac_base; + +@@ -854,6 +858,7 @@ static void ag71xx_link_adjust(struct ag + + if (!phydev->link && update) { + ag71xx_hw_stop(ag); ++ phy_print_status(phydev); + return; + } + +@@ -907,8 +912,25 @@ static void ag71xx_link_adjust(struct ag + static void ag71xx_phy_link_adjust(struct net_device *ndev) + { + struct ag71xx *ag = netdev_priv(ndev); ++ struct phy_device *phydev = ndev->phydev; ++ int status_change = 0; ++ ++ if (phydev->link) { ++ if (ag->duplex != phydev->duplex ++ || ag->speed != phydev->speed) { ++ status_change = 1; ++ } ++ } ++ ++ if (phydev->link != ag->link) ++ status_change = 1; ++ ++ ag->link = phydev->link; ++ ag->duplex = phydev->duplex; ++ ag->speed = phydev->speed; + +- ag71xx_link_adjust(ag, true); ++ if (status_change) ++ ag71xx_link_adjust(ag, true); + } + + static int ag71xx_phy_connect(struct ag71xx *ag) -- 2.25.1