Skip to content

Commit 05925e5

Browse files
Vladimir Zapolskiydavem330
Vladimir Zapolskiy
authored andcommitted
ravb: fix invalid context bug while changing link options by ethtool
The change fixes sleep in atomic context bug, which is encountered every time when link settings are changed by ethtool. Since commit 35b5f6b ("PHYLIB: Locking fixes for PHY I/O potentially sleeping") phy_start_aneg() function utilizes a mutex to serialize changes to phy state, however that helper function is called in atomic context under a grabbed spinlock, because phy_start_aneg() is called by phy_ethtool_ksettings_set() and by replaced phy_ethtool_sset() helpers from phylib. Now duplex mode setting is enforced in ravb_adjust_link() only, also now RX/TX is disabled when link is put down or modifications to E-MAC registers ECMR and GECMR are expected for both cases of checked and ignored link status pin state from E-MAC interrupt handler. Fixes: c156633 ("Renesas Ethernet AVB driver proper") Signed-off-by: Vladimir Zapolskiy <[email protected]> Reviewed-by: Sergei Shtylyov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0973a4d commit 05925e5

File tree

1 file changed

+15
-34
lines changed

1 file changed

+15
-34
lines changed

drivers/net/ethernet/renesas/ravb_main.c

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,13 @@ static void ravb_adjust_link(struct net_device *ndev)
980980
struct ravb_private *priv = netdev_priv(ndev);
981981
struct phy_device *phydev = ndev->phydev;
982982
bool new_state = false;
983+
unsigned long flags;
984+
985+
spin_lock_irqsave(&priv->lock, flags);
986+
987+
/* Disable TX and RX right over here, if E-MAC change is ignored */
988+
if (priv->no_avb_link)
989+
ravb_rcv_snd_disable(ndev);
983990

984991
if (phydev->link) {
985992
if (phydev->duplex != priv->duplex) {
@@ -997,18 +1004,21 @@ static void ravb_adjust_link(struct net_device *ndev)
9971004
ravb_modify(ndev, ECMR, ECMR_TXF, 0);
9981005
new_state = true;
9991006
priv->link = phydev->link;
1000-
if (priv->no_avb_link)
1001-
ravb_rcv_snd_enable(ndev);
10021007
}
10031008
} else if (priv->link) {
10041009
new_state = true;
10051010
priv->link = 0;
10061011
priv->speed = 0;
10071012
priv->duplex = -1;
1008-
if (priv->no_avb_link)
1009-
ravb_rcv_snd_disable(ndev);
10101013
}
10111014

1015+
/* Enable TX and RX right over here, if E-MAC change is ignored */
1016+
if (priv->no_avb_link && phydev->link)
1017+
ravb_rcv_snd_enable(ndev);
1018+
1019+
mmiowb();
1020+
spin_unlock_irqrestore(&priv->lock, flags);
1021+
10121022
if (new_state && netif_msg_link(priv))
10131023
phy_print_status(phydev);
10141024
}
@@ -1115,39 +1125,10 @@ static int ravb_get_link_ksettings(struct net_device *ndev,
11151125
static int ravb_set_link_ksettings(struct net_device *ndev,
11161126
const struct ethtool_link_ksettings *cmd)
11171127
{
1118-
struct ravb_private *priv = netdev_priv(ndev);
1119-
unsigned long flags;
1120-
int error;
1121-
11221128
if (!ndev->phydev)
11231129
return -ENODEV;
11241130

1125-
spin_lock_irqsave(&priv->lock, flags);
1126-
1127-
/* Disable TX and RX */
1128-
ravb_rcv_snd_disable(ndev);
1129-
1130-
error = phy_ethtool_ksettings_set(ndev->phydev, cmd);
1131-
if (error)
1132-
goto error_exit;
1133-
1134-
if (cmd->base.duplex == DUPLEX_FULL)
1135-
priv->duplex = 1;
1136-
else
1137-
priv->duplex = 0;
1138-
1139-
ravb_set_duplex(ndev);
1140-
1141-
error_exit:
1142-
mdelay(1);
1143-
1144-
/* Enable TX and RX */
1145-
ravb_rcv_snd_enable(ndev);
1146-
1147-
mmiowb();
1148-
spin_unlock_irqrestore(&priv->lock, flags);
1149-
1150-
return error;
1131+
return phy_ethtool_ksettings_set(ndev->phydev, cmd);
11511132
}
11521133

11531134
static int ravb_nway_reset(struct net_device *ndev)

0 commit comments

Comments
 (0)