lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 1 Dec 2015 02:31:50 +0000
From:	Duan Andy <fugang.duan@...escale.com>
To:	Lothar Waßmann <LW@...O-electronics.de>,
	Andrew Lunn <andrew@...n.ch>,
	"David S. Miller" <davem@...emloft.net>,
	Fabio Estevam <Fabio.Estevam@...escale.com>,
	Greg Ungerer <gerg@...inux.org>,
	Kevin Hao <haokexin@...il.com>,
	Lucas Stach <l.stach@...gutronix.de>,
	Philippe Reynes <tremyfr@...il.com>,
	Richard Cochran <richardcochran@...il.com>,
	Russell King <rmk+kernel@....linux.org.uk>,
	Sascha Hauer <s.hauer@...gutronix.de>,
	"Stefan Agner" <stefan@...er.ch>,
	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	"netdev@...r.kernel.org" <netdev@...r.kernel.org>,
	Jeff Kirsher <jeffrey.t.kirsher@...el.com>,
	"Uwe Kleine-K?nig" <u.kleine-koenig@...gutronix.de>
Subject: RE: [PATCH 3/3] net: fec: Reset ethernet PHY whenever the enet_out
 clock is being enabled

From: Lothar Waßmann <LW@...O-electronics.de> Sent: Monday, November 30, 2015 7:33 PM
> To: Andrew Lunn; David S. Miller; Estevam Fabio-R49496; Greg Ungerer;
> Kevin Hao; Lothar Waßmann; Lucas Stach; Duan Fugang-B38611; Philippe
> Reynes; Richard Cochran; Russell King; Sascha Hauer; Stefan Agner; linux-
> kernel@...r.kernel.org; netdev@...r.kernel.org; Jeff Kirsher; Uwe Kleine-
> König
> Subject: [PATCH 3/3] net: fec: Reset ethernet PHY whenever the enet_out
> clock is being enabled
> 
> If a PHY uses ENET_OUT as reference clock, it may need a RESET to get
> functional after the clock had been disabled.
> 
> Failure to do this results in the link state constantly toggling between
> up and down:
> fec 02188000.ethernet eth0: Link is Up - 100Mbps/Full - flow control
> rx/tx fec 02188000.ethernet eth0: Link is Down fec 02188000.ethernet eth0:
> Link is Up - 100Mbps/Full - flow control rx/tx fec 02188000.ethernet eth0:
> Link is Down [...]
> 
> Signed-off-by: Lothar Waßmann <LW@...O-electronics.de>
> ---
>  drivers/net/ethernet/freescale/fec.h      |  1 +
>  drivers/net/ethernet/freescale/fec_main.c | 46 ++++++++++++++++++++++++-
> ------
>  2 files changed, 37 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/fec.h
> b/drivers/net/ethernet/freescale/fec.h
> index 99d33e2..8ab4f7f 100644
> --- a/drivers/net/ethernet/freescale/fec.h
> +++ b/drivers/net/ethernet/freescale/fec.h
> @@ -519,6 +519,7 @@ struct fec_enet_private {
>  	int	pause_flag;
>  	int	wol_flag;
>  	u32	quirks;
> +	struct gpio_desc *phy_reset;
> 
>  	struct	napi_struct napi;
>  	int	csum_flags;
> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> b/drivers/net/ethernet/freescale/fec_main.c
> index 1a983fc..7ba2bbb 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -66,6 +66,7 @@
> 
>  static void set_multicast_list(struct net_device *ndev);  static void
> fec_enet_itr_coal_init(struct net_device *ndev);
> +static void fec_reset_phy(struct platform_device *pdev);
> 
>  #define DRIVER_NAME	"fec"
> 
> @@ -1861,6 +1862,8 @@ static int fec_enet_clk_enable(struct net_device
> *ndev, bool enable)
>  			ret = clk_prepare_enable(fep->clk_enet_out);
>  			if (ret)
>  				goto failed_clk_enet_out;
> +
> +			fec_reset_phy(fep->pdev);
>  		}
>  		if (fep->clk_ptp) {
>  			mutex_lock(&fep->ptp_clk_mutex);
> @@ -3231,13 +3234,32 @@ static int fec_enet_init(struct net_device
> *ndev)  }
> 
>  #ifdef CONFIG_OF
> -static void fec_reset_phy(struct platform_device *pdev)
> +static struct gpio_desc *fec_get_reset_gpio(struct platform_device
> +*pdev)
>  {
>  	struct gpio_desc *phy_reset;
> -	int msec = 1;
>  	struct device_node *np = pdev->dev.of_node;
> 
>  	if (!np)
> +		return ERR_PTR(-ENODEV);

No need to check device node.

> +
> +	phy_reset = devm_gpiod_get_optional(&pdev->dev, "phy-reset",
> +					    GPIOD_OUT_LOW);
> +	if (IS_ERR(phy_reset))
> +		dev_err(&pdev->dev, "failed to get phy-reset-gpios: %ld\n",
> +			PTR_ERR(phy_reset));
> +	return phy_reset;
> +}
> +
> +static void fec_reset_phy(struct platform_device *pdev) {
> +	struct device_node *np = pdev->dev.of_node;
> +	struct net_device *ndev = platform_get_drvdata(pdev);
> +	struct fec_enet_private *fep = netdev_priv(ndev);
> +	int msec = 1;
> +
> +	if (!fep->phy_reset)
> +		return;
> +	if (!np)
>  		return;

No need to check device node.

> 
>  	of_property_read_u32(np, "phy-reset-duration", &msec); @@ -3245,17
> +3267,16 @@ static void fec_reset_phy(struct platform_device *pdev)
>  	if (msec > 1000)
>  		msec = 1;
> 
> -	phy_reset = devm_gpiod_get_optional(&pdev->dev, "phy-reset",
> -					    GPIOD_OUT_LOW);
> -	if (IS_ERR(phy_reset)) {
> -		dev_err(&pdev->dev, "failed to get phy-reset-gpios: %ld\n",
> -			PTR_ERR(phy_reset));
> -		return;
> -	}
> +	gpiod_set_value_cansleep(fep->phy_reset, 0);
>  	msleep(msec);
> -	gpiod_set_value_cansleep(phy_reset, 1);
> +	gpiod_set_value_cansleep(fep->phy_reset, 1);
>  }
>  #else /* CONFIG_OF */
> +static void fec_get_reset_gpio(struct platform_device *pdev) {
> +	return -EINVAL;
> +}
> +
>  static void fec_reset_phy(struct platform_device *pdev)  {
>  	/*
> @@ -3309,8 +3330,12 @@ fec_probe(struct platform_device *pdev)
>  	struct device_node *np = pdev->dev.of_node, *phy_node;
>  	int num_tx_qs;
>  	int num_rx_qs;
> +	struct gpio_desc *phy_reset;
> 
>  	fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
> +	phy_reset = fec_get_reset_gpio(pdev);
> +	if (IS_ERR(phy_reset) && PTR_ERR(phy_reset) == -EPROBE_DEFER)
> +		return -EPROBE_DEFER;
> 
>  	/* Init network device */
>  	ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private), @@ -
> 3331,6 +3356,7 @@ fec_probe(struct platform_device *pdev)
>  	fep->netdev = ndev;
>  	fep->num_rx_queues = num_rx_qs;
>  	fep->num_tx_queues = num_tx_qs;
> +	fep->phy_reset = phy_reset;
> 
>  #if !defined(CONFIG_M5272)
>  	/* default enable pause frame auto negotiation */
> --
> 2.1.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ