diff options
author | Ajit Khaparde <ajitk@serverengines.com> | 2009-12-03 01:16:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-03 15:39:21 -0500 |
commit | 71d8d1b58aa4025ea73a66a130a98d0ed077f9b1 (patch) | |
tree | 36034463fa1b1438ad018fbaafbe9dac60159751 /drivers/net/benet | |
parent | d744b44e21a2c908aae23a60da1b4ce35cd925ef (diff) |
be2net: Support for WoL using magic packet after suspend.
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>
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.c | 36 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.h | 11 | ||||
-rw-r--r-- | drivers/net/benet/be_ethtool.c | 32 | ||||
-rw-r--r-- | drivers/net/benet/be_hw.h | 4 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 44 |
6 files changed, 128 insertions, 0 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 12247480a1f8..e71cc5949413 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
@@ -269,6 +269,7 @@ struct be_adapter { | |||
269 | bool link_up; | 269 | bool link_up; |
270 | u32 port_num; | 270 | u32 port_num; |
271 | bool promiscuous; | 271 | bool promiscuous; |
272 | bool wol; | ||
272 | u32 cap; | 273 | u32 cap; |
273 | u32 rx_fc; /* Rx flow control */ | 274 | u32 rx_fc; /* Rx flow control */ |
274 | u32 tx_fc; /* Tx flow control */ | 275 | u32 tx_fc; /* Tx flow control */ |
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 5ec61de3b97f..bee7b822d120 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
@@ -1442,3 +1442,39 @@ err: | |||
1442 | spin_unlock_bh(&adapter->mcc_lock); | 1442 | spin_unlock_bh(&adapter->mcc_lock); |
1443 | return status; | 1443 | return status; |
1444 | } | 1444 | } |
1445 | |||
1446 | extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, | ||
1447 | struct be_dma_mem *nonemb_cmd) | ||
1448 | { | ||
1449 | struct be_mcc_wrb *wrb; | ||
1450 | struct be_cmd_req_acpi_wol_magic_config *req; | ||
1451 | struct be_sge *sge; | ||
1452 | int status; | ||
1453 | |||
1454 | spin_lock_bh(&adapter->mcc_lock); | ||
1455 | |||
1456 | wrb = wrb_from_mccq(adapter); | ||
1457 | if (!wrb) { | ||
1458 | status = -EBUSY; | ||
1459 | goto err; | ||
1460 | } | ||
1461 | req = nonemb_cmd->va; | ||
1462 | sge = nonembedded_sgl(wrb); | ||
1463 | |||
1464 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, | ||
1465 | OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG); | ||
1466 | |||
1467 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, | ||
1468 | OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req)); | ||
1469 | memcpy(req->magic_mac, mac, ETH_ALEN); | ||
1470 | |||
1471 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
1472 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
1473 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
1474 | |||
1475 | status = be_mcc_notify_wait(adapter); | ||
1476 | |||
1477 | err: | ||
1478 | spin_unlock_bh(&adapter->mcc_lock); | ||
1479 | return status; | ||
1480 | } | ||
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 8ec6528cb054..e8512a144f5e 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h | |||
@@ -150,6 +150,7 @@ struct be_mcc_mailbox { | |||
150 | #define OPCODE_ETH_RX_CREATE 8 | 150 | #define OPCODE_ETH_RX_CREATE 8 |
151 | #define OPCODE_ETH_TX_DESTROY 9 | 151 | #define OPCODE_ETH_TX_DESTROY 9 |
152 | #define OPCODE_ETH_RX_DESTROY 10 | 152 | #define OPCODE_ETH_RX_DESTROY 10 |
153 | #define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG 12 | ||
153 | 154 | ||
154 | struct be_cmd_req_hdr { | 155 | struct be_cmd_req_hdr { |
155 | u8 opcode; /* dword 0 */ | 156 | u8 opcode; /* dword 0 */ |
@@ -788,6 +789,14 @@ struct be_cmd_write_flashrom { | |||
788 | struct flashrom_params params; | 789 | struct flashrom_params params; |
789 | }; | 790 | }; |
790 | 791 | ||
792 | /************************ WOL *******************************/ | ||
793 | struct be_cmd_req_acpi_wol_magic_config{ | ||
794 | struct be_cmd_req_hdr hdr; | ||
795 | u32 rsvd0[145]; | ||
796 | u8 magic_mac[6]; | ||
797 | u8 rsvd2[2]; | ||
798 | } __packed; | ||
799 | |||
791 | extern int be_pci_fnum_get(struct be_adapter *adapter); | 800 | extern int be_pci_fnum_get(struct be_adapter *adapter); |
792 | extern int be_cmd_POST(struct be_adapter *adapter); | 801 | extern int be_cmd_POST(struct be_adapter *adapter); |
793 | extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, | 802 | extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, |
@@ -851,5 +860,7 @@ extern int be_cmd_write_flashrom(struct be_adapter *adapter, | |||
851 | struct be_dma_mem *cmd, u32 flash_oper, | 860 | struct be_dma_mem *cmd, u32 flash_oper, |
852 | u32 flash_opcode, u32 buf_size); | 861 | u32 flash_opcode, u32 buf_size); |
853 | extern int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc); | 862 | extern int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc); |
863 | extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, | ||
864 | struct be_dma_mem *nonemb_cmd); | ||
854 | extern int be_cmd_fw_init(struct be_adapter *adapter); | 865 | extern int be_cmd_fw_init(struct be_adapter *adapter); |
855 | extern int be_cmd_fw_clean(struct be_adapter *adapter); | 866 | extern int be_cmd_fw_clean(struct be_adapter *adapter); |
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 329560f9e543..83a2fc703995 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c | |||
@@ -411,6 +411,36 @@ be_phys_id(struct net_device *netdev, u32 data) | |||
411 | return status; | 411 | return status; |
412 | } | 412 | } |
413 | 413 | ||
414 | static void | ||
415 | be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||
416 | { | ||
417 | struct be_adapter *adapter = netdev_priv(netdev); | ||
418 | |||
419 | wol->supported = WAKE_MAGIC; | ||
420 | if (adapter->wol) | ||
421 | wol->wolopts = WAKE_MAGIC; | ||
422 | else | ||
423 | wol->wolopts = 0; | ||
424 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | static int | ||
429 | be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||
430 | { | ||
431 | struct be_adapter *adapter = netdev_priv(netdev); | ||
432 | |||
433 | if (wol->wolopts & ~WAKE_MAGIC) | ||
434 | return -EINVAL; | ||
435 | |||
436 | if (wol->wolopts & WAKE_MAGIC) | ||
437 | adapter->wol = true; | ||
438 | else | ||
439 | adapter->wol = false; | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
414 | static int | 444 | static int |
415 | be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) | 445 | be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) |
416 | { | 446 | { |
@@ -428,6 +458,8 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) | |||
428 | const struct ethtool_ops be_ethtool_ops = { | 458 | const struct ethtool_ops be_ethtool_ops = { |
429 | .get_settings = be_get_settings, | 459 | .get_settings = be_get_settings, |
430 | .get_drvinfo = be_get_drvinfo, | 460 | .get_drvinfo = be_get_drvinfo, |
461 | .get_wol = be_get_wol, | ||
462 | .set_wol = be_set_wol, | ||
431 | .get_link = ethtool_op_get_link, | 463 | .get_link = ethtool_op_get_link, |
432 | .get_coalesce = be_get_coalesce, | 464 | .get_coalesce = be_get_coalesce, |
433 | .set_coalesce = be_set_coalesce, | 465 | .set_coalesce = be_set_coalesce, |
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index f53d5ca2da9e..e2b3beffd49d 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h | |||
@@ -52,6 +52,10 @@ | |||
52 | */ | 52 | */ |
53 | #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ | 53 | #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ |
54 | 54 | ||
55 | /********* Power managment (WOL) **********/ | ||
56 | #define PCICFG_PM_CONTROL_OFFSET 0x44 | ||
57 | #define PCICFG_PM_CONTROL_MASK 0x108 /* bits 3 & 8 */ | ||
58 | |||
55 | /********* ISR0 Register offset **********/ | 59 | /********* ISR0 Register offset **********/ |
56 | #define CEV_ISR0_OFFSET 0xC18 | 60 | #define CEV_ISR0_OFFSET 0xC18 |
57 | #define CEV_ISR_SIZE 4 | 61 | #define CEV_ISR_SIZE 4 |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index f24ac4b5ce8f..84f686f41b53 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -1659,6 +1659,44 @@ ret_sts: | |||
1659 | return status; | 1659 | return status; |
1660 | } | 1660 | } |
1661 | 1661 | ||
1662 | static int be_setup_wol(struct be_adapter *adapter, bool enable) | ||
1663 | { | ||
1664 | struct be_dma_mem cmd; | ||
1665 | int status = 0; | ||
1666 | u8 mac[ETH_ALEN]; | ||
1667 | |||
1668 | memset(mac, 0, ETH_ALEN); | ||
1669 | |||
1670 | cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config); | ||
1671 | cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); | ||
1672 | if (cmd.va == NULL) | ||
1673 | return -1; | ||
1674 | memset(cmd.va, 0, cmd.size); | ||
1675 | |||
1676 | if (enable) { | ||
1677 | status = pci_write_config_dword(adapter->pdev, | ||
1678 | PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK); | ||
1679 | if (status) { | ||
1680 | dev_err(&adapter->pdev->dev, | ||
1681 | "Could not enable Wake-on-lan \n"); | ||
1682 | pci_free_consistent(adapter->pdev, cmd.size, cmd.va, | ||
1683 | cmd.dma); | ||
1684 | return status; | ||
1685 | } | ||
1686 | status = be_cmd_enable_magic_wol(adapter, | ||
1687 | adapter->netdev->dev_addr, &cmd); | ||
1688 | pci_enable_wake(adapter->pdev, PCI_D3hot, 1); | ||
1689 | pci_enable_wake(adapter->pdev, PCI_D3cold, 1); | ||
1690 | } else { | ||
1691 | status = be_cmd_enable_magic_wol(adapter, mac, &cmd); | ||
1692 | pci_enable_wake(adapter->pdev, PCI_D3hot, 0); | ||
1693 | pci_enable_wake(adapter->pdev, PCI_D3cold, 0); | ||
1694 | } | ||
1695 | |||
1696 | pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); | ||
1697 | return status; | ||
1698 | } | ||
1699 | |||
1662 | static int be_setup(struct be_adapter *adapter) | 1700 | static int be_setup(struct be_adapter *adapter) |
1663 | { | 1701 | { |
1664 | struct net_device *netdev = adapter->netdev; | 1702 | struct net_device *netdev = adapter->netdev; |
@@ -2282,6 +2320,9 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2282 | struct be_adapter *adapter = pci_get_drvdata(pdev); | 2320 | struct be_adapter *adapter = pci_get_drvdata(pdev); |
2283 | struct net_device *netdev = adapter->netdev; | 2321 | struct net_device *netdev = adapter->netdev; |
2284 | 2322 | ||
2323 | if (adapter->wol) | ||
2324 | be_setup_wol(adapter, true); | ||
2325 | |||
2285 | netif_device_detach(netdev); | 2326 | netif_device_detach(netdev); |
2286 | if (netif_running(netdev)) { | 2327 | if (netif_running(netdev)) { |
2287 | rtnl_lock(); | 2328 | rtnl_lock(); |
@@ -2324,6 +2365,9 @@ static int be_resume(struct pci_dev *pdev) | |||
2324 | rtnl_unlock(); | 2365 | rtnl_unlock(); |
2325 | } | 2366 | } |
2326 | netif_device_attach(netdev); | 2367 | netif_device_attach(netdev); |
2368 | |||
2369 | if (adapter->wol) | ||
2370 | be_setup_wol(adapter, false); | ||
2327 | return 0; | 2371 | return 0; |
2328 | } | 2372 | } |
2329 | 2373 | ||