18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/**************************************************************************** 38c2ecf20Sopenharmony_ci * Driver for Solarflare network controllers and boards 48c2ecf20Sopenharmony_ci * Copyright 2006-2011 Solarflare Communications Inc. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * Useful functions for working with MDIO clause 45 PHYs 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/types.h> 108c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include "net_driver.h" 138c2ecf20Sopenharmony_ci#include "mdio_10g.h" 148c2ecf20Sopenharmony_ci#include "workarounds.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciunsigned ef4_mdio_id_oui(u32 id) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci unsigned oui = 0; 198c2ecf20Sopenharmony_ci int i; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci /* The bits of the OUI are designated a..x, with a=0 and b variable. 228c2ecf20Sopenharmony_ci * In the id register c is the MSB but the OUI is conventionally 238c2ecf20Sopenharmony_ci * written as bytes h..a, p..i, x..q. Reorder the bits accordingly. */ 248c2ecf20Sopenharmony_ci for (i = 0; i < 22; ++i) 258c2ecf20Sopenharmony_ci if (id & (1 << (i + 10))) 268c2ecf20Sopenharmony_ci oui |= 1 << (i ^ 7); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci return oui; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciint ef4_mdio_reset_mmd(struct ef4_nic *port, int mmd, 328c2ecf20Sopenharmony_ci int spins, int spintime) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci u32 ctrl; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* Catch callers passing values in the wrong units (or just silly) */ 378c2ecf20Sopenharmony_ci EF4_BUG_ON_PARANOID(spins * spintime >= 5000); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci ef4_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET); 408c2ecf20Sopenharmony_ci /* Wait for the reset bit to clear. */ 418c2ecf20Sopenharmony_ci do { 428c2ecf20Sopenharmony_ci msleep(spintime); 438c2ecf20Sopenharmony_ci ctrl = ef4_mdio_read(port, mmd, MDIO_CTRL1); 448c2ecf20Sopenharmony_ci spins--; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci } while (spins && (ctrl & MDIO_CTRL1_RESET)); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci return spins ? spins : -ETIMEDOUT; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int ef4_mdio_check_mmd(struct ef4_nic *efx, int mmd) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci int status; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (mmd != MDIO_MMD_AN) { 568c2ecf20Sopenharmony_ci /* Read MMD STATUS2 to check it is responding. */ 578c2ecf20Sopenharmony_ci status = ef4_mdio_read(efx, mmd, MDIO_STAT2); 588c2ecf20Sopenharmony_ci if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) { 598c2ecf20Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 608c2ecf20Sopenharmony_ci "PHY MMD %d not responding.\n", mmd); 618c2ecf20Sopenharmony_ci return -EIO; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* This ought to be ridiculous overkill. We expect it to fail rarely */ 698c2ecf20Sopenharmony_ci#define MDIO45_RESET_TIME 1000 /* ms */ 708c2ecf20Sopenharmony_ci#define MDIO45_RESET_ITERS 100 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ciint ef4_mdio_wait_reset_mmds(struct ef4_nic *efx, unsigned int mmd_mask) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; 758c2ecf20Sopenharmony_ci int tries = MDIO45_RESET_ITERS; 768c2ecf20Sopenharmony_ci int rc = 0; 778c2ecf20Sopenharmony_ci int in_reset; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci while (tries) { 808c2ecf20Sopenharmony_ci int mask = mmd_mask; 818c2ecf20Sopenharmony_ci int mmd = 0; 828c2ecf20Sopenharmony_ci int stat; 838c2ecf20Sopenharmony_ci in_reset = 0; 848c2ecf20Sopenharmony_ci while (mask) { 858c2ecf20Sopenharmony_ci if (mask & 1) { 868c2ecf20Sopenharmony_ci stat = ef4_mdio_read(efx, mmd, MDIO_CTRL1); 878c2ecf20Sopenharmony_ci if (stat < 0) { 888c2ecf20Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 898c2ecf20Sopenharmony_ci "failed to read status of" 908c2ecf20Sopenharmony_ci " MMD %d\n", mmd); 918c2ecf20Sopenharmony_ci return -EIO; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci if (stat & MDIO_CTRL1_RESET) 948c2ecf20Sopenharmony_ci in_reset |= (1 << mmd); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci mask = mask >> 1; 978c2ecf20Sopenharmony_ci mmd++; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci if (!in_reset) 1008c2ecf20Sopenharmony_ci break; 1018c2ecf20Sopenharmony_ci tries--; 1028c2ecf20Sopenharmony_ci msleep(spintime); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci if (in_reset != 0) { 1058c2ecf20Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 1068c2ecf20Sopenharmony_ci "not all MMDs came out of reset in time." 1078c2ecf20Sopenharmony_ci " MMDs still in reset: %x\n", in_reset); 1088c2ecf20Sopenharmony_ci rc = -ETIMEDOUT; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci return rc; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ciint ef4_mdio_check_mmds(struct ef4_nic *efx, unsigned int mmd_mask) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci int mmd = 0, probe_mmd, devs1, devs2; 1168c2ecf20Sopenharmony_ci u32 devices; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Historically we have probed the PHYXS to find out what devices are 1198c2ecf20Sopenharmony_ci * present,but that doesn't work so well if the PHYXS isn't expected 1208c2ecf20Sopenharmony_ci * to exist, if so just find the first item in the list supplied. */ 1218c2ecf20Sopenharmony_ci probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS : 1228c2ecf20Sopenharmony_ci __ffs(mmd_mask); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* Check all the expected MMDs are present */ 1258c2ecf20Sopenharmony_ci devs1 = ef4_mdio_read(efx, probe_mmd, MDIO_DEVS1); 1268c2ecf20Sopenharmony_ci devs2 = ef4_mdio_read(efx, probe_mmd, MDIO_DEVS2); 1278c2ecf20Sopenharmony_ci if (devs1 < 0 || devs2 < 0) { 1288c2ecf20Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 1298c2ecf20Sopenharmony_ci "failed to read devices present\n"); 1308c2ecf20Sopenharmony_ci return -EIO; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci devices = devs1 | (devs2 << 16); 1338c2ecf20Sopenharmony_ci if ((devices & mmd_mask) != mmd_mask) { 1348c2ecf20Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 1358c2ecf20Sopenharmony_ci "required MMDs not present: got %x, wanted %x\n", 1368c2ecf20Sopenharmony_ci devices, mmd_mask); 1378c2ecf20Sopenharmony_ci return -ENODEV; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci netif_vdbg(efx, hw, efx->net_dev, "Devices present: %x\n", devices); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Check all required MMDs are responding and happy. */ 1428c2ecf20Sopenharmony_ci while (mmd_mask) { 1438c2ecf20Sopenharmony_ci if ((mmd_mask & 1) && ef4_mdio_check_mmd(efx, mmd)) 1448c2ecf20Sopenharmony_ci return -EIO; 1458c2ecf20Sopenharmony_ci mmd_mask = mmd_mask >> 1; 1468c2ecf20Sopenharmony_ci mmd++; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return 0; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cibool ef4_mdio_links_ok(struct ef4_nic *efx, unsigned int mmd_mask) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci /* If the port is in loopback, then we should only consider a subset 1558c2ecf20Sopenharmony_ci * of mmd's */ 1568c2ecf20Sopenharmony_ci if (LOOPBACK_INTERNAL(efx)) 1578c2ecf20Sopenharmony_ci return true; 1588c2ecf20Sopenharmony_ci else if (LOOPBACK_MASK(efx) & LOOPBACKS_WS) 1598c2ecf20Sopenharmony_ci return false; 1608c2ecf20Sopenharmony_ci else if (ef4_phy_mode_disabled(efx->phy_mode)) 1618c2ecf20Sopenharmony_ci return false; 1628c2ecf20Sopenharmony_ci else if (efx->loopback_mode == LOOPBACK_PHYXS) 1638c2ecf20Sopenharmony_ci mmd_mask &= ~(MDIO_DEVS_PHYXS | 1648c2ecf20Sopenharmony_ci MDIO_DEVS_PCS | 1658c2ecf20Sopenharmony_ci MDIO_DEVS_PMAPMD | 1668c2ecf20Sopenharmony_ci MDIO_DEVS_AN); 1678c2ecf20Sopenharmony_ci else if (efx->loopback_mode == LOOPBACK_PCS) 1688c2ecf20Sopenharmony_ci mmd_mask &= ~(MDIO_DEVS_PCS | 1698c2ecf20Sopenharmony_ci MDIO_DEVS_PMAPMD | 1708c2ecf20Sopenharmony_ci MDIO_DEVS_AN); 1718c2ecf20Sopenharmony_ci else if (efx->loopback_mode == LOOPBACK_PMAPMD) 1728c2ecf20Sopenharmony_ci mmd_mask &= ~(MDIO_DEVS_PMAPMD | 1738c2ecf20Sopenharmony_ci MDIO_DEVS_AN); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return mdio45_links_ok(&efx->mdio, mmd_mask); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_civoid ef4_mdio_transmit_disable(struct ef4_nic *efx) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, 1818c2ecf20Sopenharmony_ci MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL, 1828c2ecf20Sopenharmony_ci efx->phy_mode & PHY_MODE_TX_DISABLED); 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_civoid ef4_mdio_phy_reconfigure(struct ef4_nic *efx) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, 1888c2ecf20Sopenharmony_ci MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK, 1898c2ecf20Sopenharmony_ci efx->loopback_mode == LOOPBACK_PMAPMD); 1908c2ecf20Sopenharmony_ci ef4_mdio_set_flag(efx, MDIO_MMD_PCS, 1918c2ecf20Sopenharmony_ci MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK, 1928c2ecf20Sopenharmony_ci efx->loopback_mode == LOOPBACK_PCS); 1938c2ecf20Sopenharmony_ci ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, 1948c2ecf20Sopenharmony_ci MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK, 1958c2ecf20Sopenharmony_ci efx->loopback_mode == LOOPBACK_PHYXS_WS); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic void ef4_mdio_set_mmd_lpower(struct ef4_nic *efx, 1998c2ecf20Sopenharmony_ci int lpower, int mmd) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci int stat = ef4_mdio_read(efx, mmd, MDIO_STAT1); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci netif_vdbg(efx, drv, efx->net_dev, "Setting low power mode for MMD %d to %d\n", 2048c2ecf20Sopenharmony_ci mmd, lpower); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (stat & MDIO_STAT1_LPOWERABLE) { 2078c2ecf20Sopenharmony_ci ef4_mdio_set_flag(efx, mmd, MDIO_CTRL1, 2088c2ecf20Sopenharmony_ci MDIO_CTRL1_LPOWER, lpower); 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_civoid ef4_mdio_set_mmds_lpower(struct ef4_nic *efx, 2138c2ecf20Sopenharmony_ci int low_power, unsigned int mmd_mask) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci int mmd = 0; 2168c2ecf20Sopenharmony_ci mmd_mask &= ~MDIO_DEVS_AN; 2178c2ecf20Sopenharmony_ci while (mmd_mask) { 2188c2ecf20Sopenharmony_ci if (mmd_mask & 1) 2198c2ecf20Sopenharmony_ci ef4_mdio_set_mmd_lpower(efx, low_power, mmd); 2208c2ecf20Sopenharmony_ci mmd_mask = (mmd_mask >> 1); 2218c2ecf20Sopenharmony_ci mmd++; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/** 2268c2ecf20Sopenharmony_ci * ef4_mdio_set_link_ksettings - Set (some of) the PHY settings over MDIO. 2278c2ecf20Sopenharmony_ci * @efx: Efx NIC 2288c2ecf20Sopenharmony_ci * @cmd: New settings 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ciint ef4_mdio_set_link_ksettings(struct ef4_nic *efx, 2318c2ecf20Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci struct ethtool_link_ksettings prev = { 2348c2ecf20Sopenharmony_ci .base.cmd = ETHTOOL_GLINKSETTINGS 2358c2ecf20Sopenharmony_ci }; 2368c2ecf20Sopenharmony_ci u32 prev_advertising, advertising; 2378c2ecf20Sopenharmony_ci u32 prev_supported; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci efx->phy_op->get_link_ksettings(efx, &prev); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci ethtool_convert_link_mode_to_legacy_u32(&advertising, 2428c2ecf20Sopenharmony_ci cmd->link_modes.advertising); 2438c2ecf20Sopenharmony_ci ethtool_convert_link_mode_to_legacy_u32(&prev_advertising, 2448c2ecf20Sopenharmony_ci prev.link_modes.advertising); 2458c2ecf20Sopenharmony_ci ethtool_convert_link_mode_to_legacy_u32(&prev_supported, 2468c2ecf20Sopenharmony_ci prev.link_modes.supported); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (advertising == prev_advertising && 2498c2ecf20Sopenharmony_ci cmd->base.speed == prev.base.speed && 2508c2ecf20Sopenharmony_ci cmd->base.duplex == prev.base.duplex && 2518c2ecf20Sopenharmony_ci cmd->base.port == prev.base.port && 2528c2ecf20Sopenharmony_ci cmd->base.autoneg == prev.base.autoneg) 2538c2ecf20Sopenharmony_ci return 0; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* We can only change these settings for -T PHYs */ 2568c2ecf20Sopenharmony_ci if (prev.base.port != PORT_TP || cmd->base.port != PORT_TP) 2578c2ecf20Sopenharmony_ci return -EINVAL; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* Check that PHY supports these settings */ 2608c2ecf20Sopenharmony_ci if (!cmd->base.autoneg || 2618c2ecf20Sopenharmony_ci (advertising | SUPPORTED_Autoneg) & ~prev_supported) 2628c2ecf20Sopenharmony_ci return -EINVAL; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci ef4_link_set_advertising(efx, advertising | ADVERTISED_Autoneg); 2658c2ecf20Sopenharmony_ci ef4_mdio_an_reconfigure(efx); 2668c2ecf20Sopenharmony_ci return 0; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/** 2708c2ecf20Sopenharmony_ci * ef4_mdio_an_reconfigure - Push advertising flags and restart autonegotiation 2718c2ecf20Sopenharmony_ci * @efx: Efx NIC 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_civoid ef4_mdio_an_reconfigure(struct ef4_nic *efx) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci int reg; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN)); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Set up the base page */ 2808c2ecf20Sopenharmony_ci reg = ADVERTISE_CSMA | ADVERTISE_RESV; 2818c2ecf20Sopenharmony_ci if (efx->link_advertising & ADVERTISED_Pause) 2828c2ecf20Sopenharmony_ci reg |= ADVERTISE_PAUSE_CAP; 2838c2ecf20Sopenharmony_ci if (efx->link_advertising & ADVERTISED_Asym_Pause) 2848c2ecf20Sopenharmony_ci reg |= ADVERTISE_PAUSE_ASYM; 2858c2ecf20Sopenharmony_ci ef4_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* Set up the (extended) next page */ 2888c2ecf20Sopenharmony_ci efx->phy_op->set_npage_adv(efx, efx->link_advertising); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Enable and restart AN */ 2918c2ecf20Sopenharmony_ci reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); 2928c2ecf20Sopenharmony_ci reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP; 2938c2ecf20Sopenharmony_ci ef4_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ciu8 ef4_mdio_get_pause(struct ef4_nic *efx) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci BUILD_BUG_ON(EF4_FC_AUTO & (EF4_FC_RX | EF4_FC_TX)); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (!(efx->wanted_fc & EF4_FC_AUTO)) 3018c2ecf20Sopenharmony_ci return efx->wanted_fc; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN)); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci return mii_resolve_flowctrl_fdx( 3068c2ecf20Sopenharmony_ci mii_advertise_flowctrl(efx->wanted_fc), 3078c2ecf20Sopenharmony_ci ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA)); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ciint ef4_mdio_test_alive(struct ef4_nic *efx) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci int rc; 3138c2ecf20Sopenharmony_ci int devad = __ffs(efx->mdio.mmds); 3148c2ecf20Sopenharmony_ci u16 physid1, physid2; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci mutex_lock(&efx->mac_lock); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci physid1 = ef4_mdio_read(efx, devad, MDIO_DEVID1); 3198c2ecf20Sopenharmony_ci physid2 = ef4_mdio_read(efx, devad, MDIO_DEVID2); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if ((physid1 == 0x0000) || (physid1 == 0xffff) || 3228c2ecf20Sopenharmony_ci (physid2 == 0x0000) || (physid2 == 0xffff)) { 3238c2ecf20Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 3248c2ecf20Sopenharmony_ci "no MDIO PHY present with ID %d\n", efx->mdio.prtad); 3258c2ecf20Sopenharmony_ci rc = -EINVAL; 3268c2ecf20Sopenharmony_ci } else { 3278c2ecf20Sopenharmony_ci rc = ef4_mdio_check_mmds(efx, efx->mdio.mmds); 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci mutex_unlock(&efx->mac_lock); 3318c2ecf20Sopenharmony_ci return rc; 3328c2ecf20Sopenharmony_ci} 333