aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Tatt Chuah <kim.tatt.chuah@intel.com>2017-03-26 20:44:35 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2017-04-20 19:32:45 -0400
commitb90fa8763560aab7c75697fb324ffc73fb813ecc (patch)
treeed8508e766ecae30c81fed64ff77068f694987f9
parent4827cc37796a02ece7097e01dad8e08f537ac815 (diff)
igb: Enable reading of wake up packet
Currently, in igb_resume(), igb driver ignores the Wake Up Status (WUS) and Wake Up Packet Memory (WUPM) registers. This patch enables the igb driver to read the WUPM if the controller was woken by a wake up packet that is not more than 128 bytes long (maximum WUPM size), then pass it up the kernel network stack. Signed-off-by: Kim Tatt Chuah <kim.tatt.chuah@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h21
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c36
2 files changed, 56 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 8aee314332a8..d8517779439b 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -39,6 +39,27 @@
39#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ 39#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
40#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ 40#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
41 41
42/* Wake Up Status */
43#define E1000_WUS_EX 0x00000004 /* Directed Exact */
44#define E1000_WUS_ARPD 0x00000020 /* Directed ARP Request */
45#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 */
46#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 */
47#define E1000_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */
48
49/* Packet types that are enabled for wake packet delivery */
50#define WAKE_PKT_WUS ( \
51 E1000_WUS_EX | \
52 E1000_WUS_ARPD | \
53 E1000_WUS_IPV4 | \
54 E1000_WUS_IPV6 | \
55 E1000_WUS_NSD)
56
57/* Wake Up Packet Length */
58#define E1000_WUPL_MASK 0x00000FFF
59
60/* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */
61#define E1000_WUPM_BYTES 128
62
42/* Extended Device Control */ 63/* Extended Device Control */
43#define E1000_CTRL_EXT_SDP2_DATA 0x00000040 /* Value of SW Defineable Pin 2 */ 64#define E1000_CTRL_EXT_SDP2_DATA 0x00000040 /* Value of SW Defineable Pin 2 */
44#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Defineable Pin 3 */ 65#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Defineable Pin 3 */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 53e66c87abaf..1cf74aa4ebd9 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -7985,6 +7985,36 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake,
7985 return 0; 7985 return 0;
7986} 7986}
7987 7987
7988static void igb_deliver_wake_packet(struct net_device *netdev)
7989{
7990 struct igb_adapter *adapter = netdev_priv(netdev);
7991 struct e1000_hw *hw = &adapter->hw;
7992 struct sk_buff *skb;
7993 u32 wupl;
7994
7995 wupl = rd32(E1000_WUPL) & E1000_WUPL_MASK;
7996
7997 /* WUPM stores only the first 128 bytes of the wake packet.
7998 * Read the packet only if we have the whole thing.
7999 */
8000 if ((wupl == 0) || (wupl > E1000_WUPM_BYTES))
8001 return;
8002
8003 skb = netdev_alloc_skb_ip_align(netdev, E1000_WUPM_BYTES);
8004 if (!skb)
8005 return;
8006
8007 skb_put(skb, wupl);
8008
8009 /* Ensure reads are 32-bit aligned */
8010 wupl = roundup(wupl, 4);
8011
8012 memcpy_fromio(skb->data, hw->hw_addr + E1000_WUPM_REG(0), wupl);
8013
8014 skb->protocol = eth_type_trans(skb, netdev);
8015 netif_rx(skb);
8016}
8017
7988#ifdef CONFIG_PM 8018#ifdef CONFIG_PM
7989#ifdef CONFIG_PM_SLEEP 8019#ifdef CONFIG_PM_SLEEP
7990static int igb_suspend(struct device *dev) 8020static int igb_suspend(struct device *dev)
@@ -8014,7 +8044,7 @@ static int igb_resume(struct device *dev)
8014 struct net_device *netdev = pci_get_drvdata(pdev); 8044 struct net_device *netdev = pci_get_drvdata(pdev);
8015 struct igb_adapter *adapter = netdev_priv(netdev); 8045 struct igb_adapter *adapter = netdev_priv(netdev);
8016 struct e1000_hw *hw = &adapter->hw; 8046 struct e1000_hw *hw = &adapter->hw;
8017 u32 err; 8047 u32 err, val;
8018 8048
8019 pci_set_power_state(pdev, PCI_D0); 8049 pci_set_power_state(pdev, PCI_D0);
8020 pci_restore_state(pdev); 8050 pci_restore_state(pdev);
@@ -8045,6 +8075,10 @@ static int igb_resume(struct device *dev)
8045 */ 8075 */
8046 igb_get_hw_control(adapter); 8076 igb_get_hw_control(adapter);
8047 8077
8078 val = rd32(E1000_WUS);
8079 if (val & WAKE_PKT_WUS)
8080 igb_deliver_wake_packet(netdev);
8081
8048 wr32(E1000_WUS, ~0); 8082 wr32(E1000_WUS, ~0);
8049 8083
8050 rtnl_lock(); 8084 rtnl_lock();