Skip to content

Commit bd34cf6

Browse files
committed
Merge branch 'cpsw-phy-handle-fixes'
David Rivshin says: ==================== drivers: net: cpsw: phy-handle fixes This series fixes a number of related issues around using phy-handle properties in cpsw emac nodes. Patch 1 fixes a bug if more than one slave is used, and either slave uses the phy-handle property in the devicetree. Patch 2 fixes a NULL pointer dereference which can occur if a phy-handle property is used and of_phy_connect() return NULL, such as with a bad devicetree. Patch 3 fixes an issue where the phy-mode property would be ignored if a phy-handle property was used. This also fixes a bogus error message that would be emitted. Patch 4 fixes makes the binding documentation more explicit that exactly one PHY property should be used, and also marks phy_id as deprecated. Patch 5 cleans up the fixed-link case to work like the now-fixed phy-handle case. I have tested on the following hardware configurations: - (EVMSK) dual emac, phy_id property in both slaves - (EVMSK) dual emac, phy-handle property in both slaves - (EVMSK) a bad phy-handle property pointing to &mmc1 - (EVMSK) phy_id property with incorrect PHY address - (BeagleBoneBlack) single emac, phy_id property - (custom) single emac, fixed-link subnode Andrew Goodbody reported testing v2 on a board that doesn't use dual_emac mode, but with 2 PHYs using phy-handle properties [1]. Nicolas Chauvet reported testing v2 on an HP t410 (dm8148). Markus Brunner reported testing v1 on the following [2]: - emac0 with phy_id and emac1 with fixed phy - emac0 with phy-handle and emac1 with fixed phy - emac0 with fixed phy and emac1 with fixed phy [1] https://lkml.org/lkml/2016/4/22/537 [2] http://www.spinics.net/lists/netdev/msg357890.html ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents bbdd09e + 06cd6d6 commit bd34cf6

File tree

3 files changed

+40
-34
lines changed

3 files changed

+40
-34
lines changed

Documentation/devicetree/bindings/net/cpsw.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ Required properties:
4545
Optional properties:
4646
- dual_emac_res_vlan : Specifies VID to be used to segregate the ports
4747
- mac-address : See ethernet.txt file in the same directory
48-
- phy_id : Specifies slave phy id
48+
- phy_id : Specifies slave phy id (deprecated, use phy-handle)
4949
- phy-handle : See ethernet.txt file in the same directory
5050

5151
Slave sub-nodes:
5252
- fixed-link : See fixed-link.txt file in the same directory
53-
Either the property phy_id, or the sub-node
54-
fixed-link can be specified
53+
54+
Note: Exactly one of phy_id, phy-handle, or fixed-link must be specified.
5555

5656
Note: "ti,hwmods" field is used to fetch the base address and irq
5757
resources from TI, omap hwmod data base during device registration.

drivers/net/ethernet/ti/cpsw.c

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,6 @@ struct cpsw_priv {
367367
spinlock_t lock;
368368
struct platform_device *pdev;
369369
struct net_device *ndev;
370-
struct device_node *phy_node;
371370
struct napi_struct napi_rx;
372371
struct napi_struct napi_tx;
373372
struct device *dev;
@@ -1148,25 +1147,34 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
11481147
cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
11491148
1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
11501149

1151-
if (priv->phy_node)
1152-
slave->phy = of_phy_connect(priv->ndev, priv->phy_node,
1150+
if (slave->data->phy_node) {
1151+
slave->phy = of_phy_connect(priv->ndev, slave->data->phy_node,
11531152
&cpsw_adjust_link, 0, slave->data->phy_if);
1154-
else
1153+
if (!slave->phy) {
1154+
dev_err(priv->dev, "phy \"%s\" not found on slave %d\n",
1155+
slave->data->phy_node->full_name,
1156+
slave->slave_num);
1157+
return;
1158+
}
1159+
} else {
11551160
slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
11561161
&cpsw_adjust_link, slave->data->phy_if);
1157-
if (IS_ERR(slave->phy)) {
1158-
dev_err(priv->dev, "phy %s not found on slave %d\n",
1159-
slave->data->phy_id, slave->slave_num);
1160-
slave->phy = NULL;
1161-
} else {
1162-
phy_attached_info(slave->phy);
1162+
if (IS_ERR(slave->phy)) {
1163+
dev_err(priv->dev,
1164+
"phy \"%s\" not found on slave %d, err %ld\n",
1165+
slave->data->phy_id, slave->slave_num,
1166+
PTR_ERR(slave->phy));
1167+
slave->phy = NULL;
1168+
return;
1169+
}
1170+
}
11631171

1164-
phy_start(slave->phy);
1172+
phy_attached_info(slave->phy);
11651173

1166-
/* Configure GMII_SEL register */
1167-
cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface,
1168-
slave->slave_num);
1169-
}
1174+
phy_start(slave->phy);
1175+
1176+
/* Configure GMII_SEL register */
1177+
cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface, slave->slave_num);
11701178
}
11711179

11721180
static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
@@ -1940,12 +1948,11 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
19401948
slave->port_vlan = data->dual_emac_res_vlan;
19411949
}
19421950

1943-
static int cpsw_probe_dt(struct cpsw_priv *priv,
1951+
static int cpsw_probe_dt(struct cpsw_platform_data *data,
19441952
struct platform_device *pdev)
19451953
{
19461954
struct device_node *node = pdev->dev.of_node;
19471955
struct device_node *slave_node;
1948-
struct cpsw_platform_data *data = &priv->data;
19491956
int i = 0, ret;
19501957
u32 prop;
19511958

@@ -2033,25 +2040,21 @@ static int cpsw_probe_dt(struct cpsw_priv *priv,
20332040
if (strcmp(slave_node->name, "slave"))
20342041
continue;
20352042

2036-
priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
2043+
slave_data->phy_node = of_parse_phandle(slave_node,
2044+
"phy-handle", 0);
20372045
parp = of_get_property(slave_node, "phy_id", &lenp);
2038-
if (of_phy_is_fixed_link(slave_node)) {
2039-
struct device_node *phy_node;
2040-
struct phy_device *phy_dev;
2041-
2046+
if (slave_data->phy_node) {
2047+
dev_dbg(&pdev->dev,
2048+
"slave[%d] using phy-handle=\"%s\"\n",
2049+
i, slave_data->phy_node->full_name);
2050+
} else if (of_phy_is_fixed_link(slave_node)) {
20422051
/* In the case of a fixed PHY, the DT node associated
20432052
* to the PHY is the Ethernet MAC DT node.
20442053
*/
20452054
ret = of_phy_register_fixed_link(slave_node);
20462055
if (ret)
20472056
return ret;
2048-
phy_node = of_node_get(slave_node);
2049-
phy_dev = of_phy_find_device(phy_node);
2050-
if (!phy_dev)
2051-
return -ENODEV;
2052-
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
2053-
PHY_ID_FMT, phy_dev->mdio.bus->id,
2054-
phy_dev->mdio.addr);
2057+
slave_data->phy_node = of_node_get(slave_node);
20552058
} else if (parp) {
20562059
u32 phyid;
20572060
struct device_node *mdio_node;
@@ -2072,7 +2075,9 @@ static int cpsw_probe_dt(struct cpsw_priv *priv,
20722075
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
20732076
PHY_ID_FMT, mdio->name, phyid);
20742077
} else {
2075-
dev_err(&pdev->dev, "No slave[%d] phy_id or fixed-link property\n", i);
2078+
dev_err(&pdev->dev,
2079+
"No slave[%d] phy_id, phy-handle, or fixed-link property\n",
2080+
i);
20762081
goto no_phy_slave;
20772082
}
20782083
slave_data->phy_if = of_get_phy_mode(slave_node);
@@ -2275,7 +2280,7 @@ static int cpsw_probe(struct platform_device *pdev)
22752280
/* Select default pin state */
22762281
pinctrl_pm_select_default_state(&pdev->dev);
22772282

2278-
if (cpsw_probe_dt(priv, pdev)) {
2283+
if (cpsw_probe_dt(&priv->data, pdev)) {
22792284
dev_err(&pdev->dev, "cpsw: platform data missing\n");
22802285
ret = -ENODEV;
22812286
goto clean_runtime_disable_ret;

drivers/net/ethernet/ti/cpsw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/phy.h>
1919

2020
struct cpsw_slave_data {
21+
struct device_node *phy_node;
2122
char phy_id[MII_BUS_ID_SIZE];
2223
int phy_if;
2324
u8 mac_addr[ETH_ALEN];

0 commit comments

Comments
 (0)