nvethernet: add PHY read/write support

Add a private ioctl for phy register read
and write. This support is needed for accessing
the PHY registers from user space when fixed link
is enabled in SW even though PHY is directly connected
to MAC.

Bug 200733774

Change-Id: Ifd9b5dc7764363d897605c2370da419a863ddea4
Signed-off-by: Narayan Reddy <narayanr@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2554892
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Narayan Reddy
2021-07-07 01:17:19 +05:30
committed by Revanth Kumar Uppala
parent 3f0e18c74d
commit 56063f5983
2 changed files with 109 additions and 0 deletions

View File

@@ -3386,6 +3386,105 @@ void ether_set_rx_mode(struct net_device *dev)
schedule_work(&pdata->set_rx_mode_work);
}
/**
* @brief Function to handle PHY read private IOCTL
*
* Algorithm: This function is used to write the data
* into the specified register.
*
* @param [in] pdata: Pointer to private data structure.
* @param [in] ifr: Interface request structure used for socket ioctl
*
* @retval 0 on success.
* @retval "negative value" on failure.
*/
static int ether_handle_priv_rmdio_ioctl(struct ether_priv_data *pdata,
struct ifreq *ifr)
{
#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 9, 0))
struct mii_ioctl_data *mii_data = if_mii(ifr);
unsigned int prtad, devad;
int ret = 0;
if (!ifr->ifr_data) {
dev_err(pdata->dev, "%s: Invalid data for priv ioctl\n",
__func__);
return -EFAULT;
}
if (mdio_phy_id_is_c45(mii_data->phy_id)) {
prtad = mdio_phy_id_prtad(mii_data->phy_id);
devad = mdio_phy_id_devad(mii_data->phy_id);
devad = mdiobus_c45_addr(devad, mii_data->reg_num);
} else {
prtad = mii_data->phy_id;
devad = mii_data->reg_num;
}
dev_dbg(pdata->dev, "%s: phy_id:%d regadd: %d devaddr:%d\n",
__func__, mii_data->phy_id, prtad, devad);
ret = osi_read_phy_reg(pdata->osi_core, prtad, devad);
if (ret < 0) {
dev_err(pdata->dev, "%s: Data read failed\n", __func__);
return -EFAULT;
}
mii_data->val_out = ret;
return 0;
#else
dev_err(pdata->dev, "Not supported for kernel versions less than 5.10");
return -ENOTSUPP;
#endif
}
/**
* @brief Function to handle PHY write private IOCTL
*
* Algorithm: This function is used to write the data
* into the specified register.
*
* @param [in] pdata: Pointer to private data structure.
* @param [in] ifr: Interface request structure used for socket ioctl
*
* @retval 0 on success.
* @retval "negative value" on failure.
*/
static int ether_handle_priv_wmdio_ioctl(struct ether_priv_data *pdata,
struct ifreq *ifr)
{
#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 9, 0))
struct mii_ioctl_data *mii_data = if_mii(ifr);
unsigned int prtad, devad;
if (!ifr->ifr_data) {
dev_err(pdata->dev, "%s: Invalid data for priv ioctl\n",
__func__);
return -EFAULT;
}
if (mdio_phy_id_is_c45(mii_data->phy_id)) {
prtad = mdio_phy_id_prtad(mii_data->phy_id);
devad = mdio_phy_id_devad(mii_data->phy_id);
devad = mdiobus_c45_addr(devad, mii_data->reg_num);
} else {
prtad = mii_data->phy_id;
devad = mii_data->reg_num;
}
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);
#else
dev_err(pdata->dev, "Not supported for kernel versions less than 5.10");
return -ENOTSUPP;
#endif
}
/**
* @brief Network stack IOCTL hook to driver
*
@@ -3433,6 +3532,14 @@ static int ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ret = ether_handle_priv_ioctl(dev, rq);
break;
case ETHER_PRV_RMDIO_IOCTL:
ret = ether_handle_priv_rmdio_ioctl(pdata, rq);
break;
case ETHER_PRV_WMDIO_IOCTL:
ret = ether_handle_priv_wmdio_ioctl(pdata, rq);
break;
case ETHER_PRV_TS_IOCTL:
ret = ether_handle_priv_ts_ioctl(pdata, rq);
break;