net: stmmac: get set wol & duplicate message fix

Add support for get & set wol from the ethtool.
Also, remove duplicate message.

Change-Id: Ia7fab9706d6b67e469eac5153060cdd670c65605
Signed-off-by: Suraj Jaiswal <jsuraj@codeaurora.org>
tirimbino
Suraj Jaiswal 5 years ago committed by Gerrit - the friendly Code Review server
parent cb01cab585
commit d1247a832d
  1. 54
      drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
  2. 1
      drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h
  3. 6
      drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c
  4. 2
      drivers/net/ethernet/stmicro/stmmac/stmmac.h
  5. 64
      drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
  6. 9
      drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

@ -321,7 +321,7 @@ static int qcom_ethqos_add_ipaddr(struct ip_params *ip_info,
struct net *net = dev_net(dev);
if (!net || !net->genl_sock || !net->genl_sock->sk_socket) {
ETHQOSINFO("Sock is null, unable to assign ipv4 address\n");
ETHQOSERR("Sock is null, unable to assign ipv4 address\n");
return res;
}
/*For valid Ipv4 address*/
@ -972,6 +972,8 @@ static void ethqos_handle_phy_interrupt(struct qcom_ethqos *ethqos)
phy_mac_interrupt(dev->phydev, LINK_DOWN);
} else if (!(phy_intr_status & AUTONEG_STATE_MASK)) {
ETHQOSDBG("Intr for link down with auto-neg err\n");
} else if (phy_intr_status & PHY_WOL) {
ETHQOSDBG("Interrupt received for WoL packet\n");
}
} else {
phy_intr_status =
@ -1406,7 +1408,7 @@ static int ethqos_update_rgmii_tx_drv_strength(struct qcom_ethqos *ethqos)
ethqos->pdev, IORESOURCE_MEM, "tlmm-central-base");
if (!resource) {
ETHQOSINFO("Resource tlmm-central-base not found\n");
ETHQOSERR("Resource tlmm-central-base not found\n");
goto err_out;
}
@ -1507,7 +1509,8 @@ inline bool qcom_ethqos_is_phy_link_up(struct qcom_ethqos *ethqos)
*/
struct stmmac_priv *priv = qcom_ethqos_get_priv(ethqos);
return (priv->dev->phydev && priv->dev->phydev->link);
return ((priv->oldlink != -1) &&
(priv->dev->phydev && priv->dev->phydev->link));
}
static void qcom_ethqos_phy_resume_clks(struct qcom_ethqos *ethqos)
@ -1587,11 +1590,11 @@ void qcom_ethqos_request_phy_wol(struct plat_stmmacenet_data *plat)
wol.supported = 0;
wol.wolopts = 0;
ETHQOSINFO("phydev addr: 0x%pK\n", priv->phydev);
ETHQOSDBG("phydev addr: %x\n", priv->phydev);
phy_ethtool_get_wol(priv->phydev, &wol);
ethqos->phy_wol_supported = wol.supported;
ETHQOSINFO("Get WoL[0x%x] in %s\n", wol.supported,
priv->phydev->drv->name);
ETHQOSDBG("Get WoL[0x%x] in %s\n", wol.supported,
priv->phydev->drv->name);
/* Try to enable supported Wake-on-LAN features in PHY*/
if (wol.supported) {
@ -1606,9 +1609,9 @@ void qcom_ethqos_request_phy_wol(struct plat_stmmacenet_data *plat)
enable_irq_wake(ethqos->phy_intr);
device_set_wakeup_enable(&ethqos->pdev->dev, 1);
ETHQOSINFO("Enabled WoL[0x%x] in %s\n",
wol.wolopts,
priv->phydev->drv->name);
ETHQOSDBG("Enabled WoL[0x%x] in %s\n",
wol.wolopts,
priv->phydev->drv->name);
} else {
ETHQOSINFO("Disabled WoL[0x%x] in %s\n",
wol.wolopts,
@ -1626,7 +1629,7 @@ static void ethqos_is_ipv4_NW_stack_ready(struct work_struct *work)
struct net_device *ndev = NULL;
int ret;
ETHQOSINFO("\n");
ETHQOSDBG("Enter\n");
dwork = container_of(work, struct delayed_work, work);
ethqos = container_of(dwork, struct qcom_ethqos, ipv4_addr_assign_wq);
@ -1656,7 +1659,7 @@ static void ethqos_is_ipv6_NW_stack_ready(struct work_struct *work)
struct net_device *ndev = NULL;
int ret;
ETHQOSINFO("\n");
ETHQOSDBG("Enter\n");
dwork = container_of(work, struct delayed_work, work);
ethqos = container_of(dwork, struct qcom_ethqos, ipv6_addr_assign_wq);
@ -1725,6 +1728,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
struct stmmac_priv *priv;
int ret;
if (of_device_is_compatible(pdev->dev.of_node,
"qcom,emac-smmu-embedded"))
return stmmac_emb_smmu_cb_probe(pdev);
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
place_marker("M - Ethernet probe start");
#endif
@ -1734,11 +1741,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (!ipc_stmmac_log_ctxt)
ETHQOSERR("Error creating logging context for emac\n");
else
ETHQOSINFO("IPC logging has been enabled for emac\n");
if (of_device_is_compatible(pdev->dev.of_node,
"qcom,emac-smmu-embedded"))
return stmmac_emb_smmu_cb_probe(pdev);
ETHQOSDBG("IPC logging has been enabled for emac\n");
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;
@ -1880,15 +1883,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ndev = dev_get_drvdata(&ethqos->pdev->dev);
priv = netdev_priv(ndev);
if (priv->phydev && priv->phydev->drv &&
priv->phydev->drv->config_intr &&
!priv->phydev->drv->config_intr(priv->phydev)) {
qcom_ethqos_request_phy_wol(priv->plat);
priv->phydev->irq = PHY_IGNORE_INTERRUPT;
priv->phydev->interrupts = PHY_INTERRUPT_ENABLED;
} else {
ETHQOSERR("config_phy_intr configuration failed");
}
if (ethqos->early_eth_enabled) {
/* Initialize work*/
INIT_WORK(&ethqos->early_eth,
@ -2038,22 +2032,22 @@ static int __init qcom_ethqos_init_module(void)
{
int ret = 0;
ETHQOSINFO("\n");
ETHQOSDBG("Enter\n");
ret = platform_driver_register(&qcom_ethqos_driver);
if (ret < 0) {
ETHQOSINFO("qcom-ethqos: Driver registration failed");
ETHQOSERR("qcom-ethqos: Driver registration failed");
return ret;
}
ETHQOSINFO("\n");
ETHQOSDBG("Exit\n");
return ret;
}
static void __exit qcom_ethqos_exit_module(void)
{
ETHQOSINFO("\n");
ETHQOSDBG("Enter\n");
platform_driver_unregister(&qcom_ethqos_driver);
@ -2065,7 +2059,7 @@ static void __exit qcom_ethqos_exit_module(void)
ipc_stmmac_log_ctxt = NULL;
ipc_stmmac_log_ctxt_low = NULL;
ETHQOSINFO("\n");
ETHQOSDBG("Exit\n");
}
/*!

@ -229,6 +229,7 @@ do {\
#define LINK_STATE_MASK 0x4
#define AUTONEG_STATE_MASK 0x20
#define MICREL_LINK_UP_INTR_STATUS BIT(0)
#define PHY_WOL 0x1
#define VOTE_IDX_0MBPS 0
#define VOTE_IDX_10MBPS 1

@ -1,4 +1,4 @@
/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -226,7 +226,7 @@ int ethqos_init_pinctrl(struct device *dev)
return ret;
}
ETHQOSINFO("pinctrl_lookup_state %s succeded\n", name);
ETHQOSDBG("pinctrl_lookup_state %s succeded\n", name);
ret = pinctrl_select_state(pinctrl, pinctrl_state);
if (ret) {
@ -234,7 +234,7 @@ int ethqos_init_pinctrl(struct device *dev)
return ret;
}
ETHQOSINFO("pinctrl_select_state %s succeded\n", name);
ETHQOSDBG("pinctrl_select_state %s succeded\n", name);
}
return ret;

@ -113,7 +113,7 @@ struct stmmac_priv {
/* TX Queue */
struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES];
bool oldlink;
int oldlink;
int speed;
int oldduplex;
unsigned int flow_ctrl;

@ -28,6 +28,7 @@
#include "stmmac.h"
#include "dwmac_dma.h"
#include "dwmac-qcom-ethqos.h"
#define REG_SPACE_SIZE 0x1060
#define MAC100_ETHTOOL_NAME "st_mac100"
@ -626,10 +627,11 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct stmmac_priv *priv = netdev_priv(dev);
phy_ethtool_get_wol(priv->phydev, wol);
mutex_lock(&priv->lock);
if (device_can_wakeup(priv->device)) {
wol->supported = WAKE_MAGIC | WAKE_UCAST;
wol->wolopts = priv->wolopts;
wol->wolopts |= priv->wolopts;
}
mutex_unlock(&priv->lock);
}
@ -637,33 +639,63 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct stmmac_priv *priv = netdev_priv(dev);
u32 support = WAKE_MAGIC | WAKE_UCAST;
struct qcom_ethqos *ethqos = priv->plat->bsp_priv;
u32 emac_wol_support = 0;
int ret;
/* By default almost all GMAC devices support the WoL via
* magic frame but we can disable it if the HW capability
* register shows no support for pmt_magic_frame. */
if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame))
wol->wolopts &= ~WAKE_MAGIC;
if (priv->hw_cap_support && priv->dma_cap.pmt_magic_frame)
wol->wolopts |= WAKE_MAGIC;
if (priv->hw_cap_support && priv->dma_cap.pmt_remote_wake_up)
wol->wolopts |= WAKE_UCAST;
if (wol->wolopts & ~(emac_wol_support | ethqos->phy_wol_supported))
return -EOPNOTSUPP;
if (!device_can_wakeup(priv->device))
return -EINVAL;
if (wol->wolopts & ~support)
return -EINVAL;
mutex_lock(&priv->lock);
if (priv->hw_cap_support && priv->dma_cap.pmt_magic_frame)
priv->wolopts |= WAKE_MAGIC;
if (priv->hw_cap_support && priv->dma_cap.pmt_remote_wake_up)
priv->wolopts |= WAKE_UCAST;
mutex_unlock(&priv->lock);
if (wol->wolopts) {
pr_info("stmmac: wakeup enable\n");
device_set_wakeup_enable(priv->device, 1);
enable_irq_wake(priv->wol_irq);
} else {
device_set_wakeup_enable(priv->device, 0);
disable_irq_wake(priv->wol_irq);
if (emac_wol_support && priv->wolopts != wol->wolopts) {
if (priv->wolopts) {
pr_info("stmmac: wakeup enable\n");
device_set_wakeup_enable(&ethqos->pdev->dev, 1);
enable_irq_wake(ethqos->phy_intr);
} else {
device_set_wakeup_enable(&ethqos->pdev->dev, 0);
disable_irq_wake(ethqos->phy_intr);
}
}
mutex_lock(&priv->lock);
priv->wolopts = wol->wolopts;
mutex_unlock(&priv->lock);
if (ethqos->phy_wol_wolopts != wol->wolopts) {
if (phy_intr_en && ethqos->phy_wol_supported) {
ethqos->phy_wol_wolopts = 0;
ret = phy_ethtool_set_wol(priv->phydev, wol);
if (ret) {
pr_err("set wol in PHY failed\n");
return ret;
}
ethqos->phy_wol_wolopts = wol->wolopts;
if (ethqos->phy_wol_wolopts) {
enable_irq_wake(ethqos->phy_intr);
device_set_wakeup_enable(&ethqos->pdev->dev, 1);
} else {
disable_irq_wake(ethqos->phy_intr);
device_set_wakeup_enable(&ethqos->pdev->dev, 0);
}
}
}
return 0;
}

@ -843,7 +843,7 @@ static void stmmac_adjust_link(struct net_device *dev)
writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
if (!priv->oldlink) {
if (!priv->oldlink || (priv->oldlink == -1)) {
new_state = true;
priv->oldlink = true;
}
@ -954,7 +954,7 @@ static int stmmac_init_phy(struct net_device *dev)
int interface = priv->plat->interface;
int max_speed = priv->plat->max_speed;
int ret = 0;
priv->oldlink = false;
priv->oldlink = -1;
priv->boot_kpi = false;
priv->speed = SPEED_UNKNOWN;
priv->oldduplex = DUPLEX_UNKNOWN;
@ -1001,9 +1001,6 @@ static int stmmac_init_phy(struct net_device *dev)
}
}
pr_info(" qcom-ethqos: %s early eth setting stmmac init\n",
__func__);
/* Stop Advertising 1000BASE Capability if interface is not GMII */
if ((interface == PHY_INTERFACE_MODE_MII) ||
(interface == PHY_INTERFACE_MODE_RMII) ||
@ -4640,7 +4637,7 @@ int stmmac_suspend(struct device *dev)
}
mutex_unlock(&priv->lock);
priv->oldlink = false;
priv->oldlink = -1;
priv->speed = SPEED_UNKNOWN;
priv->oldduplex = DUPLEX_UNKNOWN;
return 0;

Loading…
Cancel
Save