Commit 45f13df7 authored by Sriharsha Basavapatna's avatar Sriharsha Basavapatna Committed by David S. Miller

be2net: Enable Wake-On-LAN from shutdown for Skyhawk

Skyhawk does support wake-up from ACPI shutdown state - S5, provided the
platform supports it (like Auxiliary power source etc). The changes listed
below are done to fix this.

1) There's no need to defer the HW configuration of WOL to be_suspend().
Remove this in be_suspend() and move it to be_set_wol() ethtool function
so it is configured directly in the context of ethtool. This automatically
takes care of the shutdown case.

2) The driver incorrectly uses WOL_CAP field in the FW response to
get_acpi_wol_cap() command, to determine if WOL is enabled. Instead the
driver must rely on the macaddr field in the response to infer WOL state.

3) In be_get_config() during init, if we find that WOL is enabled in FW,
call pci_enable_wake() to enable pmcsr.pme_en bit. This is needed to
support persistent WOL configuration provided by the FW in some platforms.

4) Remove code in be_set_wol() that writes to PCICFG_PM_CONTROL_OFFSET
to set pme_en bit; pci_enable_wake() sets that.

Fixes: 028991e4 ("Enabling Wake-on-LAN is not supported in S5 state")
Signed-off-by: default avatarSriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: default avatarSathya Perla <sathya.perla@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9263cbf
......@@ -4023,7 +4023,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *)cmd.va;
adapter->wol_cap = resp->wol_settings;
if (adapter->wol_cap & BE_WOL_CAP)
/* Non-zero macaddr indicates WOL is enabled */
if (adapter->wol_cap & BE_WOL_CAP &&
!is_zero_ether_addr(resp->magic_mac))
adapter->wol_en = true;
}
err:
......
......@@ -1556,7 +1556,9 @@ struct be_cmd_resp_acpi_wol_magic_config_v1 {
u8 rsvd0[2];
u8 wol_settings;
u8 rsvd1[5];
u32 rsvd2[295];
u32 rsvd2[288];
u8 magic_mac[6];
u8 rsvd3[22];
} __packed;
#define BE_GET_WOL_CAP 2
......
......@@ -793,6 +793,11 @@ static void be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct be_adapter *adapter = netdev_priv(netdev);
struct device *dev = &adapter->pdev->dev;
struct be_dma_mem cmd;
u8 mac[ETH_ALEN];
bool enable;
int status;
if (wol->wolopts & ~WAKE_MAGIC)
return -EOPNOTSUPP;
......@@ -802,12 +807,32 @@ static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return -EOPNOTSUPP;
}
if (wol->wolopts & WAKE_MAGIC)
adapter->wol_en = true;
else
adapter->wol_en = false;
cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
if (!cmd.va)
return -ENOMEM;
return 0;
eth_zero_addr(mac);
enable = wol->wolopts & WAKE_MAGIC;
if (enable)
ether_addr_copy(mac, adapter->netdev->dev_addr);
status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
if (status) {
dev_err(dev, "Could not set Wake-on-lan mac address\n");
status = be_cmd_status(status);
goto err;
}
pci_enable_wake(adapter->pdev, PCI_D3hot, enable);
pci_enable_wake(adapter->pdev, PCI_D3cold, enable);
adapter->wol_en = enable ? true : false;
err:
dma_free_coherent(dev, cmd.size, cmd.va, cmd.dma);
return status;
}
static int be_test_ddr_dma(struct be_adapter *adapter)
......
......@@ -3636,40 +3636,6 @@ static int be_open(struct net_device *netdev)
return -EIO;
}
static int be_setup_wol(struct be_adapter *adapter, bool enable)
{
struct device *dev = &adapter->pdev->dev;
struct be_dma_mem cmd;
u8 mac[ETH_ALEN];
int status;
eth_zero_addr(mac);
cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
if (!cmd.va)
return -ENOMEM;
if (enable) {
status = pci_write_config_dword(adapter->pdev,
PCICFG_PM_CONTROL_OFFSET,
PCICFG_PM_CONTROL_MASK);
if (status) {
dev_err(dev, "Could not enable Wake-on-lan\n");
goto err;
}
} else {
ether_addr_copy(mac, adapter->netdev->dev_addr);
}
status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
pci_enable_wake(adapter->pdev, PCI_D3hot, enable);
pci_enable_wake(adapter->pdev, PCI_D3cold, enable);
err:
dma_free_coherent(dev, cmd.size, cmd.va, cmd.dma);
return status;
}
static void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
{
u32 addr;
......@@ -4294,6 +4260,8 @@ static int be_get_config(struct be_adapter *adapter)
}
be_cmd_get_acpi_wol_cap(adapter);
pci_enable_wake(adapter->pdev, PCI_D3hot, adapter->wol_en);
pci_enable_wake(adapter->pdev, PCI_D3cold, adapter->wol_en);
be_cmd_query_port_name(adapter);
......@@ -5463,9 +5431,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct be_adapter *adapter = pci_get_drvdata(pdev);
if (adapter->wol_en)
be_setup_wol(adapter, true);
be_intr_set(adapter, false);
be_cancel_err_detection(adapter);
......@@ -5494,9 +5459,6 @@ static int be_pci_resume(struct pci_dev *pdev)
be_schedule_err_detection(adapter, ERR_DETECTION_DELAY);
if (adapter->wol_en)
be_setup_wol(adapter, false);
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment