nvethernet: add mutex lock for osi mdio

There is chance to hit race condition when doing mdio read/write from
different application.

This would lead to PHY not work properly intermittently.

Bug 5211090

Change-Id: I62afbc1d206fd4cf02a0b58036e8d38ca84968ac
Signed-off-by: Wayne Wang(SW-TEGRA) <waywang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/3453343
(cherry picked from commit 1442bbd24a8fe0423fc67b5b004b2a07d604c109)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3477850
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
This commit is contained in:
Wayne Wang(SW-TEGRA)
2025-09-17 15:53:48 +08:00
committed by mobile promotions
parent 1d659b240c
commit 2f7421c40b
2 changed files with 22 additions and 6 deletions

View File

@@ -2449,15 +2449,18 @@ static int ether_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
{
struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev);
int ret = 0;
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY write\n", __func__);
return -ENODEV;
}
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_write_phy_reg(pdata->osi_core, (unsigned int)phyaddr, (unsigned int)phyreg, phydata);
mutex_unlock(&pdata->osi_mdio_lock);
return osi_write_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg, phydata);
return ret;
}
/**
@@ -2479,15 +2482,18 @@ static int ether_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
{
struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev);
int ret = 0;
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY read\n", __func__);
return -ENODEV;
}
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_read_phy_reg(pdata->osi_core, (unsigned int)phyaddr, (unsigned int)phyreg);
mutex_unlock(&pdata->osi_mdio_lock);
return osi_read_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg);
return ret;
}
#if defined(NV_MII_BUS_STRUCT_HAS_WRITE_C45) /* Linux v6.3 */
@@ -3798,7 +3804,9 @@ static int ether_handle_priv_rmdio_ioctl(struct ether_priv_data *pdata,
dev_dbg(pdata->dev, "%s: phy_id:%d regadd: %d devaddr:%d\n",
__func__, mii_data->phy_id, prtad, devad);
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_read_phy_reg(pdata->osi_core, prtad, devad);
mutex_unlock(&pdata->osi_mdio_lock);
if (ret < 0) {
dev_err(pdata->dev, "%s: Data read failed\n", __func__);
return -EFAULT;
@@ -3826,6 +3834,7 @@ static int ether_handle_priv_wmdio_ioctl(struct ether_priv_data *pdata,
{
struct mii_ioctl_data *mii_data = if_mii(ifr);
unsigned int prtad, devad;
int ret = 0;
if (mdio_phy_id_is_c45(mii_data->phy_id)) {
prtad = mdio_phy_id_prtad(mii_data->phy_id);
@@ -3839,8 +3848,11 @@ static int ether_handle_priv_wmdio_ioctl(struct ether_priv_data *pdata,
dev_dbg(pdata->dev, "%s: phy_id:%d regadd: %d devaddr:%d val:%d\n",
__func__, mii_data->phy_id, prtad, devad, mii_data->val_in);
return osi_write_phy_reg(pdata->osi_core, prtad, devad,
mii_data->val_in);
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_write_phy_reg(pdata->osi_core, prtad, devad, mii_data->val_in);
mutex_unlock(&pdata->osi_mdio_lock);
return ret;
}
/**
@@ -6548,6 +6560,8 @@ static int ether_probe(struct platform_device *pdev)
osi_core->osd = pdata;
osi_dma->osd = pdata;
mutex_init(&pdata->osi_mdio_lock);
osi_core->num_mtl_queues = num_mtl_queues;
osi_dma->num_dma_chans = num_dma_chans;