net: ngbe: add Wake on Lan support
Implement ethtool_ops get_wol and set_wol. Implement Wake-on-LAN support. Wol requires hardware board support which use sub id to identify. Magic packets are checked by fw, for now just support WAKE_MAGIC. Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
88085b3b83
commit
6963e46325
@ -1501,7 +1501,7 @@ static void wx_restore_vlan(struct wx *wx)
|
||||
*
|
||||
* Configure the Rx unit of the MAC after a reset.
|
||||
**/
|
||||
static void wx_configure_rx(struct wx *wx)
|
||||
void wx_configure_rx(struct wx *wx)
|
||||
{
|
||||
u32 psrtype, i;
|
||||
int ret;
|
||||
@ -1545,6 +1545,7 @@ static void wx_configure_rx(struct wx *wx)
|
||||
wx_enable_rx(wx);
|
||||
wx_enable_sec_rx_path(wx);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_configure_rx);
|
||||
|
||||
static void wx_configure_isb(struct wx *wx)
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ void wx_disable_rx(struct wx *wx);
|
||||
void wx_set_rx_mode(struct net_device *netdev);
|
||||
int wx_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring);
|
||||
void wx_configure_rx(struct wx *wx);
|
||||
void wx_configure(struct wx *wx);
|
||||
void wx_start_hw(struct wx *wx);
|
||||
int wx_disable_pcie_master(struct wx *wx);
|
||||
|
@ -160,6 +160,10 @@
|
||||
#define WX_PSR_LAN_FLEX_DW_H(_i) (0x15C04 + ((_i) * 16))
|
||||
#define WX_PSR_LAN_FLEX_MSK(_i) (0x15C08 + ((_i) * 16))
|
||||
|
||||
#define WX_PSR_WKUP_CTL 0x15B80
|
||||
/* Wake Up Filter Control Bit */
|
||||
#define WX_PSR_WKUP_CTL_MAG BIT(1) /* Magic Packet Wakeup Enable */
|
||||
|
||||
/* vlan tbl */
|
||||
#define WX_PSR_VLAN_TBL(_i) (0x16000 + ((_i) * 4))
|
||||
|
||||
@ -846,7 +850,7 @@ struct wx {
|
||||
int duplex;
|
||||
struct phy_device *phydev;
|
||||
|
||||
bool wol_enabled;
|
||||
bool wol_hw_supported;
|
||||
bool ncsi_enabled;
|
||||
bool gpio_ctrl;
|
||||
raw_spinlock_t gpio_lock;
|
||||
|
@ -6,14 +6,49 @@
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "../libwx/wx_ethtool.h"
|
||||
#include "../libwx/wx_type.h"
|
||||
#include "ngbe_ethtool.h"
|
||||
|
||||
static void ngbe_get_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
|
||||
if (!wx->wol_hw_supported)
|
||||
return;
|
||||
wol->supported = WAKE_MAGIC;
|
||||
wol->wolopts = 0;
|
||||
if (wx->wol & WX_PSR_WKUP_CTL_MAG)
|
||||
wol->wolopts |= WAKE_MAGIC;
|
||||
}
|
||||
|
||||
static int ngbe_set_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
struct pci_dev *pdev = wx->pdev;
|
||||
|
||||
if (!wx->wol_hw_supported)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
wx->wol = 0;
|
||||
if (wol->wolopts & WAKE_MAGIC)
|
||||
wx->wol = WX_PSR_WKUP_CTL_MAG;
|
||||
netdev->wol_enabled = !!(wx->wol);
|
||||
wr32(wx, WX_PSR_WKUP_CTL, wx->wol);
|
||||
device_set_wakeup_enable(&pdev->dev, netdev->wol_enabled);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops ngbe_ethtool_ops = {
|
||||
.get_drvinfo = wx_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_link_ksettings = phy_ethtool_get_link_ksettings,
|
||||
.set_link_ksettings = phy_ethtool_set_link_ksettings,
|
||||
.nway_reset = phy_ethtool_nway_reset,
|
||||
.get_wol = ngbe_get_wol,
|
||||
.set_wol = ngbe_set_wol,
|
||||
};
|
||||
|
||||
void ngbe_set_ethtool_ops(struct net_device *netdev)
|
||||
|
@ -62,7 +62,7 @@ static void ngbe_init_type_code(struct wx *wx)
|
||||
em_mac_type_rgmii :
|
||||
em_mac_type_mdi;
|
||||
|
||||
wx->wol_enabled = (wol_mask == NGBE_WOL_SUP) ? 1 : 0;
|
||||
wx->wol_hw_supported = (wol_mask == NGBE_WOL_SUP) ? 1 : 0;
|
||||
wx->ncsi_enabled = (ncsi_mask == NGBE_NCSI_MASK ||
|
||||
type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0;
|
||||
|
||||
@ -440,14 +440,26 @@ static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
||||
{
|
||||
struct wx *wx = pci_get_drvdata(pdev);
|
||||
struct net_device *netdev;
|
||||
u32 wufc = wx->wol;
|
||||
|
||||
netdev = wx->netdev;
|
||||
rtnl_lock();
|
||||
netif_device_detach(netdev);
|
||||
|
||||
rtnl_lock();
|
||||
if (netif_running(netdev))
|
||||
ngbe_down(wx);
|
||||
ngbe_close(netdev);
|
||||
wx_clear_interrupt_scheme(wx);
|
||||
rtnl_unlock();
|
||||
|
||||
if (wufc) {
|
||||
wx_set_rx_mode(netdev);
|
||||
wx_configure_rx(wx);
|
||||
wr32(wx, NGBE_PSR_WKUP_CTL, wufc);
|
||||
} else {
|
||||
wr32(wx, NGBE_PSR_WKUP_CTL, 0);
|
||||
}
|
||||
pci_wake_from_d3(pdev, !!wufc);
|
||||
*enable_wake = !!wufc;
|
||||
wx_control_hw(wx, false);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
@ -621,12 +633,11 @@ static int ngbe_probe(struct pci_dev *pdev,
|
||||
}
|
||||
|
||||
wx->wol = 0;
|
||||
if (wx->wol_enabled)
|
||||
if (wx->wol_hw_supported)
|
||||
wx->wol = NGBE_PSR_WKUP_CTL_MAG;
|
||||
|
||||
wx->wol_enabled = !!(wx->wol);
|
||||
netdev->wol_enabled = !!(wx->wol);
|
||||
wr32(wx, NGBE_PSR_WKUP_CTL, wx->wol);
|
||||
|
||||
device_set_wakeup_enable(&pdev->dev, wx->wol);
|
||||
|
||||
/* Save off EEPROM version number and Option Rom version which
|
||||
@ -712,11 +723,52 @@ static void ngbe_remove(struct pci_dev *pdev)
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
bool wake;
|
||||
|
||||
ngbe_dev_shutdown(pdev, &wake);
|
||||
device_set_wakeup_enable(&pdev->dev, wake);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ngbe_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
struct wx *wx;
|
||||
u32 err;
|
||||
|
||||
wx = pci_get_drvdata(pdev);
|
||||
netdev = wx->netdev;
|
||||
|
||||
err = pci_enable_device_mem(pdev);
|
||||
if (err) {
|
||||
wx_err(wx, "Cannot enable PCI device from suspend\n");
|
||||
return err;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
device_wakeup_disable(&pdev->dev);
|
||||
|
||||
ngbe_reset_hw(wx);
|
||||
rtnl_lock();
|
||||
err = wx_init_interrupt_scheme(wx);
|
||||
if (!err && netif_running(netdev))
|
||||
err = ngbe_open(netdev);
|
||||
if (!err)
|
||||
netif_device_attach(netdev);
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pci_driver ngbe_driver = {
|
||||
.name = ngbe_driver_name,
|
||||
.id_table = ngbe_pci_tbl,
|
||||
.probe = ngbe_probe,
|
||||
.remove = ngbe_remove,
|
||||
.suspend = ngbe_suspend,
|
||||
.resume = ngbe_resume,
|
||||
.shutdown = ngbe_shutdown,
|
||||
};
|
||||
|
||||
|
@ -236,6 +236,7 @@ static void ngbe_phy_fixup(struct wx *wx)
|
||||
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
|
||||
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
|
||||
|
||||
phydev->mac_managed_pm = true;
|
||||
if (wx->mac_type != em_mac_type_mdi)
|
||||
return;
|
||||
/* disable EEE, internal phy does not support eee */
|
||||
|
Loading…
x
Reference in New Issue
Block a user