atl1e_ethtool.c (10747B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright(c) 2007 Atheros Corporation. All rights reserved. 4 * 5 * Derived from Intel e1000 driver 6 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 7 */ 8 9#include <linux/netdevice.h> 10#include <linux/ethtool.h> 11#include <linux/slab.h> 12 13#include "atl1e.h" 14 15static int atl1e_get_link_ksettings(struct net_device *netdev, 16 struct ethtool_link_ksettings *cmd) 17{ 18 struct atl1e_adapter *adapter = netdev_priv(netdev); 19 struct atl1e_hw *hw = &adapter->hw; 20 u32 supported, advertising; 21 22 supported = (SUPPORTED_10baseT_Half | 23 SUPPORTED_10baseT_Full | 24 SUPPORTED_100baseT_Half | 25 SUPPORTED_100baseT_Full | 26 SUPPORTED_Autoneg | 27 SUPPORTED_TP); 28 if (hw->nic_type == athr_l1e) 29 supported |= SUPPORTED_1000baseT_Full; 30 31 advertising = ADVERTISED_TP; 32 33 advertising |= ADVERTISED_Autoneg; 34 advertising |= hw->autoneg_advertised; 35 36 cmd->base.port = PORT_TP; 37 cmd->base.phy_address = 0; 38 39 if (adapter->link_speed != SPEED_0) { 40 cmd->base.speed = adapter->link_speed; 41 if (adapter->link_duplex == FULL_DUPLEX) 42 cmd->base.duplex = DUPLEX_FULL; 43 else 44 cmd->base.duplex = DUPLEX_HALF; 45 } else { 46 cmd->base.speed = SPEED_UNKNOWN; 47 cmd->base.duplex = DUPLEX_UNKNOWN; 48 } 49 50 cmd->base.autoneg = AUTONEG_ENABLE; 51 52 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 53 supported); 54 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 55 advertising); 56 57 return 0; 58} 59 60static int atl1e_set_link_ksettings(struct net_device *netdev, 61 const struct ethtool_link_ksettings *cmd) 62{ 63 struct atl1e_adapter *adapter = netdev_priv(netdev); 64 struct atl1e_hw *hw = &adapter->hw; 65 u32 advertising; 66 67 ethtool_convert_link_mode_to_legacy_u32(&advertising, 68 cmd->link_modes.advertising); 69 70 while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) 71 msleep(1); 72 73 if (cmd->base.autoneg == AUTONEG_ENABLE) { 74 u16 adv4, adv9; 75 76 if (advertising & ADVERTISE_1000_FULL) { 77 if (hw->nic_type == athr_l1e) { 78 hw->autoneg_advertised = 79 advertising & AT_ADV_MASK; 80 } else { 81 clear_bit(__AT_RESETTING, &adapter->flags); 82 return -EINVAL; 83 } 84 } else if (advertising & ADVERTISE_1000_HALF) { 85 clear_bit(__AT_RESETTING, &adapter->flags); 86 return -EINVAL; 87 } else { 88 hw->autoneg_advertised = 89 advertising & AT_ADV_MASK; 90 } 91 advertising = hw->autoneg_advertised | 92 ADVERTISED_TP | ADVERTISED_Autoneg; 93 94 adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL; 95 adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK; 96 if (hw->autoneg_advertised & ADVERTISE_10_HALF) 97 adv4 |= ADVERTISE_10HALF; 98 if (hw->autoneg_advertised & ADVERTISE_10_FULL) 99 adv4 |= ADVERTISE_10FULL; 100 if (hw->autoneg_advertised & ADVERTISE_100_HALF) 101 adv4 |= ADVERTISE_100HALF; 102 if (hw->autoneg_advertised & ADVERTISE_100_FULL) 103 adv4 |= ADVERTISE_100FULL; 104 if (hw->autoneg_advertised & ADVERTISE_1000_FULL) 105 adv9 |= ADVERTISE_1000FULL; 106 107 if (adv4 != hw->mii_autoneg_adv_reg || 108 adv9 != hw->mii_1000t_ctrl_reg) { 109 hw->mii_autoneg_adv_reg = adv4; 110 hw->mii_1000t_ctrl_reg = adv9; 111 hw->re_autoneg = true; 112 } 113 114 } else { 115 clear_bit(__AT_RESETTING, &adapter->flags); 116 return -EINVAL; 117 } 118 119 /* reset the link */ 120 121 if (netif_running(adapter->netdev)) { 122 atl1e_down(adapter); 123 atl1e_up(adapter); 124 } else 125 atl1e_reset_hw(&adapter->hw); 126 127 clear_bit(__AT_RESETTING, &adapter->flags); 128 return 0; 129} 130 131static u32 atl1e_get_msglevel(struct net_device *netdev) 132{ 133#ifdef DBG 134 return 1; 135#else 136 return 0; 137#endif 138} 139 140static int atl1e_get_regs_len(struct net_device *netdev) 141{ 142 return AT_REGS_LEN * sizeof(u32); 143} 144 145static void atl1e_get_regs(struct net_device *netdev, 146 struct ethtool_regs *regs, void *p) 147{ 148 struct atl1e_adapter *adapter = netdev_priv(netdev); 149 struct atl1e_hw *hw = &adapter->hw; 150 u32 *regs_buff = p; 151 u16 phy_data; 152 153 memset(p, 0, AT_REGS_LEN * sizeof(u32)); 154 155 regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; 156 157 regs_buff[0] = AT_READ_REG(hw, REG_VPD_CAP); 158 regs_buff[1] = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); 159 regs_buff[2] = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG); 160 regs_buff[3] = AT_READ_REG(hw, REG_TWSI_CTRL); 161 regs_buff[4] = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); 162 regs_buff[5] = AT_READ_REG(hw, REG_MASTER_CTRL); 163 regs_buff[6] = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT); 164 regs_buff[7] = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); 165 regs_buff[8] = AT_READ_REG(hw, REG_GPHY_CTRL); 166 regs_buff[9] = AT_READ_REG(hw, REG_CMBDISDMA_TIMER); 167 regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS); 168 regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL); 169 regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK); 170 regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL); 171 regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG); 172 regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR); 173 regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4); 174 regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE); 175 regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4); 176 regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); 177 regs_buff[20] = AT_READ_REG(hw, REG_MTU); 178 regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL); 179 regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR); 180 regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN); 181 regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR); 182 regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN); 183 regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR); 184 regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN); 185 regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR); 186 regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR); 187 188 atl1e_read_phy_reg(hw, MII_BMCR, &phy_data); 189 regs_buff[73] = (u32)phy_data; 190 atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); 191 regs_buff[74] = (u32)phy_data; 192} 193 194static int atl1e_get_eeprom_len(struct net_device *netdev) 195{ 196 struct atl1e_adapter *adapter = netdev_priv(netdev); 197 198 if (!atl1e_check_eeprom_exist(&adapter->hw)) 199 return AT_EEPROM_LEN; 200 else 201 return 0; 202} 203 204static int atl1e_get_eeprom(struct net_device *netdev, 205 struct ethtool_eeprom *eeprom, u8 *bytes) 206{ 207 struct atl1e_adapter *adapter = netdev_priv(netdev); 208 struct atl1e_hw *hw = &adapter->hw; 209 u32 *eeprom_buff; 210 int first_dword, last_dword; 211 int ret_val = 0; 212 int i; 213 214 if (eeprom->len == 0) 215 return -EINVAL; 216 217 if (atl1e_check_eeprom_exist(hw)) /* not exist */ 218 return -EINVAL; 219 220 eeprom->magic = hw->vendor_id | (hw->device_id << 16); 221 222 first_dword = eeprom->offset >> 2; 223 last_dword = (eeprom->offset + eeprom->len - 1) >> 2; 224 225 eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32), 226 GFP_KERNEL); 227 if (eeprom_buff == NULL) 228 return -ENOMEM; 229 230 for (i = first_dword; i < last_dword; i++) { 231 if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { 232 kfree(eeprom_buff); 233 return -EIO; 234 } 235 } 236 237 memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), 238 eeprom->len); 239 kfree(eeprom_buff); 240 241 return ret_val; 242} 243 244static int atl1e_set_eeprom(struct net_device *netdev, 245 struct ethtool_eeprom *eeprom, u8 *bytes) 246{ 247 struct atl1e_adapter *adapter = netdev_priv(netdev); 248 struct atl1e_hw *hw = &adapter->hw; 249 u32 *eeprom_buff; 250 u32 *ptr; 251 int first_dword, last_dword; 252 int ret_val = 0; 253 int i; 254 255 if (eeprom->len == 0) 256 return -EOPNOTSUPP; 257 258 if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) 259 return -EINVAL; 260 261 first_dword = eeprom->offset >> 2; 262 last_dword = (eeprom->offset + eeprom->len - 1) >> 2; 263 eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL); 264 if (eeprom_buff == NULL) 265 return -ENOMEM; 266 267 ptr = eeprom_buff; 268 269 if (eeprom->offset & 3) { 270 /* need read/modify/write of first changed EEPROM word */ 271 /* only the second byte of the word is being modified */ 272 if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) { 273 ret_val = -EIO; 274 goto out; 275 } 276 ptr++; 277 } 278 if (((eeprom->offset + eeprom->len) & 3)) { 279 /* need read/modify/write of last changed EEPROM word */ 280 /* only the first byte of the word is being modified */ 281 282 if (!atl1e_read_eeprom(hw, last_dword * 4, 283 &(eeprom_buff[last_dword - first_dword]))) { 284 ret_val = -EIO; 285 goto out; 286 } 287 } 288 289 /* Device's eeprom is always little-endian, word addressable */ 290 memcpy(ptr, bytes, eeprom->len); 291 292 for (i = 0; i < last_dword - first_dword + 1; i++) { 293 if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4), 294 eeprom_buff[i])) { 295 ret_val = -EIO; 296 goto out; 297 } 298 } 299out: 300 kfree(eeprom_buff); 301 return ret_val; 302} 303 304static void atl1e_get_drvinfo(struct net_device *netdev, 305 struct ethtool_drvinfo *drvinfo) 306{ 307 struct atl1e_adapter *adapter = netdev_priv(netdev); 308 309 strlcpy(drvinfo->driver, atl1e_driver_name, sizeof(drvinfo->driver)); 310 strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version)); 311 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 312 sizeof(drvinfo->bus_info)); 313} 314 315static void atl1e_get_wol(struct net_device *netdev, 316 struct ethtool_wolinfo *wol) 317{ 318 struct atl1e_adapter *adapter = netdev_priv(netdev); 319 320 wol->supported = WAKE_MAGIC | WAKE_PHY; 321 wol->wolopts = 0; 322 323 if (adapter->wol & AT_WUFC_EX) 324 wol->wolopts |= WAKE_UCAST; 325 if (adapter->wol & AT_WUFC_MC) 326 wol->wolopts |= WAKE_MCAST; 327 if (adapter->wol & AT_WUFC_BC) 328 wol->wolopts |= WAKE_BCAST; 329 if (adapter->wol & AT_WUFC_MAG) 330 wol->wolopts |= WAKE_MAGIC; 331 if (adapter->wol & AT_WUFC_LNKC) 332 wol->wolopts |= WAKE_PHY; 333} 334 335static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) 336{ 337 struct atl1e_adapter *adapter = netdev_priv(netdev); 338 339 if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | 340 WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) 341 return -EOPNOTSUPP; 342 /* these settings will always override what we currently have */ 343 adapter->wol = 0; 344 345 if (wol->wolopts & WAKE_MAGIC) 346 adapter->wol |= AT_WUFC_MAG; 347 if (wol->wolopts & WAKE_PHY) 348 adapter->wol |= AT_WUFC_LNKC; 349 350 device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); 351 352 return 0; 353} 354 355static int atl1e_nway_reset(struct net_device *netdev) 356{ 357 struct atl1e_adapter *adapter = netdev_priv(netdev); 358 if (netif_running(netdev)) 359 atl1e_reinit_locked(adapter); 360 return 0; 361} 362 363static const struct ethtool_ops atl1e_ethtool_ops = { 364 .get_drvinfo = atl1e_get_drvinfo, 365 .get_regs_len = atl1e_get_regs_len, 366 .get_regs = atl1e_get_regs, 367 .get_wol = atl1e_get_wol, 368 .set_wol = atl1e_set_wol, 369 .get_msglevel = atl1e_get_msglevel, 370 .nway_reset = atl1e_nway_reset, 371 .get_link = ethtool_op_get_link, 372 .get_eeprom_len = atl1e_get_eeprom_len, 373 .get_eeprom = atl1e_get_eeprom, 374 .set_eeprom = atl1e_set_eeprom, 375 .get_link_ksettings = atl1e_get_link_ksettings, 376 .set_link_ksettings = atl1e_set_link_ksettings, 377}; 378 379void atl1e_set_ethtool_ops(struct net_device *netdev) 380{ 381 netdev->ethtool_ops = &atl1e_ethtool_ops; 382}