diff mbox

[OpenWrt-Devel] ar71xx: fix 100/10mbps ethernet link issues on mynet range extender

Message ID 23125132.vs2gYODNjC@debian64
State Accepted
Headers show

Commit Message

Christian Lamparter June 3, 2015, 3:20 p.m. UTC
The mynet range extender hardware is suffering from ethernet
link loss when booting with a recent openwrt image. This only
happens on 100mbps links, with 1Gbps speed the link was fine.

The cause of the problem is that the AR8035 PHY (aka F1E)
requires turning on and off the special TX delay setting
depending on the speed of the link.

The 10mbps mode only needed the proper pll value, which was
extracted from the vendor code.

Reported-by: Pascal Paradis
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
 .../ar71xx/files/arch/mips/ath79/mach-mynet-rext.c | 20 ++++++++
 ...t-phy-at803x-allow-to-configure-via-pdata.patch | 53 ++++++++++++++++++++--
 2 files changed, 69 insertions(+), 4 deletions(-)

Comments

Dave Täht June 5, 2015, 9:18 p.m. UTC | #1
TX delay setting? What else can it do?

My dream has been to find a way to set the tx completion interrupt
to only return with a soft set rate. So if I had a gigE connection
but my uplink was only 10Mbits, it would return the interrupt
after 1.3ms had expired.

this would let me get away entirely from using software rate limiting
with htb, just program a register once with the uplink rate, and
let bql and fq_codel handle the rest.

On Wed, Jun 03, 2015 at 05:20:22PM +0200, Christian Lamparter wrote:
> The mynet range extender hardware is suffering from ethernet
> link loss when booting with a recent openwrt image. This only
> happens on 100mbps links, with 1Gbps speed the link was fine.
> 
> The cause of the problem is that the AR8035 PHY (aka F1E)
> requires turning on and off the special TX delay setting
> depending on the speed of the link.
> 
> The 10mbps mode only needed the proper pll value, which was
> extracted from the vendor code.
> 
> Reported-by: Pascal Paradis
> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
> ---
>  .../ar71xx/files/arch/mips/ath79/mach-mynet-rext.c | 20 ++++++++
>  ...t-phy-at803x-allow-to-configure-via-pdata.patch | 53 ++++++++++++++++++++--
>  2 files changed, 69 insertions(+), 4 deletions(-)
> 
> diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
> index 02d168e..3d48ca8 100644
> --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
> +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
> @@ -14,6 +14,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/ath9k_platform.h>
>  #include <linux/ar8216_platform.h>
> +#include <linux/platform_data/phy-at803x.h>
>  
>  #include <asm/mach-ath79/ar71xx_regs.h>
>  
> @@ -124,6 +125,21 @@ static struct gpio_keys_button mynet_rext_gpio_keys[] __initdata = {
>  	},
>  };
>  
> +static struct at803x_platform_data mynet_rext_at803x_data = {
> +	.disable_smarteee = 0,
> +	.enable_rgmii_rx_delay = 1,
> +	.enable_rgmii_tx_delay = 0,
> +	.fixup_rgmii_tx_delay = 1,
> +};
> +
> +static struct mdio_board_info mynet_rext_mdio0_info[] = {
> +        {
> +                .bus_id = "ag71xx-mdio.0",
> +                .phy_addr = 4,
> +                .platform_data = &mynet_rext_at803x_data,
> +        },
> +};
> +
>  static void mynet_rext_get_mac(const char *name, char *mac)
>  {
>  	u8 *nvram = (u8 *) KSEG1ADDR(MYNET_REXT_NVRAM_ADDR);
> @@ -169,12 +185,16 @@ static void __init mynet_rext_setup(void)
>  
>  	ath79_register_mdio(0, 0x0);
>  
> +	mdiobus_register_board_info(mynet_rext_mdio0_info,
> +				    ARRAY_SIZE(mynet_rext_mdio0_info));
> +
>  	/* LAN */
>  	mynet_rext_get_mac("et0macaddr=", ath79_eth0_data.mac_addr);
>  
>  	/* GMAC0 is connected to an external PHY on Port 4 */
>  	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
>  	ath79_eth0_data.phy_mask = BIT(4);
> +	ath79_eth0_pll_data.pll_10   = 0x00001313; /* athrs_mac.c */
>  	ath79_eth0_pll_data.pll_1000 = 0x0e000000; /* athrs_mac.c */
>  	ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
>  	ath79_register_eth(0);
> diff --git a/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
> index babc695..d046ede 100644
> --- a/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
> +++ b/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
> @@ -32,6 +32,14 @@
>   #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
>   #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
>   
> +@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
> + struct at803x_priv {
> + 	bool phy_reset:1;
> + 	struct gpio_desc *gpiod_reset;
> ++	int prev_speed;
> + };
> + 
> + struct at803x_context {
>  @@ -61,6 +71,43 @@ struct at803x_context {
>   	u16 led_control;
>   };
> @@ -120,16 +128,53 @@
>   	return 0;
>   }
>   
> +@@ -258,6 +334,8 @@ static int at803x_config_intr(struct phy
> + static void at803x_link_change_notify(struct phy_device *phydev)
> + {
> + 	struct at803x_priv *priv = phydev->priv;
> ++	struct at803x_platform_data *pdata;
> ++	pdata = dev_get_platdata(&phydev->dev);
> + 
> + 	/*
> + 	 * Conduct a hardware reset for AT8030 every time a link loss is
> +@@ -287,6 +365,26 @@ static void at803x_link_change_notify(st
> + 		} else {
> + 			priv->phy_reset = false;
> + 		}
> ++	}
> ++	if (pdata->fixup_rgmii_tx_delay &&
> ++	    phydev->speed != priv->prev_speed) {
> ++		switch (phydev->speed) {
> ++		case SPEED_10:
> ++		case SPEED_100:
> ++			at803x_dbg_reg_set(phydev,
> ++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
> ++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
> ++			break;
> ++		case SPEED_1000:
> ++			at803x_dbg_reg_clr(phydev,
> ++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
> ++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
> ++			break;
> ++		default:
> ++			break;
> ++		}
> ++
> ++		priv->prev_speed = phydev->speed;
> + 	}
> + }
> + 
>  --- /dev/null
>  +++ b/include/linux/platform_data/phy-at803x.h
> -@@ -0,0 +1,10 @@
> +@@ -0,0 +1,11 @@
>  +#ifndef _PHY_AT803X_PDATA_H
>  +#define _PHY_AT803X_PDATA_H
>  +
>  +struct at803x_platform_data {
> -+       int disable_smarteee:1;
> -+       int enable_rgmii_tx_delay:1;
> -+       int enable_rgmii_rx_delay:1;
> ++	int disable_smarteee:1;
> ++	int enable_rgmii_tx_delay:1;
> ++	int enable_rgmii_rx_delay:1;
> ++	int fixup_rgmii_tx_delay:1;
>  +};
>  +
>  +#endif /* _PHY_AT803X_PDATA_H */
> -- 
> 2.1.4
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
Florian Fainelli June 6, 2015, 6:07 a.m. UTC | #2
Florian
On Jun 5, 2015 2:18 PM, "Dave Taht" <dave.taht@bufferbloat.net> wrote:
>
> TX delay setting? What else can it do?

This is a delay between the transmit data lines and the transmit clock on a
RGMII interface. Based on PCB designs, this is something that may have to
be configured to align clock and data lines in a way that does not violate
timings and causes packet losses between the MAC and the PHY. These delays
are not valid when a RGMII interface operates at 10 or 100Mbits/sec since
the clock becomes slow enough the rise and fall times of the data lines are
negligable.

>
> My dream has been to find a way to set the tx completion interrupt
> to only return with a soft set rate. So if I had a gigE connection
> but my uplink was only 10Mbits, it would return the interrupt
> after 1.3ms had expired.

What you are referring to here is interrupt coalescing, which is different
and implemented at the Ethernet MAC and DMA engine levels and not all
controllers support that.

>
> this would let me get away entirely from using software rate limiting
> with htb, just program a register once with the uplink rate, and
> let bql and fq_codel handle the rest.
>
> On Wed, Jun 03, 2015 at 05:20:22PM +0200, Christian Lamparter wrote:
> > The mynet range extender hardware is suffering from ethernet
> > link loss when booting with a recent openwrt image. This only
> > happens on 100mbps links, with 1Gbps speed the link was fine.
> >
> > The cause of the problem is that the AR8035 PHY (aka F1E)
> > requires turning on and off the special TX delay setting
> > depending on the speed of the link.
> >
> > The 10mbps mode only needed the proper pll value, which was
> > extracted from the vendor code.
> >
> > Reported-by: Pascal Paradis
> > Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
> > ---
> >  .../ar71xx/files/arch/mips/ath79/mach-mynet-rext.c | 20 ++++++++
> >  ...t-phy-at803x-allow-to-configure-via-pdata.patch | 53
++++++++++++++++++++--
> >  2 files changed, 69 insertions(+), 4 deletions(-)
> >
> > diff --git
a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
> > index 02d168e..3d48ca8 100644
> > --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
> > +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
> > @@ -14,6 +14,7 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/ath9k_platform.h>
> >  #include <linux/ar8216_platform.h>
> > +#include <linux/platform_data/phy-at803x.h>
> >
> >  #include <asm/mach-ath79/ar71xx_regs.h>
> >
> > @@ -124,6 +125,21 @@ static struct gpio_keys_button
mynet_rext_gpio_keys[] __initdata = {
> >       },
> >  };
> >
> > +static struct at803x_platform_data mynet_rext_at803x_data = {
> > +     .disable_smarteee = 0,
> > +     .enable_rgmii_rx_delay = 1,
> > +     .enable_rgmii_tx_delay = 0,
> > +     .fixup_rgmii_tx_delay = 1,
> > +};
> > +
> > +static struct mdio_board_info mynet_rext_mdio0_info[] = {
> > +        {
> > +                .bus_id = "ag71xx-mdio.0",
> > +                .phy_addr = 4,
> > +                .platform_data = &mynet_rext_at803x_data,
> > +        },
> > +};
> > +
> >  static void mynet_rext_get_mac(const char *name, char *mac)
> >  {
> >       u8 *nvram = (u8 *) KSEG1ADDR(MYNET_REXT_NVRAM_ADDR);
> > @@ -169,12 +185,16 @@ static void __init mynet_rext_setup(void)
> >
> >       ath79_register_mdio(0, 0x0);
> >
> > +     mdiobus_register_board_info(mynet_rext_mdio0_info,
> > +                                 ARRAY_SIZE(mynet_rext_mdio0_info));
> > +
> >       /* LAN */
> >       mynet_rext_get_mac("et0macaddr=", ath79_eth0_data.mac_addr);
> >
> >       /* GMAC0 is connected to an external PHY on Port 4 */
> >       ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
> >       ath79_eth0_data.phy_mask = BIT(4);
> > +     ath79_eth0_pll_data.pll_10   = 0x00001313; /* athrs_mac.c */
> >       ath79_eth0_pll_data.pll_1000 = 0x0e000000; /* athrs_mac.c */
> >       ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
> >       ath79_register_eth(0);
> > diff --git
a/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
b/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
> > index babc695..d046ede 100644
> > ---
a/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
> > +++
b/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
> > @@ -32,6 +32,14 @@
> >   #define AT803X_DEBUG_SYSTEM_MODE_CTRL               0x05
> >   #define AT803X_DEBUG_RGMII_TX_CLK_DLY               BIT(8)
> >
> > +@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
> > + struct at803x_priv {
> > +     bool phy_reset:1;
> > +     struct gpio_desc *gpiod_reset;
> > ++    int prev_speed;
> > + };
> > +
> > + struct at803x_context {
> >  @@ -61,6 +71,43 @@ struct at803x_context {
> >       u16 led_control;
> >   };
> > @@ -120,16 +128,53 @@
> >       return 0;
> >   }
> >
> > +@@ -258,6 +334,8 @@ static int at803x_config_intr(struct phy
> > + static void at803x_link_change_notify(struct phy_device *phydev)
> > + {
> > +     struct at803x_priv *priv = phydev->priv;
> > ++    struct at803x_platform_data *pdata;
> > ++    pdata = dev_get_platdata(&phydev->dev);
> > +
> > +     /*
> > +      * Conduct a hardware reset for AT8030 every time a link loss is
> > +@@ -287,6 +365,26 @@ static void at803x_link_change_notify(st
> > +             } else {
> > +                     priv->phy_reset = false;
> > +             }
> > ++    }
> > ++    if (pdata->fixup_rgmii_tx_delay &&
> > ++        phydev->speed != priv->prev_speed) {
> > ++            switch (phydev->speed) {
> > ++            case SPEED_10:
> > ++            case SPEED_100:
> > ++                    at803x_dbg_reg_set(phydev,
> > ++                            AT803X_DEBUG_SYSTEM_MODE_CTRL,
> > ++                            AT803X_DEBUG_RGMII_TX_CLK_DLY);
> > ++                    break;
> > ++            case SPEED_1000:
> > ++                    at803x_dbg_reg_clr(phydev,
> > ++                            AT803X_DEBUG_SYSTEM_MODE_CTRL,
> > ++                            AT803X_DEBUG_RGMII_TX_CLK_DLY);
> > ++                    break;
> > ++            default:
> > ++                    break;
> > ++            }
> > ++
> > ++            priv->prev_speed = phydev->speed;
> > +     }
> > + }
> > +
> >  --- /dev/null
> >  +++ b/include/linux/platform_data/phy-at803x.h
> > -@@ -0,0 +1,10 @@
> > +@@ -0,0 +1,11 @@
> >  +#ifndef _PHY_AT803X_PDATA_H
> >  +#define _PHY_AT803X_PDATA_H
> >  +
> >  +struct at803x_platform_data {
> > -+       int disable_smarteee:1;
> > -+       int enable_rgmii_tx_delay:1;
> > -+       int enable_rgmii_rx_delay:1;
> > ++    int disable_smarteee:1;
> > ++    int enable_rgmii_tx_delay:1;
> > ++    int enable_rgmii_rx_delay:1;
> > ++    int fixup_rgmii_tx_delay:1;
> >  +};
> >  +
> >  +#endif /* _PHY_AT803X_PDATA_H */
> > --
> > 2.1.4
> > _______________________________________________
> > openwrt-devel mailing list
> > openwrt-devel@lists.openwrt.org
> > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
Christian Lamparter June 6, 2015, 12:42 p.m. UTC | #3
On Friday, June 05, 2015 02:18:22 PM Dave Taht wrote:
> TX delay setting? What else can it do?
Can't tell. Atheros' ethernet driver source is available
in the GPL source for this device (but I guess this is 
nothing special. Version is: s17_ssdk_v1.0.4p1). 

> My dream has been to find a way to set the tx completion interrupt
> to only return with a soft set rate. So if I had a gigE connection
> but my uplink was only 10Mbits, it would return the interrupt
> after 1.3ms had expired.
> 
> this would let me get away entirely from using software rate limiting
> with htb, just program a register once with the uplink rate, and
> let bql and fq_codel handle the rest.
I don't know if the rate limiting implementation you describe would
be possible to implement or not. But, the vendor driver has some 
code to setup some hardware rate limiting in "athrs_qos.c". 

Regards,
  Christian
Christian Lamparter June 9, 2015, 2:35 p.m. UTC | #4
On Wednesday, June 03, 2015 05:20:22 PM Christian Lamparter wrote:
> The mynet range extender hardware is suffering from ethernet
> link loss when booting with a recent openwrt image. This only
> happens on 100mbps links, with 1Gbps speed the link was fine.
> 
> The cause of the problem is that the AR8035 PHY (aka F1E)
> requires turning on and off the special TX delay setting
> depending on the speed of the link.
> 
> The 10mbps mode only needed the proper pll value, which was
> extracted from the vendor code.
> 
> Reported-by: Pascal Paradis
> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>

No comments so far (but also, no merge). Ping?

Regards,
  Christian
Florian Fainelli June 9, 2015, 4:05 p.m. UTC | #5
On Jun 9, 2015 7:36 AM, "Christian Lamparter" <chunkeey@googlemail.com>
wrote:
>
> On Wednesday, June 03, 2015 05:20:22 PM Christian Lamparter wrote:
> > The mynet range extender hardware is suffering from ethernet
> > link loss when booting with a recent openwrt image. This only
> > happens on 100mbps links, with 1Gbps speed the link was fine.
> >
> > The cause of the problem is that the AR8035 PHY (aka F1E)
> > requires turning on and off the special TX delay setting
> > depending on the speed of the link.
> >
> > The 10mbps mode only needed the proper pll value, which was
> > extracted from the vendor code.
> >
> > Reported-by: Pascal Paradis
> > Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
>
> No comments so far (but also, no merge). Ping?

Actually, I have one question, most PHY s should disable these kinds of
delays when linking at 10/100Mbits/sec. Is not that working here because
the registers used have a special behavior (force or override), or is it
broken at the hardware level?

>
> Regards,
>   Christian
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
Christian Lamparter June 9, 2015, 7:24 p.m. UTC | #6
On Tuesday, June 09, 2015 09:05:46 AM Florian Fainelli wrote:
> On Jun 9, 2015 7:36 AM, "Christian Lamparter" <chunkeey@googlemail.com>
> wrote:
> >
> > On Wednesday, June 03, 2015 05:20:22 PM Christian Lamparter wrote:
> > > The mynet range extender hardware is suffering from ethernet
> > > link loss when booting with a recent openwrt image. This only
> > > happens on 100mbps links, with 1Gbps speed the link was fine.
> > >
> > > The cause of the problem is that the AR8035 PHY (aka F1E)
> > > requires turning on and off the special TX delay setting
> > > depending on the speed of the link.
> > >
> > > The 10mbps mode only needed the proper pll value, which was
> > > extracted from the vendor code.
> > >
> > > Reported-by: Pascal Paradis
> > > Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
> >
> > No comments so far (but also, no merge). Ping?
> 
> Actually, I have one question, most PHY s should disable these kinds of
> delays when linking at 10/100Mbits/sec. Is not that working here because
> the registers used have a special behavior (force or override), or is it
> broken at the hardware level?

Oh boy, how can I check (without introducing any "doubt") if this is broken
at the hardware level (I think it is) without specialized hardware? From my
POV I would need something like an ethernet analyzer with 20k price tag.
 
If it helps: I can run experiments and maybe tell you something about the
device/situation and you can tell me if this code is acceptable (and can
be merged) or if this needs to be done differently.

Something to keep in mind about the device:
Both, the original vendor driver (Atheros' SDK) and the uboot's ethernet 
driver, always enable/set the rx delay for every "link up". Both drivers
also modify the tx delay setting for 1000mbps (off) and 100/10mbps(on).
[I can point you to the relevant code in WD's source code if you want]. 

And now for the funny "bit" about why this problem wasn't discovered
sooner:

The issue was first spotted in commit: r45439 [0].

Before this change: the PHY wasn't recognized and the generic phy driver
was used. The generic phy driver obviously doesn't mess with the tx/rx
delay registers. 

=> uboot initialized the ethernet and linux simply kept the setting and
   it would continue to work. Unless of course the user decided to
   replugged the device while linux was running and a different speed 
   setting was negotiated.

After this change: The PHY is recognized as AT8035. The code in at803x.c
(vanilla source: [1] and patch [2]) now overwrites the uboot setting and 
forces the tx and rx delay settings to what is supplied by a 
at803x_platform_data struct. 

=> The problem with the mynet device is that the tx delay needs to be
enabled for 100mbps/10mbps speed and disabled for 1000mbps. Not doing
so results in an unusable ethernet link (verified by Pascal and me).
This is why I think this is a hardware problem. (Furthermore, Sven 
Eckelmann (CC'd, he wrote the support for the OM5P-AN - which also uses
the AT8035) doesn't mention any workaround in his commits.

What do you think?

Regards,
  Christian

[0] <https://dev.openwrt.org/changeset/45439>
[1] <http://lxr.free-electrons.com/source/drivers/net/phy/at803x.c>
[2] <https://dev.openwrt.org/browser/trunk/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch>
Christian Lamparter June 12, 2015, 10:12 a.m. UTC | #7
On Tuesday, June 09, 2015 09:24:41 PM Christian Lamparter wrote:
> On Tuesday, June 09, 2015 09:05:46 AM Florian Fainelli wrote:
> > On Jun 9, 2015 7:36 AM, "Christian Lamparter" <chunkeey@googlemail.com> wrote:
> > > On Wednesday, June 03, 2015 05:20:22 PM Christian Lamparter wrote:
> > 
> > Actually, I have one question, most PHY s should disable these kinds of
> > delays when linking at 10/100Mbits/sec. Is not that working here because
> > the registers used have a special behavior (force or override), or is it
> > broken at the hardware level?
> 
> => The problem with the mynet device is that the tx delay needs to be
> enabled for 100mbps/10mbps speed and disabled for 1000mbps. Not doing
> so results in an unusable ethernet link (verified by Pascal and me).
> This is why I think this is a hardware problem. (Furthermore, Sven 
> Eckelmann (CC'd, he wrote the support for the OM5P-AN - which also uses
> the AT8035) doesn't mention any workaround in his commits.

No further comments so far (but also: no merge). Ping?

Thanks,
   Christian
diff mbox

Patch

diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
index 02d168e..3d48ca8 100644
--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mynet-rext.c
@@ -14,6 +14,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/ath9k_platform.h>
 #include <linux/ar8216_platform.h>
+#include <linux/platform_data/phy-at803x.h>
 
 #include <asm/mach-ath79/ar71xx_regs.h>
 
@@ -124,6 +125,21 @@  static struct gpio_keys_button mynet_rext_gpio_keys[] __initdata = {
 	},
 };
 
+static struct at803x_platform_data mynet_rext_at803x_data = {
+	.disable_smarteee = 0,
+	.enable_rgmii_rx_delay = 1,
+	.enable_rgmii_tx_delay = 0,
+	.fixup_rgmii_tx_delay = 1,
+};
+
+static struct mdio_board_info mynet_rext_mdio0_info[] = {
+        {
+                .bus_id = "ag71xx-mdio.0",
+                .phy_addr = 4,
+                .platform_data = &mynet_rext_at803x_data,
+        },
+};
+
 static void mynet_rext_get_mac(const char *name, char *mac)
 {
 	u8 *nvram = (u8 *) KSEG1ADDR(MYNET_REXT_NVRAM_ADDR);
@@ -169,12 +185,16 @@  static void __init mynet_rext_setup(void)
 
 	ath79_register_mdio(0, 0x0);
 
+	mdiobus_register_board_info(mynet_rext_mdio0_info,
+				    ARRAY_SIZE(mynet_rext_mdio0_info));
+
 	/* LAN */
 	mynet_rext_get_mac("et0macaddr=", ath79_eth0_data.mac_addr);
 
 	/* GMAC0 is connected to an external PHY on Port 4 */
 	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
 	ath79_eth0_data.phy_mask = BIT(4);
+	ath79_eth0_pll_data.pll_10   = 0x00001313; /* athrs_mac.c */
 	ath79_eth0_pll_data.pll_1000 = 0x0e000000; /* athrs_mac.c */
 	ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
 	ath79_register_eth(0);
diff --git a/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
index babc695..d046ede 100644
--- a/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
+++ b/target/linux/ar71xx/patches-3.18/425-net-phy-at803x-allow-to-configure-via-pdata.patch
@@ -32,6 +32,14 @@ 
  #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
  #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
  
+@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
+ struct at803x_priv {
+ 	bool phy_reset:1;
+ 	struct gpio_desc *gpiod_reset;
++	int prev_speed;
+ };
+ 
+ struct at803x_context {
 @@ -61,6 +71,43 @@ struct at803x_context {
  	u16 led_control;
  };
@@ -120,16 +128,53 @@ 
  	return 0;
  }
  
+@@ -258,6 +334,8 @@ static int at803x_config_intr(struct phy
+ static void at803x_link_change_notify(struct phy_device *phydev)
+ {
+ 	struct at803x_priv *priv = phydev->priv;
++	struct at803x_platform_data *pdata;
++	pdata = dev_get_platdata(&phydev->dev);
+ 
+ 	/*
+ 	 * Conduct a hardware reset for AT8030 every time a link loss is
+@@ -287,6 +365,26 @@ static void at803x_link_change_notify(st
+ 		} else {
+ 			priv->phy_reset = false;
+ 		}
++	}
++	if (pdata->fixup_rgmii_tx_delay &&
++	    phydev->speed != priv->prev_speed) {
++		switch (phydev->speed) {
++		case SPEED_10:
++		case SPEED_100:
++			at803x_dbg_reg_set(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		case SPEED_1000:
++			at803x_dbg_reg_clr(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		default:
++			break;
++		}
++
++		priv->prev_speed = phydev->speed;
+ 	}
+ }
+ 
 --- /dev/null
 +++ b/include/linux/platform_data/phy-at803x.h
-@@ -0,0 +1,10 @@
+@@ -0,0 +1,11 @@
 +#ifndef _PHY_AT803X_PDATA_H
 +#define _PHY_AT803X_PDATA_H
 +
 +struct at803x_platform_data {
-+       int disable_smarteee:1;
-+       int enable_rgmii_tx_delay:1;
-+       int enable_rgmii_rx_delay:1;
++	int disable_smarteee:1;
++	int enable_rgmii_tx_delay:1;
++	int enable_rgmii_rx_delay:1;
++	int fixup_rgmii_tx_delay:1;
 +};
 +
 +#endif /* _PHY_AT803X_PDATA_H */