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 <hauke@hauke-m.de>
This commit is contained in:
parent
53ab9865c2
commit
1e95f9b3ea
5 changed files with 183 additions and 4 deletions
|
@ -232,6 +232,8 @@
|
||||||
pll-handle = <&pll>;
|
pll-handle = <&pll>;
|
||||||
resets = <&rst 9>, <&rst 22>;
|
resets = <&rst 9>, <&rst 22>;
|
||||||
reset-names = "mac", "mdio";
|
reset-names = "mac", "mdio";
|
||||||
|
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
|
||||||
|
clock-names = "eth", "mdio";
|
||||||
};
|
};
|
||||||
|
|
||||||
&mdio1 {
|
&mdio1 {
|
||||||
|
@ -272,8 +274,10 @@
|
||||||
ð1 {
|
ð1 {
|
||||||
compatible = "qca,ar9340-eth", "syscon";
|
compatible = "qca,ar9340-eth", "syscon";
|
||||||
|
|
||||||
resets = <&rst 13>;
|
resets = <&rst 13>, <&rst 23>;
|
||||||
reset-names = "mac";
|
reset-names = "mac", "mdio";
|
||||||
|
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
|
||||||
|
clock-names = "eth", "mdio";
|
||||||
phy-mode = "gmii";
|
phy-mode = "gmii";
|
||||||
|
|
||||||
fixed-link {
|
fixed-link {
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
interrupts = <4>;
|
interrupts = <4>;
|
||||||
phy-mode = "mii";
|
phy-mode = "mii";
|
||||||
|
|
||||||
mdio0: mdio-bus {
|
mdio0: mdio {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
compatible = "qca,ath79-mdio";
|
compatible = "qca,ath79-mdio";
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
interrupts = <5>;
|
interrupts = <5>;
|
||||||
phy-mode = "mii";
|
phy-mode = "mii";
|
||||||
|
|
||||||
mdio1: mdio-bus {
|
mdio1: mdio {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
compatible = "qca,ath79-mdio";
|
compatible = "qca,ath79-mdio";
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
From 2cee757eaf5cc6175bc0ac7b0b808794124ec40a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||||
|
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 <hauke@hauke-m.de>
|
||||||
|
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)
|
|
@ -0,0 +1,45 @@
|
||||||
|
From 2f8c5a68d0030ae5e65fca1bf5ca44929d5b3b06 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||||
|
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 <hauke@hauke-m.de>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
From d42c6bf2752a46bdf3931bd6e56db419742fbb20 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||||
|
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 <hauke@hauke-m.de>
|
||||||
|
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)
|
Loading…
Reference in a new issue