Skip to content

Commit

Permalink
be2net: Support for WoL using magic packet after suspend.
Browse files Browse the repository at this point in the history
Add support for WOL using Magic Packet after suspend is done.

Signed-off-by: Sarveshwar Bandi <sarveshwarb@serverengines.com>
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ajit Khaparde authored and David S. Miller committed Dec 3, 2009
1 parent d744b44 commit 71d8d1b
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/benet/be.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ struct be_adapter {
bool link_up;
u32 port_num;
bool promiscuous;
bool wol;
u32 cap;
u32 rx_fc; /* Rx flow control */
u32 tx_fc; /* Tx flow control */
Expand Down
36 changes: 36 additions & 0 deletions drivers/net/benet/be_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -1442,3 +1442,39 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc)
spin_unlock_bh(&adapter->mcc_lock);
return status;
}

extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
struct be_dma_mem *nonemb_cmd)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_acpi_wol_magic_config *req;
struct be_sge *sge;
int status;

spin_lock_bh(&adapter->mcc_lock);

wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
goto err;
}
req = nonemb_cmd->va;
sge = nonembedded_sgl(wrb);

be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG);

be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req));
memcpy(req->magic_mac, mac, ETH_ALEN);

sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd->size);

status = be_mcc_notify_wait(adapter);

err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
11 changes: 11 additions & 0 deletions drivers/net/benet/be_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ struct be_mcc_mailbox {
#define OPCODE_ETH_RX_CREATE 8
#define OPCODE_ETH_TX_DESTROY 9
#define OPCODE_ETH_RX_DESTROY 10
#define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG 12

struct be_cmd_req_hdr {
u8 opcode; /* dword 0 */
Expand Down Expand Up @@ -788,6 +789,14 @@ struct be_cmd_write_flashrom {
struct flashrom_params params;
};

/************************ WOL *******************************/
struct be_cmd_req_acpi_wol_magic_config{
struct be_cmd_req_hdr hdr;
u32 rsvd0[145];
u8 magic_mac[6];
u8 rsvd2[2];
} __packed;

extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_cmd_POST(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
Expand Down Expand Up @@ -851,5 +860,7 @@ extern int be_cmd_write_flashrom(struct be_adapter *adapter,
struct be_dma_mem *cmd, u32 flash_oper,
u32 flash_opcode, u32 buf_size);
extern int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc);
extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
struct be_dma_mem *nonemb_cmd);
extern int be_cmd_fw_init(struct be_adapter *adapter);
extern int be_cmd_fw_clean(struct be_adapter *adapter);
32 changes: 32 additions & 0 deletions drivers/net/benet/be_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,36 @@ be_phys_id(struct net_device *netdev, u32 data)
return status;
}

static void
be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct be_adapter *adapter = netdev_priv(netdev);

wol->supported = WAKE_MAGIC;
if (adapter->wol)
wol->wolopts = WAKE_MAGIC;
else
wol->wolopts = 0;
memset(&wol->sopass, 0, sizeof(wol->sopass));
return;
}

static int
be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct be_adapter *adapter = netdev_priv(netdev);

if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;

if (wol->wolopts & WAKE_MAGIC)
adapter->wol = true;
else
adapter->wol = false;

return 0;
}

static int
be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
{
Expand All @@ -428,6 +458,8 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
const struct ethtool_ops be_ethtool_ops = {
.get_settings = be_get_settings,
.get_drvinfo = be_get_drvinfo,
.get_wol = be_get_wol,
.set_wol = be_set_wol,
.get_link = ethtool_op_get_link,
.get_coalesce = be_get_coalesce,
.set_coalesce = be_set_coalesce,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/benet/be_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
*/
#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */

/********* Power managment (WOL) **********/
#define PCICFG_PM_CONTROL_OFFSET 0x44
#define PCICFG_PM_CONTROL_MASK 0x108 /* bits 3 & 8 */

/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
#define CEV_ISR_SIZE 4
Expand Down
44 changes: 44 additions & 0 deletions drivers/net/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,44 @@ static int be_open(struct net_device *netdev)
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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 71d8d1b

Please sign in to comment.