diff options
Diffstat (limited to 'drivers/net/ethernet/wangxun/ngbe')
-rw-r--r-- | drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c | 35 | ||||
-rw-r--r-- | drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 64 | ||||
-rw-r--r-- | drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c | 88 | ||||
-rw-r--r-- | drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 19 |
4 files changed, 137 insertions, 69 deletions
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c index 5b25834baf38..ec0e869e9aac 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c @@ -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) diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index c99a5d3de72e..2b431db6085a 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -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, }; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c index c9ddbbc3fa4f..591f5b7b6da6 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c @@ -37,24 +37,24 @@ static int ngbe_phy_read_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int regn wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0xF); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(device_type); - wr32(wx, NGBE_MSCA, command); - command = NGBE_MSCC_CMD(NGBE_MSCA_CMD_READ) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(device_type); + wr32(wx, WX_MSCA, command); + command = WX_MSCC_CMD(WX_MSCA_CMD_READ) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) { wx_err(wx, "Mdio read c22 command did not complete.\n"); return ret; } - return (u16)rd32(wx, NGBE_MSCC); + return (u16)rd32(wx, WX_MSCC); } static int ngbe_phy_write_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int regnum, u16 value) @@ -65,19 +65,19 @@ static int ngbe_phy_write_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int reg wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0xF); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(device_type); - wr32(wx, NGBE_MSCA, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(device_type); + wr32(wx, WX_MSCA, command); command = value | - NGBE_MSCC_CMD(NGBE_MSCA_CMD_WRITE) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + WX_MSCC_CMD(WX_MSCA_CMD_WRITE) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) wx_err(wx, "Mdio write c22 command did not complete.\n"); @@ -92,24 +92,24 @@ static int ngbe_phy_read_reg_mdi_c45(struct mii_bus *bus, int phy_addr, int devn wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0x0); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(devnum); - wr32(wx, NGBE_MSCA, command); - command = NGBE_MSCC_CMD(NGBE_MSCA_CMD_READ) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(devnum); + wr32(wx, WX_MSCA, command); + command = WX_MSCC_CMD(WX_MSCA_CMD_READ) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) { wx_err(wx, "Mdio read c45 command did not complete.\n"); return ret; } - return (u16)rd32(wx, NGBE_MSCC); + return (u16)rd32(wx, WX_MSCC); } static int ngbe_phy_write_reg_mdi_c45(struct mii_bus *bus, int phy_addr, @@ -121,19 +121,19 @@ static int ngbe_phy_write_reg_mdi_c45(struct mii_bus *bus, int phy_addr, wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0x0); /* setup and write the address cycle command */ - command = NGBE_MSCA_RA(regnum) | - NGBE_MSCA_PA(phy_addr) | - NGBE_MSCA_DA(devnum); - wr32(wx, NGBE_MSCA, command); + command = WX_MSCA_RA(regnum) | + WX_MSCA_PA(phy_addr) | + WX_MSCA_DA(devnum); + wr32(wx, WX_MSCA, command); command = value | - NGBE_MSCC_CMD(NGBE_MSCA_CMD_WRITE) | - NGBE_MSCC_BUSY | - NGBE_MDIO_CLK(6); - wr32(wx, NGBE_MSCC, command); + WX_MSCC_CMD(WX_MSCA_CMD_WRITE) | + WX_MSCC_BUSY | + WX_MDIO_CLK(6); + wr32(wx, WX_MSCC, command); /* wait to complete */ - ret = read_poll_timeout(rd32, val, !(val & NGBE_MSCC_BUSY), 1000, - 100000, false, wx, NGBE_MSCC); + ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000, + 100000, false, wx, WX_MSCC); if (ret) wx_err(wx, "Mdio write c45 command did not complete.\n"); @@ -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 */ @@ -265,8 +266,7 @@ int ngbe_mdio_init(struct wx *wx) mii_bus->write_c45 = ngbe_phy_write_reg_mdi_c45; } - snprintf(mii_bus->id, MII_BUS_ID_SIZE, "ngbe-%x", - (pdev->bus->number << 8) | pdev->devfn); + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "ngbe-%x", pci_dev_id(pdev)); ret = devm_mdiobus_register(&pdev->dev, mii_bus); if (ret) return ret; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h index b70eca397b67..72c8cd2d5575 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h @@ -59,25 +59,6 @@ #define NGBE_EEPROM_VERSION_L 0x1D #define NGBE_EEPROM_VERSION_H 0x1E -/* mdio access */ -#define NGBE_MSCA 0x11200 -#define NGBE_MSCA_RA(v) FIELD_PREP(U16_MAX, v) -#define NGBE_MSCA_PA(v) FIELD_PREP(GENMASK(20, 16), v) -#define NGBE_MSCA_DA(v) FIELD_PREP(GENMASK(25, 21), v) -#define NGBE_MSCC 0x11204 -#define NGBE_MSCC_CMD(v) FIELD_PREP(GENMASK(17, 16), v) - -enum NGBE_MSCA_CMD_value { - NGBE_MSCA_CMD_RSV = 0, - NGBE_MSCA_CMD_WRITE, - NGBE_MSCA_CMD_POST_READ, - NGBE_MSCA_CMD_READ, -}; - -#define NGBE_MSCC_SADDR BIT(18) -#define NGBE_MSCC_BUSY BIT(22) -#define NGBE_MDIO_CLK(v) FIELD_PREP(GENMASK(21, 19), v) - /* Media-dependent registers. */ #define NGBE_MDIO_CLAUSE_SELECT 0x11220 |