nvethernet: move mdio_register to open

Issue: mdio bus is registered in probe and before exiting
probe ethernet clocks are disabled to save power. When SC7
is initiated then PHY framework invokes a PHY suspend which
triggers the PHY register write. Since clocks are not enabled
PHY register write is ignored and returned failure which
inturn prevented the entire system to enter into SC7

Fix: Move mdio bus registration to open so that PHY reads/writes
will not be invoked before bringing up the ethernet interface.

Bug 3368603
Change-Id: Idc74be76f47ca1cb607502a4572cb2001d42903a
Signed-off-by: Narayan Reddy <narayanr@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2607300
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-by: Rakesh Goyal <rgoyal@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Narayan Reddy
2021-10-08 00:20:47 +05:30
committed by Revanth Kumar Uppala
parent e9222d366f
commit e6cde88eb8

View File

@@ -2256,6 +2256,117 @@ static int ether_update_mac_addr_filter(struct ether_priv_data *pdata,
return osi_handle_ioctl(osi_core, ioctl_data);
}
/**
* @brief MII call back for MDIO register write.
*
* Algorithm: Invoke OSI layer for PHY register write.
* phy_write() API from Linux PHY subsystem will call this.
*
* @param[in] bus: MDIO bus instances.
* @param[in] phyaddr: PHY address (ID).
* @param[in] phyreg: PHY register to write.
* @param[in] phydata: Data to be written in register.
*
* @note MAC has to be out of reset.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
u16 phydata)
{
struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev);
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY write\n", __func__);
return -ENODEV;
}
return osi_write_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg, phydata);
}
/**
* @brief MII call back for MDIO register read.
*
* Algorithm: Invoke OSI layer for PHY register read.
* phy_read() API from Linux subsystem will call this.
*
* @param[in] bus: MDIO bus instances.
* @param[in] phyaddr: PHY address (ID).
* @param[in] phyreg: PHY register to read.
*
* @note MAC has to be out of reset.
*
* @retval data from PHY register on success
* @retval "nagative value" on failure.
*/
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);
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY read\n", __func__);
return -ENODEV;
}
return osi_read_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg);
}
/**
* @brief MDIO bus registration.
*
* Algorithm: Registers MDIO bus if there is mdio sub DT node
* as part of MAC DT node.
*
* @param[in] pdata: OSD private data.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_mdio_register(struct ether_priv_data *pdata)
{
struct device *dev = pdata->dev;
struct mii_bus *new_bus = NULL;
int ret = 0;
if (pdata->mdio_node == NULL) {
pdata->mii = NULL;
return 0;
}
new_bus = devm_mdiobus_alloc(dev);
if (new_bus == NULL) {
ret = -ENOMEM;
dev_err(dev, "failed to allocate MDIO bus\n");
goto exit;
}
new_bus->name = "nvethernet_mdio_bus";
new_bus->read = ether_mdio_read;
new_bus->write = ether_mdio_write;
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
new_bus->priv = pdata->ndev;
new_bus->parent = dev;
ret = of_mdiobus_register(new_bus, pdata->mdio_node);
if (ret) {
dev_err(dev, "failed to register MDIO bus (%s)\n",
new_bus->name);
goto exit;
}
pdata->mii = new_bus;
exit:
return ret;
}
/**
* @brief Call back to handle bring up of Ethernet interface
*
@@ -2330,6 +2441,12 @@ static int ether_open(struct net_device *dev)
goto err_poll_swr;
}
ret = ether_mdio_register(pdata);
if (ret < 0) {
dev_err(&dev->dev, "failed to register MDIO bus\n");
goto err_mdio_reg;
}
atomic_set(&pdata->padcal_in_progress, OSI_DISABLE);
/* PHY reset and initialization */
ret = ether_phy_init(dev);
@@ -2470,7 +2587,11 @@ err_alloc:
phy_disconnect(pdata->phydev);
}
err_phy_init:
if (pdata->mii != NULL) {
mdiobus_unregister(pdata->mii);
}
err_poll_swr:
err_mdio_reg:
if (pdata->xpcs_rst) {
reset_control_assert(pdata->xpcs_rst);
}
@@ -2719,6 +2840,10 @@ static int ether_close(struct net_device *ndev)
reset_control_assert(pdata->mac_rst);
}
if (pdata->mii != NULL) {
mdiobus_unregister(pdata->mii);
}
/* Disable clock */
ether_disable_clks(pdata);
@@ -4058,117 +4183,6 @@ static int ether_alloc_napi(struct ether_priv_data *pdata)
return 0;
}
/**
* @brief MII call back for MDIO register write.
*
* Algorithm: Invoke OSI layer for PHY register write.
* phy_write() API from Linux PHY subsystem will call this.
*
* @param[in] bus: MDIO bus instances.
* @param[in] phyaddr: PHY address (ID).
* @param[in] phyreg: PHY register to write.
* @param[in] phydata: Data to be written in register.
*
* @note MAC has to be out of reset.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
u16 phydata)
{
struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev);
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY write\n", __func__);
return -ENODEV;
}
return osi_write_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg, phydata);
}
/**
* @brief MII call back for MDIO register read.
*
* Algorithm: Invoke OSI layer for PHY register read.
* phy_read() API from Linux subsystem will call this.
*
* @param[in] bus: MDIO bus instances.
* @param[in] phyaddr: PHY address (ID).
* @param[in] phyreg: PHY register to read.
*
* @note MAC has to be out of reset.
*
* @retval data from PHY register on success
* @retval "nagative value" on failure.
*/
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);
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY read\n", __func__);
return -ENODEV;
}
return osi_read_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg);
}
/**
* @brief MDIO bus registration.
*
* Algorithm: Registers MDIO bus if there is mdio sub DT node
* as part of MAC DT node.
*
* @param[in] pdata: OSD private data.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_mdio_register(struct ether_priv_data *pdata)
{
struct device *dev = pdata->dev;
struct mii_bus *new_bus = NULL;
int ret = 0;
if (pdata->mdio_node == NULL) {
pdata->mii = NULL;
return 0;
}
new_bus = devm_mdiobus_alloc(dev);
if (new_bus == NULL) {
ret = -ENOMEM;
dev_err(dev, "failed to allocate MDIO bus\n");
goto exit;
}
new_bus->name = "nvethernet_mdio_bus";
new_bus->read = ether_mdio_read;
new_bus->write = ether_mdio_write;
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
new_bus->priv = pdata->ndev;
new_bus->parent = dev;
ret = of_mdiobus_register(new_bus, pdata->mdio_node);
if (ret) {
dev_err(dev, "failed to register MDIO bus (%s)\n",
new_bus->name);
goto exit;
}
pdata->mii = new_bus;
exit:
return ret;
}
/**
* @brief ether_set_vm_irq_chan_mask - Set VM DMA channel mask.
*
@@ -6165,19 +6179,13 @@ static int ether_probe(struct platform_device *pdev)
goto err_dma_mask;
}
ret = ether_mdio_register(pdata);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register MDIO bus\n");
goto err_dma_mask;
}
ndev->netdev_ops = &ether_netdev_ops;
ether_set_ethtool_ops(ndev);
ret = ether_alloc_napi(pdata);
if (ret < 0) {
dev_err(&pdev->dev, "failed to allocate NAPI\n");
goto err_napi;
goto err_dma_mask;
}
/* Setup the tx_usecs timer */
@@ -6267,8 +6275,6 @@ err_netdev:
#ifdef MACSEC_SUPPORT
err_macsec:
#endif /* MACSEC_SUPPORT */
err_napi:
mdiobus_unregister(pdata->mii);
err_dma_mask:
ether_disable_clks(pdata);
ether_put_clks(pdata);
@@ -6308,10 +6314,6 @@ static int ether_remove(struct platform_device *pdev)
/* remove nvethernet sysfs group under /sys/devices/<ether_device>/ */
ether_sysfs_unregister(pdata);
if (pdata->mii != NULL) {
mdiobus_unregister(pdata->mii);
}
ether_put_clks(pdata);
/* Assert MAC RST gpio */