Commit d733f754 authored by David Rivshin's avatar David Rivshin Committed by David S. Miller

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

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>
parent 552165bc
...@@ -1147,25 +1147,34 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) ...@@ -1147,25 +1147,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;
}
}
phy_attached_info(slave->phy); phy_attached_info(slave->phy);
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment