]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
igc: Add WOL support
authorSasha Neftin <sasha.neftin@intel.com>
Mon, 3 Feb 2020 07:55:20 +0000 (09:55 +0200)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 20 Feb 2020 00:51:43 +0000 (16:51 -0800)
This patch adds a define and WOL support for an i225 parts.

Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_defines.h
drivers/net/ethernet/intel/igc/igc_ethtool.c
drivers/net/ethernet/intel/igc/igc_main.c

index 5e9c2dd8b8e448e8fa4e76de82fa27b12335429d..8d9ed4f0b69dc230680cb91b62d4284e425327bd 100644 (file)
@@ -61,6 +61,7 @@ extern char igc_driver_version[];
 #define IGC_FLAG_QUEUE_PAIRS           BIT(3)
 #define IGC_FLAG_DMAC                  BIT(4)
 #define IGC_FLAG_PTP                   BIT(8)
+#define IGC_FLAG_WOL_SUPPORTED         BIT(8)
 #define IGC_FLAG_NEED_LINK_UPDATE      BIT(9)
 #define IGC_FLAG_MEDIA_RESET           BIT(10)
 #define IGC_FLAG_MAS_ENABLE            BIT(12)
index 3c03962bde5e7d9ce47a1a882434239039cd90dc..4ddccccf42ccf3568e9284cf5655362552be306a 100644 (file)
 
 /* Wake Up Filter Control */
 #define IGC_WUFC_LNKC  0x00000001 /* Link Status Change Wakeup Enable */
+#define IGC_WUFC_MAG   0x00000002 /* Magic Packet Wakeup Enable */
+#define IGC_WUFC_EX    0x00000004 /* Directed Exact Wakeup Enable */
 #define IGC_WUFC_MC    0x00000008 /* Directed Multicast Wakeup Enable */
+#define IGC_WUFC_BC    0x00000010 /* Broadcast Wakeup Enable */
 
 #define IGC_CTRL_ADVD3WUC      0x00100000  /* D3 WUC */
 
index ee07011e13e9b8e948cb3552a51b46ca3d3035a1..69f50b8e2af3b1866c267349e7577350934d6d9f 100644 (file)
@@ -308,6 +308,65 @@ static void igc_get_regs(struct net_device *netdev,
                regs_buff[168 + i] = rd32(IGC_TXDCTL(i));
 }
 
+static void igc_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+       struct igc_adapter *adapter = netdev_priv(netdev);
+
+       wol->wolopts = 0;
+
+       if (!(adapter->flags & IGC_FLAG_WOL_SUPPORTED))
+               return;
+
+       wol->supported = WAKE_UCAST | WAKE_MCAST |
+                        WAKE_BCAST | WAKE_MAGIC |
+                        WAKE_PHY;
+
+       /* apply any specific unsupported masks here */
+       switch (adapter->hw.device_id) {
+       default:
+               break;
+       }
+
+       if (adapter->wol & IGC_WUFC_EX)
+               wol->wolopts |= WAKE_UCAST;
+       if (adapter->wol & IGC_WUFC_MC)
+               wol->wolopts |= WAKE_MCAST;
+       if (adapter->wol & IGC_WUFC_BC)
+               wol->wolopts |= WAKE_BCAST;
+       if (adapter->wol & IGC_WUFC_MAG)
+               wol->wolopts |= WAKE_MAGIC;
+       if (adapter->wol & IGC_WUFC_LNKC)
+               wol->wolopts |= WAKE_PHY;
+}
+
+static int igc_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+       struct igc_adapter *adapter = netdev_priv(netdev);
+
+       if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_FILTER))
+               return -EOPNOTSUPP;
+
+       if (!(adapter->flags & IGC_FLAG_WOL_SUPPORTED))
+               return wol->wolopts ? -EOPNOTSUPP : 0;
+
+       /* these settings will always override what we currently have */
+       adapter->wol = 0;
+
+       if (wol->wolopts & WAKE_UCAST)
+               adapter->wol |= IGC_WUFC_EX;
+       if (wol->wolopts & WAKE_MCAST)
+               adapter->wol |= IGC_WUFC_MC;
+       if (wol->wolopts & WAKE_BCAST)
+               adapter->wol |= IGC_WUFC_BC;
+       if (wol->wolopts & WAKE_MAGIC)
+               adapter->wol |= IGC_WUFC_MAG;
+       if (wol->wolopts & WAKE_PHY)
+               adapter->wol |= IGC_WUFC_LNKC;
+       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+       return 0;
+}
+
 static u32 igc_get_msglevel(struct net_device *netdev)
 {
        struct igc_adapter *adapter = netdev_priv(netdev);
@@ -1859,6 +1918,8 @@ static const struct ethtool_ops igc_ethtool_ops = {
        .get_drvinfo            = igc_get_drvinfo,
        .get_regs_len           = igc_get_regs_len,
        .get_regs               = igc_get_regs,
+       .get_wol                = igc_get_wol,
+       .set_wol                = igc_set_wol,
        .get_msglevel           = igc_get_msglevel,
        .set_msglevel           = igc_set_msglevel,
        .nway_reset             = igc_nway_reset,
index e982b5f54dc94cfd73df6dc58fdc1f39044772e8..69fa1ce1f92719b0f3ea91fdfeda4cc514aadd30 100644 (file)
@@ -4789,6 +4789,16 @@ static int igc_probe(struct pci_dev *pdev,
        hw->fc.requested_mode = igc_fc_default;
        hw->fc.current_mode = igc_fc_default;
 
+       /* By default, support wake on port A */
+       adapter->flags |= IGC_FLAG_WOL_SUPPORTED;
+
+       /* initialize the wol settings based on the eeprom settings */
+       if (adapter->flags & IGC_FLAG_WOL_SUPPORTED)
+               adapter->wol |= IGC_WUFC_MAG;
+
+       device_set_wakeup_enable(&adapter->pdev->dev,
+                                adapter->flags & IGC_FLAG_WOL_SUPPORTED);
+
        /* reset the hardware with the new settings */
        igc_reset(adapter);