Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1247a83 authored by Suraj Jaiswal's avatar Suraj Jaiswal Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarSuraj Jaiswal <jsuraj@codeaurora.org>
parent cb01cab5
Loading
Loading
Loading
Loading
+24 −30
Original line number Diff line number Diff line
@@ -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,10 +1590,10 @@ 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,
		ETHQOSDBG("Get WoL[0x%x] in %s\n", wol.supported,
			  priv->phydev->drv->name);

	/* Try to enable supported Wake-on-LAN features in PHY*/
@@ -1606,7 +1609,7 @@ 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",
				ETHQOSDBG("Enabled WoL[0x%x] in %s\n",
					  wol.wolopts,
					  priv->phydev->drv->name);
			} else {
@@ -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");
}

/*!
+1 −0
Original line number Diff line number Diff line
@@ -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
+3 −3
Original line number Diff line number Diff line
/* 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;
+1 −1
Original line number Diff line number Diff line
@@ -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;
+48 −16
Original line number Diff line number Diff line
@@ -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) {
	if (emac_wol_support && priv->wolopts != wol->wolopts) {
		if (priv->wolopts) {
			pr_info("stmmac: wakeup enable\n");
		device_set_wakeup_enable(priv->device, 1);
		enable_irq_wake(priv->wol_irq);
			device_set_wakeup_enable(&ethqos->pdev->dev, 1);
			enable_irq_wake(ethqos->phy_intr);
		} else {
		device_set_wakeup_enable(priv->device, 0);
		disable_irq_wake(priv->wol_irq);
			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;
}

Loading