net: usb: ax88179_178a: wol optimizations
authorJustin Chen <justinpopo6@gmail.com>
Thu, 21 Jul 2022 00:28:16 +0000 (17:28 -0700)
committerJakub Kicinski <kuba@kernel.org>
Sat, 23 Jul 2022 04:43:59 +0000 (21:43 -0700)
- Check if wol is supported on reset instead of everytime get_wol
is called.
- Save wolopts in private data instead of relying on the HW to save it.
- Defer enabling WoL until suspend instead of enabling it everytime
set_wol is called.

Signed-off-by: Justin Chen <justinpopo6@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/usb/ax88179_178a.c

index d0cd9867cae7a9cfaff5ad81980f7c28b40b9ff0..3b0e8f93e3c8eea803f771338f36f297ea636e31 100644 (file)
@@ -171,6 +171,8 @@ struct ax88179_data {
        u8  eee_active;
        u16 rxctl;
        u8 in_pm;
+       u32 wol_supported;
+       u32 wolopts;
 };
 
 struct ax88179_int_data {
@@ -400,6 +402,7 @@ ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad,
 static int ax88179_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
+       struct ax88179_data *priv = dev->driver_priv;
        u16 tmp16;
        u8 tmp8;
 
@@ -407,6 +410,19 @@ static int ax88179_suspend(struct usb_interface *intf, pm_message_t message)
 
        usbnet_suspend(intf, message);
 
+       /* Enable WoL */
+       if (priv->wolopts) {
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
+                                1, 1, &tmp8);
+               if (priv->wolopts & WAKE_PHY)
+                       tmp8 |= AX_MONITOR_MODE_RWLC;
+               if (priv->wolopts & WAKE_MAGIC)
+                       tmp8 |= AX_MONITOR_MODE_RWMP;
+
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
+                                 1, 1, &tmp8);
+       }
+
        /* Disable RX path */
        ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
                         2, 2, &tmp16);
@@ -480,40 +496,22 @@ static void
 ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
        struct usbnet *dev = netdev_priv(net);
-       u8 opt;
-
-       if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
-                            1, 1, &opt) < 0) {
-               wolinfo->supported = 0;
-               wolinfo->wolopts = 0;
-               return;
-       }
+       struct ax88179_data *priv = dev->driver_priv;
 
-       wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
-       wolinfo->wolopts = 0;
-       if (opt & AX_MONITOR_MODE_RWLC)
-               wolinfo->wolopts |= WAKE_PHY;
-       if (opt & AX_MONITOR_MODE_RWMP)
-               wolinfo->wolopts |= WAKE_MAGIC;
+       wolinfo->supported = priv->wol_supported;
+       wolinfo->wolopts = priv->wolopts;
 }
 
 static int
 ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
        struct usbnet *dev = netdev_priv(net);
-       u8 opt = 0;
+       struct ax88179_data *priv = dev->driver_priv;
 
-       if (wolinfo->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
+       if (wolinfo->wolopts & ~(priv->wol_supported))
                return -EINVAL;
 
-       if (wolinfo->wolopts & WAKE_PHY)
-               opt |= AX_MONITOR_MODE_RWLC;
-       if (wolinfo->wolopts & WAKE_MAGIC)
-               opt |= AX_MONITOR_MODE_RWMP;
-
-       if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
-                             1, 1, &opt) < 0)
-               return -EINVAL;
+       priv->wolopts = wolinfo->wolopts;
 
        return 0;
 }
@@ -1636,6 +1634,12 @@ static int ax88179_reset(struct usbnet *dev)
        ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
                          2, 2, tmp16);
 
+       /* Check if WoL is supported */
+       ax179_data->wol_supported = 0;
+       if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
+                            1, 1, &tmp) > 0)
+               ax179_data->wol_supported = WAKE_MAGIC | WAKE_PHY;
+
        ax88179_led_setting(dev);
 
        ax179_data->eee_enabled = 0;