aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2013-03-14 01:12:01 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-15 08:46:48 -0400
commitd97e74976982a35168c7f131cce0d93537337a26 (patch)
treeda808857fddb6f987c1982b2348555afd247b80e /drivers/net
parentcca7af3889bfa343d33d5e657a38d876abd10e58 (diff)
net: fec: restart the FEC when PHY speed changes
Proviously we would only restart the FEC when PHY link or duplex state changed. PHY does not always bring down the link for speed changes, in which case we would not detect any change and keep FEC running. Switching link speed without restarting the FEC results in the FEC being stuck in an indefinite state, generating error conditions for every packet. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/freescale/fec.c26
-rw-r--r--drivers/net/ethernet/freescale/fec.h1
2 files changed, 16 insertions, 11 deletions
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 069a155d16ed..61d2e6202bf3 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -934,24 +934,28 @@ static void fec_enet_adjust_link(struct net_device *ndev)
934 goto spin_unlock; 934 goto spin_unlock;
935 } 935 }
936 936
937 /* Duplex link change */
938 if (phy_dev->link) { 937 if (phy_dev->link) {
939 if (fep->full_duplex != phy_dev->duplex) { 938 if (!fep->link) {
940 fec_restart(ndev, phy_dev->duplex);
941 /* prevent unnecessary second fec_restart() below */
942 fep->link = phy_dev->link; 939 fep->link = phy_dev->link;
943 status_change = 1; 940 status_change = 1;
944 } 941 }
945 }
946 942
947 /* Link on or off change */ 943 if (fep->full_duplex != phy_dev->duplex)
948 if (phy_dev->link != fep->link) { 944 status_change = 1;
949 fep->link = phy_dev->link; 945
950 if (phy_dev->link) 946 if (phy_dev->speed != fep->speed) {
947 fep->speed = phy_dev->speed;
948 status_change = 1;
949 }
950
951 /* if any of the above changed restart the FEC */
952 if (status_change)
951 fec_restart(ndev, phy_dev->duplex); 953 fec_restart(ndev, phy_dev->duplex);
952 else 954 } else {
955 if (fep->link) {
953 fec_stop(ndev); 956 fec_stop(ndev);
954 status_change = 1; 957 status_change = 1;
958 }
955 } 959 }
956 960
957spin_unlock: 961spin_unlock:
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index f5390071efd0..eb4372962839 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -240,6 +240,7 @@ struct fec_enet_private {
240 phy_interface_t phy_interface; 240 phy_interface_t phy_interface;
241 int link; 241 int link;
242 int full_duplex; 242 int full_duplex;
243 int speed;
243 struct completion mdio_done; 244 struct completion mdio_done;
244 int irq[FEC_IRQ_NUM]; 245 int irq[FEC_IRQ_NUM];
245 int bufdesc_ex; 246 int bufdesc_ex;