mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 02:01:36 +03:00
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:
committed by
Revanth Kumar Uppala
parent
e9222d366f
commit
e6cde88eb8
@@ -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 = ðer_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 */
|
||||
|
||||
Reference in New Issue
Block a user