Commit 95dcfdff authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'lan78xx-preparations-for-phylink'

Oleksij Rempel says:

====================
lan78xx: Preparations for PHYlink

This patch set is a third part of the preparatory work for migrating
the lan78xx USB Ethernet driver to the PHYlink framework. During
extensive testing, I observed that resetting the USB adapter can lead to
various read/write errors. While the errors themselves are acceptable,
they generate excessive log messages, resulting in significant log spam.
This set improves error handling to reduce logging noise by addressing
errors directly and returning early when necessary.
====================

Link: https://patch.msgid.link/20241216120941.1690908-1-o.rempel@pengutronix.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 33d06d1d 01e2f4d5
Loading
Loading
Loading
Loading
+40 −33
Original line number Diff line number Diff line
@@ -439,7 +439,7 @@ struct lan78xx_net {
	struct usb_anchor	deferred;

	struct mutex		dev_mutex; /* serialise open/stop wrt suspend/resume */
	struct mutex		phy_mutex; /* for phy access */
	struct mutex		mdiobus_mutex; /* for MDIO bus access */
	unsigned int		pipe_in, pipe_out, pipe_intr;

	unsigned int		bulk_in_delay;
@@ -844,9 +844,7 @@ static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled,
		} while (!stopped && !time_after(jiffies, timeout));
	}

	ret = stopped ? 0 : -ETIME;

	return ret;
	return stopped ? 0 : -ETIMEDOUT;
}

static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 fifo_flush)
@@ -954,7 +952,7 @@ static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)
	return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_);
}

/* Loop until the read is completed with timeout called with phy_mutex held */
/* Loop until the read is completed with timeout called with mdiobus_mutex held */
static int lan78xx_mdiobus_wait_not_busy(struct lan78xx_net *dev)
{
	unsigned long start_time = jiffies;
@@ -1598,7 +1596,7 @@ static int lan78xx_mac_reset(struct lan78xx_net *dev)
	u32 val;
	int ret;

	mutex_lock(&dev->phy_mutex);
	mutex_lock(&dev->mdiobus_mutex);

	/* Resetting the device while there is activity on the MDIO
	 * bus can result in the MAC interface locking up and not
@@ -1606,16 +1604,16 @@ static int lan78xx_mac_reset(struct lan78xx_net *dev)
	 */
	ret = lan78xx_mdiobus_wait_not_busy(dev);
	if (ret < 0)
		goto done;
		goto exit_unlock;

	ret = lan78xx_read_reg(dev, MAC_CR, &val);
	if (ret < 0)
		goto done;
		goto exit_unlock;

	val |= MAC_CR_RST_;
	ret = lan78xx_write_reg(dev, MAC_CR, val);
	if (ret < 0)
		goto done;
		goto exit_unlock;

	/* Wait for the reset to complete before allowing any further
	 * MAC register accesses otherwise the MAC may lock up.
@@ -1623,17 +1621,17 @@ static int lan78xx_mac_reset(struct lan78xx_net *dev)
	do {
		ret = lan78xx_read_reg(dev, MAC_CR, &val);
		if (ret < 0)
			goto done;
			goto exit_unlock;

		if (!(val & MAC_CR_RST_)) {
			ret = 0;
			goto done;
			goto exit_unlock;
		}
	} while (!time_after(jiffies, start_time + HZ));

	ret = -ETIMEDOUT;
done:
	mutex_unlock(&dev->phy_mutex);
exit_unlock:
	mutex_unlock(&dev->mdiobus_mutex);

	return ret;
}
@@ -1859,6 +1857,7 @@ static void lan78xx_get_wol(struct net_device *netdev,

	ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
	if (unlikely(ret < 0)) {
		netdev_warn(dev->net, "failed to get WoL %pe", ERR_PTR(ret));
		wol->supported = 0;
		wol->wolopts = 0;
	} else {
@@ -1890,10 +1889,13 @@ static int lan78xx_set_wol(struct net_device *netdev,

	pdata->wol = wol->wolopts;

	device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
	ret = device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
	if (ret < 0)
		goto exit_pm_put;

	phy_ethtool_set_wol(netdev->phydev, wol);
	ret = phy_ethtool_set_wol(netdev->phydev, wol);

exit_pm_put:
	usb_autopm_put_interface(dev->intf);

	return ret;
@@ -2098,30 +2100,35 @@ static int lan78xx_set_pause(struct net_device *net,

static int lan78xx_get_regs_len(struct net_device *netdev)
{
	if (!netdev->phydev)
		return (sizeof(lan78xx_regs));
	else
		return (sizeof(lan78xx_regs) + PHY_REG_SIZE);
	return sizeof(lan78xx_regs);
}

static void
lan78xx_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
		 void *buf)
{
	u32 *data = buf;
	int i, j;
	struct lan78xx_net *dev = netdev_priv(netdev);
	unsigned int data_count = 0;
	u32 *data = buf;
	int i, ret;

	/* Read Device/MAC registers */
	for (i = 0; i < ARRAY_SIZE(lan78xx_regs); i++)
		lan78xx_read_reg(dev, lan78xx_regs[i], &data[i]);
	for (i = 0; i < ARRAY_SIZE(lan78xx_regs); i++) {
		ret = lan78xx_read_reg(dev, lan78xx_regs[i], &data[i]);
		if (ret < 0) {
			netdev_warn(dev->net,
				    "failed to read register 0x%08x\n",
				    lan78xx_regs[i]);
			goto clean_data;
		}

		data_count++;
	}

	if (!netdev->phydev)
	return;

	/* Read PHY registers */
	for (j = 0; j < 32; i++, j++)
		data[i] = phy_read(netdev->phydev, j);
clean_data:
	memset(data, 0, data_count * sizeof(u32));
}

static const struct ethtool_ops lan78xx_ethtool_ops = {
@@ -2227,7 +2234,7 @@ static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)
	if (ret < 0)
		return ret;

	mutex_lock(&dev->phy_mutex);
	mutex_lock(&dev->mdiobus_mutex);

	/* confirm MII not busy */
	ret = lan78xx_mdiobus_wait_not_busy(dev);
@@ -2251,7 +2258,7 @@ static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)
	ret = (int)(val & 0xFFFF);

done:
	mutex_unlock(&dev->phy_mutex);
	mutex_unlock(&dev->mdiobus_mutex);
	usb_autopm_put_interface(dev->intf);

	return ret;
@@ -2268,7 +2275,7 @@ static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,
	if (ret < 0)
		return ret;

	mutex_lock(&dev->phy_mutex);
	mutex_lock(&dev->mdiobus_mutex);

	/* confirm MII not busy */
	ret = lan78xx_mdiobus_wait_not_busy(dev);
@@ -2291,7 +2298,7 @@ static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,
		goto done;

done:
	mutex_unlock(&dev->phy_mutex);
	mutex_unlock(&dev->mdiobus_mutex);
	usb_autopm_put_interface(dev->intf);
	return ret;
}
@@ -4454,7 +4461,7 @@ static int lan78xx_probe(struct usb_interface *intf,
	skb_queue_head_init(&dev->rxq_done);
	skb_queue_head_init(&dev->txq_pend);
	skb_queue_head_init(&dev->rxq_overflow);
	mutex_init(&dev->phy_mutex);
	mutex_init(&dev->mdiobus_mutex);
	mutex_init(&dev->dev_mutex);

	ret = lan78xx_urb_config_init(dev);