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