]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.14.67/smsc75xx-add-workaround-for-gigabit-link-up-hardware-errata.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.14.67 / smsc75xx-add-workaround-for-gigabit-link-up-hardware-errata.patch
1 From foo@baz Wed Aug 22 09:33:46 CEST 2018
2 From: Yuiko Oshino <yuiko.oshino@microchip.com>
3 Date: Tue, 3 Jul 2018 11:21:46 -0400
4 Subject: smsc75xx: Add workaround for gigabit link up hardware errata.
5
6 From: Yuiko Oshino <yuiko.oshino@microchip.com>
7
8 [ Upstream commit d461e3da905332189aad546b2ad9adbe6071c7cc ]
9
10 In certain conditions, the device may not be able to link in gigabit mode. This software workaround ensures that the device will not enter the failure state.
11
12 Fixes: d0cad871703b898a442e4049c532ec39168e5b57 ("SMSC75XX USB 2.0 Gigabit Ethernet Devices")
13 Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
15 Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
16 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
17 ---
18 drivers/net/usb/smsc75xx.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
19 1 file changed, 62 insertions(+)
20
21 --- a/drivers/net/usb/smsc75xx.c
22 +++ b/drivers/net/usb/smsc75xx.c
23 @@ -82,6 +82,9 @@ static bool turbo_mode = true;
24 module_param(turbo_mode, bool, 0644);
25 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
26
27 +static int smsc75xx_link_ok_nopm(struct usbnet *dev);
28 +static int smsc75xx_phy_gig_workaround(struct usbnet *dev);
29 +
30 static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
31 u32 *data, int in_pm)
32 {
33 @@ -852,6 +855,9 @@ static int smsc75xx_phy_initialize(struc
34 return -EIO;
35 }
36
37 + /* phy workaround for gig link */
38 + smsc75xx_phy_gig_workaround(dev);
39 +
40 smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
41 ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
42 ADVERTISE_PAUSE_ASYM);
43 @@ -987,6 +993,62 @@ static int smsc75xx_wait_ready(struct us
44 return -EIO;
45 }
46
47 +static int smsc75xx_phy_gig_workaround(struct usbnet *dev)
48 +{
49 + struct mii_if_info *mii = &dev->mii;
50 + int ret = 0, timeout = 0;
51 + u32 buf, link_up = 0;
52 +
53 + /* Set the phy in Gig loopback */
54 + smsc75xx_mdio_write(dev->net, mii->phy_id, MII_BMCR, 0x4040);
55 +
56 + /* Wait for the link up */
57 + do {
58 + link_up = smsc75xx_link_ok_nopm(dev);
59 + usleep_range(10000, 20000);
60 + timeout++;
61 + } while ((!link_up) && (timeout < 1000));
62 +
63 + if (timeout >= 1000) {
64 + netdev_warn(dev->net, "Timeout waiting for PHY link up\n");
65 + return -EIO;
66 + }
67 +
68 + /* phy reset */
69 + ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
70 + if (ret < 0) {
71 + netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
72 + return ret;
73 + }
74 +
75 + buf |= PMT_CTL_PHY_RST;
76 +
77 + ret = smsc75xx_write_reg(dev, PMT_CTL, buf);
78 + if (ret < 0) {
79 + netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret);
80 + return ret;
81 + }
82 +
83 + timeout = 0;
84 + do {
85 + usleep_range(10000, 20000);
86 + ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
87 + if (ret < 0) {
88 + netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n",
89 + ret);
90 + return ret;
91 + }
92 + timeout++;
93 + } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100));
94 +
95 + if (timeout >= 100) {
96 + netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
97 + return -EIO;
98 + }
99 +
100 + return 0;
101 +}
102 +
103 static int smsc75xx_reset(struct usbnet *dev)
104 {
105 struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);