Skip to content

Commit 0271d28

Browse files
author
Paolo Abeni
committed
Merge branch 'net-lan743x-fixes-for-multiple-wol-related-issues'
Raju Lakkaraju says: ==================== net: lan743x: Fixes for multiple WOL related issues This patch series implement the following fixes: 1. Disable WOL upon resume in order to restore full data path operation 2. Support WOL at both the PHY and MAC appropriately 3. Remove interrupt mask clearing from config_init Patch-3 was sent seperately earlier. Review comments in link: https://lore.kernel.org/lkml/[email protected]/T/ ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 2d71982 + c44d3ff commit 0271d28

File tree

4 files changed

+146
-32
lines changed

4 files changed

+146
-32
lines changed

drivers/net/ethernet/microchip/lan743x_ethtool.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,8 +1127,12 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev,
11271127
if (netdev->phydev)
11281128
phy_ethtool_get_wol(netdev->phydev, wol);
11291129

1130-
wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
1131-
WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
1130+
if (wol->supported != adapter->phy_wol_supported)
1131+
netif_warn(adapter, drv, adapter->netdev,
1132+
"PHY changed its supported WOL! old=%x, new=%x\n",
1133+
adapter->phy_wol_supported, wol->supported);
1134+
1135+
wol->supported |= MAC_SUPPORTED_WAKES;
11321136

11331137
if (adapter->is_pci11x1x)
11341138
wol->supported |= WAKE_MAGICSECURE;
@@ -1143,7 +1147,39 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
11431147
{
11441148
struct lan743x_adapter *adapter = netdev_priv(netdev);
11451149

1150+
/* WAKE_MAGICSEGURE is a modifier of and only valid together with
1151+
* WAKE_MAGIC
1152+
*/
1153+
if ((wol->wolopts & WAKE_MAGICSECURE) && !(wol->wolopts & WAKE_MAGIC))
1154+
return -EINVAL;
1155+
1156+
if (netdev->phydev) {
1157+
struct ethtool_wolinfo phy_wol;
1158+
int ret;
1159+
1160+
phy_wol.wolopts = wol->wolopts & adapter->phy_wol_supported;
1161+
1162+
/* If WAKE_MAGICSECURE was requested, filter out WAKE_MAGIC
1163+
* for PHYs that do not support WAKE_MAGICSECURE
1164+
*/
1165+
if (wol->wolopts & WAKE_MAGICSECURE &&
1166+
!(adapter->phy_wol_supported & WAKE_MAGICSECURE))
1167+
phy_wol.wolopts &= ~WAKE_MAGIC;
1168+
1169+
ret = phy_ethtool_set_wol(netdev->phydev, &phy_wol);
1170+
if (ret && (ret != -EOPNOTSUPP))
1171+
return ret;
1172+
1173+
if (ret == -EOPNOTSUPP)
1174+
adapter->phy_wolopts = 0;
1175+
else
1176+
adapter->phy_wolopts = phy_wol.wolopts;
1177+
} else {
1178+
adapter->phy_wolopts = 0;
1179+
}
1180+
11461181
adapter->wolopts = 0;
1182+
wol->wolopts &= ~adapter->phy_wolopts;
11471183
if (wol->wolopts & WAKE_UCAST)
11481184
adapter->wolopts |= WAKE_UCAST;
11491185
if (wol->wolopts & WAKE_MCAST)
@@ -1164,10 +1200,10 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
11641200
memset(adapter->sopass, 0, sizeof(u8) * SOPASS_MAX);
11651201
}
11661202

1203+
wol->wolopts = adapter->wolopts | adapter->phy_wolopts;
11671204
device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
11681205

1169-
return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol)
1170-
: -ENETDOWN;
1206+
return 0;
11711207
}
11721208
#endif /* CONFIG_PM */
11731209

drivers/net/ethernet/microchip/lan743x_main.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,6 +3118,17 @@ static int lan743x_netdev_open(struct net_device *netdev)
31183118
if (ret)
31193119
goto close_tx;
31203120
}
3121+
3122+
#ifdef CONFIG_PM
3123+
if (adapter->netdev->phydev) {
3124+
struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
3125+
3126+
phy_ethtool_get_wol(netdev->phydev, &wol);
3127+
adapter->phy_wol_supported = wol.supported;
3128+
adapter->phy_wolopts = wol.wolopts;
3129+
}
3130+
#endif
3131+
31213132
return 0;
31223133

31233134
close_tx:
@@ -3575,7 +3586,7 @@ static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
35753586

35763587
/* clear wake settings */
35773588
pmtctl = lan743x_csr_read(adapter, PMT_CTL);
3578-
pmtctl |= PMT_CTL_WUPS_MASK_;
3589+
pmtctl |= PMT_CTL_WUPS_MASK_ | PMT_CTL_RES_CLR_WKP_MASK_;
35793590
pmtctl &= ~(PMT_CTL_GPIO_WAKEUP_EN_ | PMT_CTL_EEE_WAKEUP_EN_ |
35803591
PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_ |
35813592
PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_ | PMT_CTL_ETH_PHY_WAKE_EN_);
@@ -3587,10 +3598,9 @@ static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
35873598

35883599
pmtctl |= PMT_CTL_ETH_PHY_D3_COLD_OVR_ | PMT_CTL_ETH_PHY_D3_OVR_;
35893600

3590-
if (adapter->wolopts & WAKE_PHY) {
3591-
pmtctl |= PMT_CTL_ETH_PHY_EDPD_PLL_CTL_;
3601+
if (adapter->phy_wolopts)
35923602
pmtctl |= PMT_CTL_ETH_PHY_WAKE_EN_;
3593-
}
3603+
35943604
if (adapter->wolopts & WAKE_MAGIC) {
35953605
wucsr |= MAC_WUCSR_MPEN_;
35963606
macrx |= MAC_RX_RXEN_;
@@ -3686,7 +3696,7 @@ static int lan743x_pm_suspend(struct device *dev)
36863696
lan743x_csr_write(adapter, MAC_WUCSR2, 0);
36873697
lan743x_csr_write(adapter, MAC_WK_SRC, 0xFFFFFFFF);
36883698

3689-
if (adapter->wolopts)
3699+
if (adapter->wolopts || adapter->phy_wolopts)
36903700
lan743x_pm_set_wol(adapter);
36913701

36923702
if (adapter->is_pci11x1x) {
@@ -3710,6 +3720,7 @@ static int lan743x_pm_resume(struct device *dev)
37103720
struct pci_dev *pdev = to_pci_dev(dev);
37113721
struct net_device *netdev = pci_get_drvdata(pdev);
37123722
struct lan743x_adapter *adapter = netdev_priv(netdev);
3723+
u32 data;
37133724
int ret;
37143725

37153726
pci_set_power_state(pdev, PCI_D0);
@@ -3728,6 +3739,30 @@ static int lan743x_pm_resume(struct device *dev)
37283739
return ret;
37293740
}
37303741

3742+
ret = lan743x_csr_read(adapter, MAC_WK_SRC);
3743+
netif_dbg(adapter, drv, adapter->netdev,
3744+
"Wakeup source : 0x%08X\n", ret);
3745+
3746+
/* Clear the wol configuration and status bits. Note that
3747+
* the status bits are "Write One to Clear (W1C)"
3748+
*/
3749+
data = MAC_WUCSR_EEE_TX_WAKE_ | MAC_WUCSR_EEE_RX_WAKE_ |
3750+
MAC_WUCSR_RFE_WAKE_FR_ | MAC_WUCSR_PFDA_FR_ | MAC_WUCSR_WUFR_ |
3751+
MAC_WUCSR_MPR_ | MAC_WUCSR_BCAST_FR_;
3752+
lan743x_csr_write(adapter, MAC_WUCSR, data);
3753+
3754+
data = MAC_WUCSR2_NS_RCD_ | MAC_WUCSR2_ARP_RCD_ |
3755+
MAC_WUCSR2_IPV6_TCPSYN_RCD_ | MAC_WUCSR2_IPV4_TCPSYN_RCD_;
3756+
lan743x_csr_write(adapter, MAC_WUCSR2, data);
3757+
3758+
data = MAC_WK_SRC_ETH_PHY_WK_ | MAC_WK_SRC_IPV6_TCPSYN_RCD_WK_ |
3759+
MAC_WK_SRC_IPV4_TCPSYN_RCD_WK_ | MAC_WK_SRC_EEE_TX_WK_ |
3760+
MAC_WK_SRC_EEE_RX_WK_ | MAC_WK_SRC_RFE_FR_WK_ |
3761+
MAC_WK_SRC_PFDA_FR_WK_ | MAC_WK_SRC_MP_FR_WK_ |
3762+
MAC_WK_SRC_BCAST_FR_WK_ | MAC_WK_SRC_WU_FR_WK_ |
3763+
MAC_WK_SRC_WK_FR_SAVED_;
3764+
lan743x_csr_write(adapter, MAC_WK_SRC, data);
3765+
37313766
/* open netdev when netdev is at running state while resume.
37323767
* For instance, it is true when system wakesup after pm-suspend
37333768
* However, it is false when system wakes up after suspend GUI menu
@@ -3736,9 +3771,6 @@ static int lan743x_pm_resume(struct device *dev)
37363771
lan743x_netdev_open(netdev);
37373772

37383773
netif_device_attach(netdev);
3739-
ret = lan743x_csr_read(adapter, MAC_WK_SRC);
3740-
netif_info(adapter, drv, adapter->netdev,
3741-
"Wakeup source : 0x%08X\n", ret);
37423774

37433775
return 0;
37443776
}

drivers/net/ethernet/microchip/lan743x_main.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#define PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_ BIT(18)
6262
#define PMT_CTL_GPIO_WAKEUP_EN_ BIT(15)
6363
#define PMT_CTL_EEE_WAKEUP_EN_ BIT(13)
64+
#define PMT_CTL_RES_CLR_WKP_MASK_ GENMASK(9, 8)
6465
#define PMT_CTL_READY_ BIT(7)
6566
#define PMT_CTL_ETH_PHY_RST_ BIT(4)
6667
#define PMT_CTL_WOL_EN_ BIT(3)
@@ -227,12 +228,31 @@
227228
#define MAC_WUCSR (0x140)
228229
#define MAC_MP_SO_EN_ BIT(21)
229230
#define MAC_WUCSR_RFE_WAKE_EN_ BIT(14)
231+
#define MAC_WUCSR_EEE_TX_WAKE_ BIT(13)
232+
#define MAC_WUCSR_EEE_RX_WAKE_ BIT(11)
233+
#define MAC_WUCSR_RFE_WAKE_FR_ BIT(9)
234+
#define MAC_WUCSR_PFDA_FR_ BIT(7)
235+
#define MAC_WUCSR_WUFR_ BIT(6)
236+
#define MAC_WUCSR_MPR_ BIT(5)
237+
#define MAC_WUCSR_BCAST_FR_ BIT(4)
230238
#define MAC_WUCSR_PFDA_EN_ BIT(3)
231239
#define MAC_WUCSR_WAKE_EN_ BIT(2)
232240
#define MAC_WUCSR_MPEN_ BIT(1)
233241
#define MAC_WUCSR_BCST_EN_ BIT(0)
234242

235243
#define MAC_WK_SRC (0x144)
244+
#define MAC_WK_SRC_ETH_PHY_WK_ BIT(17)
245+
#define MAC_WK_SRC_IPV6_TCPSYN_RCD_WK_ BIT(16)
246+
#define MAC_WK_SRC_IPV4_TCPSYN_RCD_WK_ BIT(15)
247+
#define MAC_WK_SRC_EEE_TX_WK_ BIT(14)
248+
#define MAC_WK_SRC_EEE_RX_WK_ BIT(13)
249+
#define MAC_WK_SRC_RFE_FR_WK_ BIT(12)
250+
#define MAC_WK_SRC_PFDA_FR_WK_ BIT(11)
251+
#define MAC_WK_SRC_MP_FR_WK_ BIT(10)
252+
#define MAC_WK_SRC_BCAST_FR_WK_ BIT(9)
253+
#define MAC_WK_SRC_WU_FR_WK_ BIT(8)
254+
#define MAC_WK_SRC_WK_FR_SAVED_ BIT(7)
255+
236256
#define MAC_MP_SO_HI (0x148)
237257
#define MAC_MP_SO_LO (0x14C)
238258

@@ -295,6 +315,10 @@
295315
#define RFE_INDX(index) (0x580 + (index << 2))
296316

297317
#define MAC_WUCSR2 (0x600)
318+
#define MAC_WUCSR2_NS_RCD_ BIT(7)
319+
#define MAC_WUCSR2_ARP_RCD_ BIT(6)
320+
#define MAC_WUCSR2_IPV6_TCPSYN_RCD_ BIT(5)
321+
#define MAC_WUCSR2_IPV4_TCPSYN_RCD_ BIT(4)
298322

299323
#define SGMII_ACC (0x720)
300324
#define SGMII_ACC_SGMII_BZY_ BIT(31)
@@ -1018,13 +1042,17 @@ enum lan743x_sgmii_lsd {
10181042
LINK_2500_SLAVE
10191043
};
10201044

1045+
#define MAC_SUPPORTED_WAKES (WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | \
1046+
WAKE_MAGIC | WAKE_ARP)
10211047
struct lan743x_adapter {
10221048
struct net_device *netdev;
10231049
struct mii_bus *mdiobus;
10241050
int msg_enable;
10251051
#ifdef CONFIG_PM
10261052
u32 wolopts;
10271053
u8 sopass[SOPASS_MAX];
1054+
u32 phy_wolopts;
1055+
u32 phy_wol_supported;
10281056
#endif
10291057
struct pci_dev *pdev;
10301058
struct lan743x_csr csr;

drivers/net/phy/mxl-gpy.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct gpy_priv {
107107

108108
u8 fw_major;
109109
u8 fw_minor;
110+
u32 wolopts;
110111

111112
/* It takes 3 seconds to fully switch out of loopback mode before
112113
* it can safely re-enter loopback mode. Record the time when
@@ -221,6 +222,15 @@ static int gpy_hwmon_register(struct phy_device *phydev)
221222
}
222223
#endif
223224

225+
static int gpy_ack_interrupt(struct phy_device *phydev)
226+
{
227+
int ret;
228+
229+
/* Clear all pending interrupts */
230+
ret = phy_read(phydev, PHY_ISTAT);
231+
return ret < 0 ? ret : 0;
232+
}
233+
224234
static int gpy_mbox_read(struct phy_device *phydev, u32 addr)
225235
{
226236
struct gpy_priv *priv = phydev->priv;
@@ -262,16 +272,8 @@ static int gpy_mbox_read(struct phy_device *phydev, u32 addr)
262272

263273
static int gpy_config_init(struct phy_device *phydev)
264274
{
265-
int ret;
266-
267-
/* Mask all interrupts */
268-
ret = phy_write(phydev, PHY_IMASK, 0);
269-
if (ret)
270-
return ret;
271-
272-
/* Clear all pending interrupts */
273-
ret = phy_read(phydev, PHY_ISTAT);
274-
return ret < 0 ? ret : 0;
275+
/* Nothing to configure. Configuration Requirement Placeholder */
276+
return 0;
275277
}
276278

277279
static int gpy21x_config_init(struct phy_device *phydev)
@@ -627,11 +629,23 @@ static int gpy_read_status(struct phy_device *phydev)
627629

628630
static int gpy_config_intr(struct phy_device *phydev)
629631
{
632+
struct gpy_priv *priv = phydev->priv;
630633
u16 mask = 0;
634+
int ret;
635+
636+
ret = gpy_ack_interrupt(phydev);
637+
if (ret)
638+
return ret;
631639

632640
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
633641
mask = PHY_IMASK_MASK;
634642

643+
if (priv->wolopts & WAKE_MAGIC)
644+
mask |= PHY_IMASK_WOL;
645+
646+
if (priv->wolopts & WAKE_PHY)
647+
mask |= PHY_IMASK_LSTC;
648+
635649
return phy_write(phydev, PHY_IMASK, mask);
636650
}
637651

@@ -678,6 +692,7 @@ static int gpy_set_wol(struct phy_device *phydev,
678692
struct ethtool_wolinfo *wol)
679693
{
680694
struct net_device *attach_dev = phydev->attached_dev;
695+
struct gpy_priv *priv = phydev->priv;
681696
int ret;
682697

683698
if (wol->wolopts & WAKE_MAGIC) {
@@ -725,13 +740,22 @@ static int gpy_set_wol(struct phy_device *phydev,
725740
ret = phy_read(phydev, PHY_ISTAT);
726741
if (ret < 0)
727742
return ret;
743+
744+
priv->wolopts |= WAKE_MAGIC;
728745
} else {
729746
/* Disable magic packet matching */
730747
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
731748
VPSPEC2_WOL_CTL,
732749
WOL_EN);
733750
if (ret < 0)
734751
return ret;
752+
753+
/* Disable the WOL interrupt */
754+
ret = phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_WOL);
755+
if (ret < 0)
756+
return ret;
757+
758+
priv->wolopts &= ~WAKE_MAGIC;
735759
}
736760

737761
if (wol->wolopts & WAKE_PHY) {
@@ -748,28 +772,22 @@ static int gpy_set_wol(struct phy_device *phydev,
748772
if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC))
749773
phy_trigger_machine(phydev);
750774

775+
priv->wolopts |= WAKE_PHY;
751776
return 0;
752777
}
753778

779+
priv->wolopts &= ~WAKE_PHY;
754780
/* Disable the link state change interrupt */
755781
return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC);
756782
}
757783

758784
static void gpy_get_wol(struct phy_device *phydev,
759785
struct ethtool_wolinfo *wol)
760786
{
761-
int ret;
787+
struct gpy_priv *priv = phydev->priv;
762788

763789
wol->supported = WAKE_MAGIC | WAKE_PHY;
764-
wol->wolopts = 0;
765-
766-
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, VPSPEC2_WOL_CTL);
767-
if (ret & WOL_EN)
768-
wol->wolopts |= WAKE_MAGIC;
769-
770-
ret = phy_read(phydev, PHY_IMASK);
771-
if (ret & PHY_IMASK_LSTC)
772-
wol->wolopts |= WAKE_PHY;
790+
wol->wolopts = priv->wolopts;
773791
}
774792

775793
static int gpy_loopback(struct phy_device *phydev, bool enable)

0 commit comments

Comments
 (0)