be2net: Support for WoL using magic packet after suspend.
[deliverable/linux.git] / drivers / net / benet / be_main.c
index f24ac4b5ce8f70c80eecf72c8838d9ebdc43c366..84f686f41b5312346c164dba4fb4d0bdcc3be343 100644 (file)
@@ -1659,6 +1659,44 @@ ret_sts:
        return status;
 }
 
+static int be_setup_wol(struct be_adapter *adapter, bool enable)
+{
+       struct be_dma_mem cmd;
+       int status = 0;
+       u8 mac[ETH_ALEN];
+
+       memset(mac, 0, ETH_ALEN);
+
+       cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
+       cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+       if (cmd.va == NULL)
+               return -1;
+       memset(cmd.va, 0, cmd.size);
+
+       if (enable) {
+               status = pci_write_config_dword(adapter->pdev,
+                       PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK);
+               if (status) {
+                       dev_err(&adapter->pdev->dev,
+                               "Could not enable Wake-on-lan \n");
+                       pci_free_consistent(adapter->pdev, cmd.size, cmd.va,
+                                       cmd.dma);
+                       return status;
+               }
+               status = be_cmd_enable_magic_wol(adapter,
+                               adapter->netdev->dev_addr, &cmd);
+               pci_enable_wake(adapter->pdev, PCI_D3hot, 1);
+               pci_enable_wake(adapter->pdev, PCI_D3cold, 1);
+       } else {
+               status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
+               pci_enable_wake(adapter->pdev, PCI_D3hot, 0);
+               pci_enable_wake(adapter->pdev, PCI_D3cold, 0);
+       }
+
+       pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
+       return status;
+}
+
 static int be_setup(struct be_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -2282,6 +2320,9 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
        struct be_adapter *adapter = pci_get_drvdata(pdev);
        struct net_device *netdev =  adapter->netdev;
 
+       if (adapter->wol)
+               be_setup_wol(adapter, true);
+
        netif_device_detach(netdev);
        if (netif_running(netdev)) {
                rtnl_lock();
@@ -2324,6 +2365,9 @@ static int be_resume(struct pci_dev *pdev)
                rtnl_unlock();
        }
        netif_device_attach(netdev);
+
+       if (adapter->wol)
+               be_setup_wol(adapter, false);
        return 0;
 }
 
This page took 0.024345 seconds and 5 git commands to generate.