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

Commit 30eee1c6 authored by David Rivshin's avatar David Rivshin Committed by Greg Kroah-Hartman
Browse files

drivers: net: cpsw: fix segfault in case of bad phy-handle



commit d733f7542ad47cf73e033c90cf55158587e1d060 upstream.

If an emac node has a phy-handle property that points to something
which is not a phy, then a segmentation fault will occur when the
interface is brought up. This is because while phy_connect() will
return ERR_PTR() on failure, of_phy_connect() will return NULL.
The common error check uses IS_ERR(), and so missed when
of_phy_connect() fails. The NULL pointer is then dereferenced.

Also, the common error message referenced slave->data->phy_id,
which would be empty in the case of phy-handle. Instead, use the
name of the device_node as a useful identifier. And in the phy_id
case add the error code for completeness.

Fixes: 9e42f715 ("drivers: net: cpsw: add phy-handle parsing")
Signed-off-by: default avatarDavid Rivshin <drivshin@allworx.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
[SZ Lin (林上智): Tweak the patch to use original print function of dev_info()]
Signed-off-by: default avatarSZ Lin (林上智) <sz.lin@moxa.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 24328b80
Loading
Loading
Loading
Loading
+23 −14
Original line number Original line Diff line number Diff line
@@ -1164,25 +1164,34 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);


	if (slave->data->phy_node)
	if (slave->data->phy_node) {
		slave->phy = of_phy_connect(priv->ndev, slave->data->phy_node,
		slave->phy = of_phy_connect(priv->ndev, slave->data->phy_node,
				 &cpsw_adjust_link, 0, slave->data->phy_if);
				 &cpsw_adjust_link, 0, slave->data->phy_if);
	else
		if (!slave->phy) {
			dev_err(priv->dev, "phy \"%s\" not found on slave %d\n",
				slave->data->phy_node->full_name,
				slave->slave_num);
			return;
		}
	} else {
		slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
		slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
				 &cpsw_adjust_link, slave->data->phy_if);
				 &cpsw_adjust_link, slave->data->phy_if);
		if (IS_ERR(slave->phy)) {
		if (IS_ERR(slave->phy)) {
		dev_err(priv->dev, "phy %s not found on slave %d\n",
			dev_err(priv->dev,
			slave->data->phy_id, slave->slave_num);
				"phy \"%s\" not found on slave %d, err %ld\n",
				slave->data->phy_id, slave->slave_num,
				PTR_ERR(slave->phy));
			slave->phy = NULL;
			slave->phy = NULL;
	} else {
			return;
		dev_info(priv->dev, "phy found : id is : 0x%x\n",
		}
			 slave->phy->phy_id);
	}

	dev_info(priv->dev, "phy found : id is : 0x%x\n", slave->phy->phy_id);

	phy_start(slave->phy);
	phy_start(slave->phy);


	/* Configure GMII_SEL register */
	/* Configure GMII_SEL register */
		cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface,
	cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface, slave->slave_num);
			     slave->slave_num);
	}
}
}


static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)