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/+/3479480
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
This commit is contained in:
Wayne Wang(SW-TEGRA)
2025-09-17 15:53:48 +08:00
committed by mobile promotions
parent 4d81ee0f63
commit f0d6883945
2 changed files with 22 additions and 6 deletions

View File

@@ -2963,15 +2963,18 @@ static int ether_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
{ {
struct net_device *ndev = bus->priv; struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev); struct ether_priv_data *pdata = netdev_priv(ndev);
int ret = 0;
if (!pdata->clks_enable) { if (!pdata->clks_enable) {
dev_err(pdata->dev, dev_err(pdata->dev,
"%s:No clks available, skipping PHY write\n", __func__); "%s:No clks available, skipping PHY write\n", __func__);
return -ENODEV; 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, return ret;
(unsigned int)phyreg, phydata);
} }
/** /**
@@ -2993,15 +2996,18 @@ static int ether_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
{ {
struct net_device *ndev = bus->priv; struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev); struct ether_priv_data *pdata = netdev_priv(ndev);
int ret = 0;
if (!pdata->clks_enable) { if (!pdata->clks_enable) {
dev_err(pdata->dev, dev_err(pdata->dev,
"%s:No clks available, skipping PHY read\n", __func__); "%s:No clks available, skipping PHY read\n", __func__);
return -ENODEV; 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, return ret;
(unsigned int)phyreg);
} }
#if defined(NV_MII_BUS_STRUCT_HAS_WRITE_C45) /* Linux v6.3 */ #if defined(NV_MII_BUS_STRUCT_HAS_WRITE_C45) /* Linux v6.3 */
@@ -4395,7 +4401,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", dev_dbg(pdata->dev, "%s: phy_id:%d regadd: %d devaddr:%d\n",
__func__, mii_data->phy_id, prtad, devad); __func__, mii_data->phy_id, prtad, devad);
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_read_phy_reg(pdata->osi_core, prtad, devad); ret = osi_read_phy_reg(pdata->osi_core, prtad, devad);
mutex_unlock(&pdata->osi_mdio_lock);
if (ret < 0) { if (ret < 0) {
dev_err(pdata->dev, "%s: Data read failed\n", __func__); dev_err(pdata->dev, "%s: Data read failed\n", __func__);
return -EFAULT; return -EFAULT;
@@ -4423,6 +4431,7 @@ static int ether_handle_priv_wmdio_ioctl(struct ether_priv_data *pdata,
{ {
struct mii_ioctl_data *mii_data = if_mii(ifr); struct mii_ioctl_data *mii_data = if_mii(ifr);
unsigned int prtad, devad; unsigned int prtad, devad;
int ret = 0;
if (mdio_phy_id_is_c45(mii_data->phy_id)) { if (mdio_phy_id_is_c45(mii_data->phy_id)) {
prtad = mdio_phy_id_prtad(mii_data->phy_id); prtad = mdio_phy_id_prtad(mii_data->phy_id);
@@ -4436,8 +4445,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", 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); __func__, mii_data->phy_id, prtad, devad, mii_data->val_in);
return osi_write_phy_reg(pdata->osi_core, prtad, devad, mutex_lock(&pdata->osi_mdio_lock);
mii_data->val_in); ret = osi_write_phy_reg(pdata->osi_core, prtad, devad, mii_data->val_in);
mutex_unlock(&pdata->osi_mdio_lock);
return ret;
} }
int ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) int ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -7528,6 +7540,8 @@ int ether_probe(struct platform_device *pdev)
osi_core->osd = pdata; osi_core->osd = pdata;
osi_dma->osd = pdata; osi_dma->osd = pdata;
mutex_init(&pdata->osi_mdio_lock);
osi_core->num_mtl_queues = num_mtl_queues; osi_core->num_mtl_queues = num_mtl_queues;
osi_dma->num_dma_chans = num_dma_chans; osi_dma->num_dma_chans = num_dma_chans;

View File

@@ -761,6 +761,8 @@ struct ether_priv_data {
struct osi_mgbe_coe mgbe_coe; struct osi_mgbe_coe mgbe_coe;
/** Flag to retry restart_lane_bringup logic */ /** Flag to retry restart_lane_bringup logic */
u32 force_restart_lane_bringup; u32 force_restart_lane_bringup;
/** MDIO lock for OSI function calls **/
struct mutex osi_mdio_lock;
}; };
/** /**