From b8fca780227a78aa55fe125847eb2fb3a1d8e33a Mon Sep 17 00:00:00 2001 From: Jeremy Alves Date: Thu, 19 Oct 2023 19:06:06 -0700 Subject: [PATCH] Lan743/6.1 include nvidia specific changes Updating Lan7431 nvidia-oot driver for kernel 6.1 to include NV specific changes Include changes from: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2924162 https://git-master.nvidia.com/r/c/linux-nv-oot/+/2932422 for userland phy and SC7 support Bug 4330040 Bug 4270736 Change-Id: I20e052f24757d0ac17501906b267bc746c3d43d2 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3000975 GVS: Gerrit_Virtual_Submit Tested-by: Jeremy Alves Reviewed-by: Jeremy Alves Reviewed-by: Laxman Dewangan --- .../net/ethernet/microchip/6.1/lan743x_main.c | 189 +++++++++++++++++- .../net/ethernet/microchip/6.1/lan743x_main.h | 6 + 2 files changed, 188 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/microchip/6.1/lan743x_main.c b/drivers/net/ethernet/microchip/6.1/lan743x_main.c index 50eeecba..d246f30a 100644 --- a/drivers/net/ethernet/microchip/6.1/lan743x_main.c +++ b/drivers/net/ethernet/microchip/6.1/lan743x_main.c @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* Copyright (C) 2018 Microchip Technology Inc. */ +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ #include #include @@ -1488,11 +1491,17 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter) struct net_device *netdev = adapter->netdev; struct lan743x_phy *phy = &adapter->phy; struct phy_device *phydev; + struct device_node *phynode; + int ret = -EIO; - /* try devicetree phy, or fixed link */ - phydev = of_phy_get_and_connect(netdev, adapter->pdev->dev.of_node, - lan743x_phy_link_status_change); + phynode = of_node_get(adapter->pdev->dev.of_node); + + if (phynode) { + phydev = of_phy_connect(netdev, phynode, + lan743x_phy_link_status_change, 0, + adapter->phy_mode); + } if (!phydev) { /* try internal phy */ @@ -1512,6 +1521,10 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter) goto return_error; } + /*phydev is assigned by now*/ + /*Skip the device resume via mdio bus */ + phydev->mac_managed_pm = true; + /* MAC doesn't support 1000T Half */ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); @@ -1529,6 +1542,45 @@ return_error: return ret; } +static int lan743x_phy_dt_init(struct lan743x_adapter *adapter, + struct pci_dev *pdev) +{ + struct lan743x_phy *phy = &adapter->phy; + struct device_node *phynode; + struct net_device *netdev; + int ret = -EIO; + + netdev = adapter->netdev; + phynode = of_node_get(pdev->dev.of_node); + + if (phynode) { + /* try devicetree phy, or fixed link */ + of_get_phy_mode(phynode, &adapter->phy_mode); + + if (of_phy_is_fixed_link(phynode)) { + ret = of_phy_register_fixed_link(phynode); + phy->fixed = true; + if (ret) { + netdev_err(netdev, + "cannot register fixed PHY\n"); + of_node_put(phynode); + goto return_error; + } + ret = of_property_read_u32(phynode, "nvidia,mdio_addr", + &phy->mdio_addr); + if (ret) { + netdev_warn(netdev, + "Unable to read mdio address\n"); + } + } + of_node_put(phynode); + } + + return 0; +return_error: + return ret; +} + static void lan743x_rfe_open(struct lan743x_adapter *adapter) { lan743x_csr_write(adapter, RFE_RSS_CFG, @@ -3083,14 +3135,133 @@ static netdev_tx_t lan743x_netdev_xmit_frame(struct sk_buff *skb, return lan743x_tx_xmit_frame(&adapter->tx[ch], skb); } +/** + * @brief Function to handle MDIO IOCTL in phyless move + * + * 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 lan7431_handle_priv_rmdio_ioctl(struct lan743x_adapter *adapter, + struct ifreq *ifr) +{ + 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); + 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; + } + + netif_dbg(adapter, drv, adapter->netdev, "%s: phy_id:%d regadd: %d devaddr:%d\n", + __func__, mii_data->phy_id, prtad, devad); + ret = lan743x_mdiobus_read(adapter->mdiobus, prtad, devad); + if (ret < 0) { + netif_err(adapter, drv, adapter->netdev, "%s: Data read failed\n", __func__); + return -EFAULT; + } + + mii_data->val_out = ret; + return 0; +} + +/** + * @brief Function to handle MDIO IOCTL in phyless move + * + * 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 lan7431_handle_priv_wmdio_ioctl(struct lan743x_adapter *adapter, + struct ifreq *ifr) +{ + struct mii_ioctl_data *mii_data = if_mii(ifr); + unsigned int prtad, devad; + + 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; + } + netif_dbg(adapter, drv, adapter->netdev, "%s: phy_id:%d regadd: %d devaddr:%d val:%04x\n", + __func__, mii_data->phy_id, prtad, devad, mii_data->val_in); + return lan743x_mdiobus_write(adapter->mdiobus, prtad, devad, mii_data->val_in); +} + static int lan743x_netdev_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { - if (!netif_running(netdev)) + int ret = -EINVAL; + struct lan743x_adapter *adapter = NULL; + + if (!netdev || !ifr) { + netif_err(adapter, drv, adapter->netdev, "%s: Invalid arg\n", __func__); return -EINVAL; - if (cmd == SIOCSHWTSTAMP) - return lan743x_ptp_ioctl(netdev, ifr, cmd); - return phy_mii_ioctl(netdev->phydev, ifr, cmd); + } + adapter = netdev_priv(netdev); + if (!adapter) { + netif_err(adapter, drv, adapter->netdev, "%s: bad priv\n", __func__); + return -EINVAL; + } + + if (netif_running(netdev)) { + switch (cmd) { + case SIOCSHWTSTAMP: + ret = lan743x_ptp_ioctl(netdev, ifr, cmd); + break; + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + if (!netdev->phydev) { + ret = -EINVAL; + break; + } + if (adapter->phy.fixed) { + if (cmd == SIOCGMIIPHY) { + struct mii_ioctl_data *mii_data = if_mii(ifr); + + mii_data->phy_id = adapter->phy.mdio_addr; + ret = 0; + } else if (cmd == SIOCGMIIREG) { + ret = lan7431_handle_priv_rmdio_ioctl(adapter, ifr); + } else if (cmd == SIOCSMIIREG) { + ret = lan7431_handle_priv_wmdio_ioctl(adapter, ifr); + } else { + netif_err(adapter, drv, adapter->netdev, + "%s: impossible case\n", __func__); + } + } else { + ret = phy_mii_ioctl(netdev->phydev, ifr, cmd); + } + break; + default: + ret = (!netdev->phydev) ? -EINVAL : phy_mii_ioctl(netdev->phydev, ifr, cmd); + break; + } + } else { + netif_err(adapter, drv, adapter->netdev, "%s: Interface not up\n", __func__); + ret = -EINVAL; + } + return ret; } static void lan743x_netdev_set_multicast(struct net_device *netdev) @@ -3374,6 +3545,10 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev, of_get_mac_address(pdev->dev.of_node, adapter->mac_address); + ret = lan743x_phy_dt_init(adapter, pdev); + if (ret) + goto return_error; + ret = lan743x_pci_init(adapter, pdev); if (ret) goto return_error; diff --git a/drivers/net/ethernet/microchip/6.1/lan743x_main.h b/drivers/net/ethernet/microchip/6.1/lan743x_main.h index 67877d3b..e08b1570 100644 --- a/drivers/net/ethernet/microchip/6.1/lan743x_main.h +++ b/drivers/net/ethernet/microchip/6.1/lan743x_main.h @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* Copyright (C) 2018 Microchip Technology Inc. */ +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ #ifndef _LAN743X_H #define _LAN743X_H @@ -914,6 +917,8 @@ struct lan743x_intr { struct lan743x_phy { bool fc_autoneg; u8 fc_request_control; + bool fixed; + u32 mdio_addr; }; /* TX */ @@ -1009,6 +1014,7 @@ enum lan743x_sgmii_lsd { struct lan743x_adapter { struct net_device *netdev; struct mii_bus *mdiobus; + phy_interface_t phy_mode; int msg_enable; #ifdef CONFIG_PM u32 wolopts;