root/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pch_gbe_get_link_ksettings
  2. pch_gbe_set_link_ksettings
  3. pch_gbe_get_regs_len
  4. pch_gbe_get_drvinfo
  5. pch_gbe_get_regs
  6. pch_gbe_get_wol
  7. pch_gbe_set_wol
  8. pch_gbe_nway_reset
  9. pch_gbe_get_ringparam
  10. pch_gbe_set_ringparam
  11. pch_gbe_get_pauseparam
  12. pch_gbe_set_pauseparam
  13. pch_gbe_get_strings
  14. pch_gbe_get_ethtool_stats
  15. pch_gbe_get_sset_count
  16. pch_gbe_set_ethtool_ops

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 1999 - 2010 Intel Corporation.
   4  * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
   5  *
   6  * This code was derived from the Intel e1000e Linux driver.
   7  */
   8 #include "pch_gbe.h"
   9 #include "pch_gbe_phy.h"
  10 
  11 /**
  12  * pch_gbe_stats - Stats item information
  13  */
  14 struct pch_gbe_stats {
  15         char string[ETH_GSTRING_LEN];
  16         size_t size;
  17         size_t offset;
  18 };
  19 
  20 #define PCH_GBE_STAT(m)                                         \
  21 {                                                               \
  22         .string = #m,                                           \
  23         .size = FIELD_SIZEOF(struct pch_gbe_hw_stats, m),       \
  24         .offset = offsetof(struct pch_gbe_hw_stats, m),         \
  25 }
  26 
  27 /**
  28  * pch_gbe_gstrings_stats - ethtool information status name list
  29  */
  30 static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
  31         PCH_GBE_STAT(rx_packets),
  32         PCH_GBE_STAT(tx_packets),
  33         PCH_GBE_STAT(rx_bytes),
  34         PCH_GBE_STAT(tx_bytes),
  35         PCH_GBE_STAT(rx_errors),
  36         PCH_GBE_STAT(tx_errors),
  37         PCH_GBE_STAT(rx_dropped),
  38         PCH_GBE_STAT(tx_dropped),
  39         PCH_GBE_STAT(multicast),
  40         PCH_GBE_STAT(collisions),
  41         PCH_GBE_STAT(rx_crc_errors),
  42         PCH_GBE_STAT(rx_frame_errors),
  43         PCH_GBE_STAT(rx_alloc_buff_failed),
  44         PCH_GBE_STAT(tx_length_errors),
  45         PCH_GBE_STAT(tx_aborted_errors),
  46         PCH_GBE_STAT(tx_carrier_errors),
  47         PCH_GBE_STAT(tx_timeout_count),
  48         PCH_GBE_STAT(tx_restart_count),
  49         PCH_GBE_STAT(intr_rx_dsc_empty_count),
  50         PCH_GBE_STAT(intr_rx_frame_err_count),
  51         PCH_GBE_STAT(intr_rx_fifo_err_count),
  52         PCH_GBE_STAT(intr_rx_dma_err_count),
  53         PCH_GBE_STAT(intr_tx_fifo_err_count),
  54         PCH_GBE_STAT(intr_tx_dma_err_count),
  55         PCH_GBE_STAT(intr_tcpip_err_count)
  56 };
  57 
  58 #define PCH_GBE_QUEUE_STATS_LEN 0
  59 #define PCH_GBE_GLOBAL_STATS_LEN        ARRAY_SIZE(pch_gbe_gstrings_stats)
  60 #define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
  61 
  62 #define PCH_GBE_MAC_REGS_LEN    (sizeof(struct pch_gbe_regs) / 4)
  63 #define PCH_GBE_REGS_LEN        (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
  64 /**
  65  * pch_gbe_get_link_ksettings - Get device-specific settings
  66  * @netdev: Network interface device structure
  67  * @ecmd:   Ethtool command
  68  * Returns:
  69  *      0:                      Successful.
  70  *      Negative value:         Failed.
  71  */
  72 static int pch_gbe_get_link_ksettings(struct net_device *netdev,
  73                                       struct ethtool_link_ksettings *ecmd)
  74 {
  75         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
  76         u32 supported, advertising;
  77 
  78         mii_ethtool_get_link_ksettings(&adapter->mii, ecmd);
  79 
  80         ethtool_convert_link_mode_to_legacy_u32(&supported,
  81                                                 ecmd->link_modes.supported);
  82         ethtool_convert_link_mode_to_legacy_u32(&advertising,
  83                                                 ecmd->link_modes.advertising);
  84 
  85         supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
  86         advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
  87 
  88         ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
  89                                                 supported);
  90         ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
  91                                                 advertising);
  92 
  93         if (!netif_carrier_ok(adapter->netdev))
  94                 ecmd->base.speed = SPEED_UNKNOWN;
  95 
  96         return 0;
  97 }
  98 
  99 /**
 100  * pch_gbe_set_link_ksettings - Set device-specific settings
 101  * @netdev: Network interface device structure
 102  * @ecmd:   Ethtool command
 103  * Returns:
 104  *      0:                      Successful.
 105  *      Negative value:         Failed.
 106  */
 107 static int pch_gbe_set_link_ksettings(struct net_device *netdev,
 108                                       const struct ethtool_link_ksettings *ecmd)
 109 {
 110         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 111         struct pch_gbe_hw *hw = &adapter->hw;
 112         struct ethtool_link_ksettings copy_ecmd;
 113         u32 speed = ecmd->base.speed;
 114         u32 advertising;
 115         int ret;
 116 
 117         pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
 118 
 119         memcpy(&copy_ecmd, ecmd, sizeof(*ecmd));
 120 
 121         /* when set_settings() is called with a ethtool_cmd previously
 122          * filled by get_settings() on a down link, speed is -1: */
 123         if (speed == UINT_MAX) {
 124                 speed = SPEED_1000;
 125                 copy_ecmd.base.speed = speed;
 126                 copy_ecmd.base.duplex = DUPLEX_FULL;
 127         }
 128         ret = mii_ethtool_set_link_ksettings(&adapter->mii, &copy_ecmd);
 129         if (ret) {
 130                 netdev_err(netdev, "Error: mii_ethtool_set_link_ksettings\n");
 131                 return ret;
 132         }
 133         hw->mac.link_speed = speed;
 134         hw->mac.link_duplex = copy_ecmd.base.duplex;
 135         ethtool_convert_link_mode_to_legacy_u32(
 136                 &advertising, copy_ecmd.link_modes.advertising);
 137         hw->phy.autoneg_advertised = advertising;
 138         hw->mac.autoneg = copy_ecmd.base.autoneg;
 139 
 140         /* reset the link */
 141         if (netif_running(adapter->netdev)) {
 142                 pch_gbe_down(adapter);
 143                 ret = pch_gbe_up(adapter);
 144         } else {
 145                 pch_gbe_reset(adapter);
 146         }
 147         return ret;
 148 }
 149 
 150 /**
 151  * pch_gbe_get_regs_len - Report the size of device registers
 152  * @netdev: Network interface device structure
 153  * Returns: the size of device registers.
 154  */
 155 static int pch_gbe_get_regs_len(struct net_device *netdev)
 156 {
 157         return PCH_GBE_REGS_LEN * (int)sizeof(u32);
 158 }
 159 
 160 /**
 161  * pch_gbe_get_drvinfo - Report driver information
 162  * @netdev:  Network interface device structure
 163  * @drvinfo: Driver information structure
 164  */
 165 static void pch_gbe_get_drvinfo(struct net_device *netdev,
 166                                  struct ethtool_drvinfo *drvinfo)
 167 {
 168         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 169 
 170         strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
 171         strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
 172         strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
 173                 sizeof(drvinfo->bus_info));
 174 }
 175 
 176 /**
 177  * pch_gbe_get_regs - Get device registers
 178  * @netdev: Network interface device structure
 179  * @regs:   Ethtool register structure
 180  * @p:      Buffer pointer of read device register date
 181  */
 182 static void pch_gbe_get_regs(struct net_device *netdev,
 183                                 struct ethtool_regs *regs, void *p)
 184 {
 185         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 186         struct pch_gbe_hw *hw = &adapter->hw;
 187         struct pci_dev *pdev = adapter->pdev;
 188         u32 *regs_buff = p;
 189         u16 i, tmp;
 190 
 191         regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
 192         for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
 193                 *regs_buff++ = ioread32(&hw->reg->INT_ST + i);
 194         /* PHY register */
 195         for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
 196                 pch_gbe_phy_read_reg_miic(&adapter->hw, i, &tmp);
 197                 *regs_buff++ = tmp;
 198         }
 199 }
 200 
 201 /**
 202  * pch_gbe_get_wol - Report whether Wake-on-Lan is enabled
 203  * @netdev: Network interface device structure
 204  * @wol:    Wake-on-Lan information
 205  */
 206 static void pch_gbe_get_wol(struct net_device *netdev,
 207                                 struct ethtool_wolinfo *wol)
 208 {
 209         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 210 
 211         wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
 212         wol->wolopts = 0;
 213 
 214         if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
 215                 wol->wolopts |= WAKE_UCAST;
 216         if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
 217                 wol->wolopts |= WAKE_MCAST;
 218         if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
 219                 wol->wolopts |= WAKE_BCAST;
 220         if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
 221                 wol->wolopts |= WAKE_MAGIC;
 222 }
 223 
 224 /**
 225  * pch_gbe_set_wol - Turn Wake-on-Lan on or off
 226  * @netdev: Network interface device structure
 227  * @wol:    Pointer of wake-on-Lan information straucture
 228  * Returns:
 229  *      0:                      Successful.
 230  *      Negative value:         Failed.
 231  */
 232 static int pch_gbe_set_wol(struct net_device *netdev,
 233                                 struct ethtool_wolinfo *wol)
 234 {
 235         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 236 
 237         if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
 238                 return -EOPNOTSUPP;
 239         /* these settings will always override what we currently have */
 240         adapter->wake_up_evt = 0;
 241 
 242         if ((wol->wolopts & WAKE_UCAST))
 243                 adapter->wake_up_evt |= PCH_GBE_WLC_IND;
 244         if ((wol->wolopts & WAKE_MCAST))
 245                 adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
 246         if ((wol->wolopts & WAKE_BCAST))
 247                 adapter->wake_up_evt |= PCH_GBE_WLC_BR;
 248         if ((wol->wolopts & WAKE_MAGIC))
 249                 adapter->wake_up_evt |= PCH_GBE_WLC_MP;
 250         return 0;
 251 }
 252 
 253 /**
 254  * pch_gbe_nway_reset - Restart autonegotiation
 255  * @netdev: Network interface device structure
 256  * Returns:
 257  *      0:                      Successful.
 258  *      Negative value:         Failed.
 259  */
 260 static int pch_gbe_nway_reset(struct net_device *netdev)
 261 {
 262         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 263 
 264         return mii_nway_restart(&adapter->mii);
 265 }
 266 
 267 /**
 268  * pch_gbe_get_ringparam - Report ring sizes
 269  * @netdev:  Network interface device structure
 270  * @ring:    Ring param structure
 271  */
 272 static void pch_gbe_get_ringparam(struct net_device *netdev,
 273                                         struct ethtool_ringparam *ring)
 274 {
 275         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 276         struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
 277         struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
 278 
 279         ring->rx_max_pending = PCH_GBE_MAX_RXD;
 280         ring->tx_max_pending = PCH_GBE_MAX_TXD;
 281         ring->rx_pending = rxdr->count;
 282         ring->tx_pending = txdr->count;
 283 }
 284 
 285 /**
 286  * pch_gbe_set_ringparam - Set ring sizes
 287  * @netdev:  Network interface device structure
 288  * @ring:    Ring param structure
 289  * Returns
 290  *      0:                      Successful.
 291  *      Negative value:         Failed.
 292  */
 293 static int pch_gbe_set_ringparam(struct net_device *netdev,
 294                                         struct ethtool_ringparam *ring)
 295 {
 296         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 297         struct pch_gbe_tx_ring *txdr, *tx_old;
 298         struct pch_gbe_rx_ring *rxdr, *rx_old;
 299         int tx_ring_size, rx_ring_size;
 300         int err = 0;
 301 
 302         if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 303                 return -EINVAL;
 304         tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
 305         rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
 306 
 307         if ((netif_running(adapter->netdev)))
 308                 pch_gbe_down(adapter);
 309         tx_old = adapter->tx_ring;
 310         rx_old = adapter->rx_ring;
 311 
 312         txdr = kzalloc(tx_ring_size, GFP_KERNEL);
 313         if (!txdr) {
 314                 err = -ENOMEM;
 315                 goto err_alloc_tx;
 316         }
 317         rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
 318         if (!rxdr) {
 319                 err = -ENOMEM;
 320                 goto err_alloc_rx;
 321         }
 322         adapter->tx_ring = txdr;
 323         adapter->rx_ring = rxdr;
 324 
 325         rxdr->count =
 326                 clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
 327         rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
 328 
 329         txdr->count =
 330                 clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
 331         txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
 332 
 333         if ((netif_running(adapter->netdev))) {
 334                 /* Try to get new resources before deleting old */
 335                 err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
 336                 if (err)
 337                         goto err_setup_rx;
 338                 err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
 339                 if (err)
 340                         goto err_setup_tx;
 341                 pch_gbe_free_rx_resources(adapter, rx_old);
 342                 pch_gbe_free_tx_resources(adapter, tx_old);
 343                 kfree(tx_old);
 344                 kfree(rx_old);
 345                 adapter->rx_ring = rxdr;
 346                 adapter->tx_ring = txdr;
 347                 err = pch_gbe_up(adapter);
 348         }
 349         return err;
 350 
 351 err_setup_tx:
 352         pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
 353 err_setup_rx:
 354         adapter->rx_ring = rx_old;
 355         adapter->tx_ring = tx_old;
 356         kfree(rxdr);
 357 err_alloc_rx:
 358         kfree(txdr);
 359 err_alloc_tx:
 360         if (netif_running(adapter->netdev))
 361                 pch_gbe_up(adapter);
 362         return err;
 363 }
 364 
 365 /**
 366  * pch_gbe_get_pauseparam - Report pause parameters
 367  * @netdev:  Network interface device structure
 368  * @pause:   Pause parameters structure
 369  */
 370 static void pch_gbe_get_pauseparam(struct net_device *netdev,
 371                                        struct ethtool_pauseparam *pause)
 372 {
 373         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 374         struct pch_gbe_hw *hw = &adapter->hw;
 375 
 376         pause->autoneg =
 377             ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
 378 
 379         if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
 380                 pause->rx_pause = 1;
 381         } else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
 382                 pause->tx_pause = 1;
 383         } else if (hw->mac.fc == PCH_GBE_FC_FULL) {
 384                 pause->rx_pause = 1;
 385                 pause->tx_pause = 1;
 386         }
 387 }
 388 
 389 /**
 390  * pch_gbe_set_pauseparam - Set pause parameters
 391  * @netdev:  Network interface device structure
 392  * @pause:   Pause parameters structure
 393  * Returns:
 394  *      0:                      Successful.
 395  *      Negative value:         Failed.
 396  */
 397 static int pch_gbe_set_pauseparam(struct net_device *netdev,
 398                                        struct ethtool_pauseparam *pause)
 399 {
 400         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 401         struct pch_gbe_hw *hw = &adapter->hw;
 402         int ret = 0;
 403 
 404         hw->mac.fc_autoneg = pause->autoneg;
 405         if ((pause->rx_pause) && (pause->tx_pause))
 406                 hw->mac.fc = PCH_GBE_FC_FULL;
 407         else if ((pause->rx_pause) && (!pause->tx_pause))
 408                 hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
 409         else if ((!pause->rx_pause) && (pause->tx_pause))
 410                 hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
 411         else if ((!pause->rx_pause) && (!pause->tx_pause))
 412                 hw->mac.fc = PCH_GBE_FC_NONE;
 413 
 414         if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
 415                 if ((netif_running(adapter->netdev))) {
 416                         pch_gbe_down(adapter);
 417                         ret = pch_gbe_up(adapter);
 418                 } else {
 419                         pch_gbe_reset(adapter);
 420                 }
 421         } else {
 422                 ret = pch_gbe_mac_force_mac_fc(hw);
 423         }
 424         return ret;
 425 }
 426 
 427 /**
 428  * pch_gbe_get_strings - Return a set of strings that describe the requested
 429  *                       objects
 430  * @netdev:    Network interface device structure
 431  * @stringset: Select the stringset. [ETH_SS_TEST] [ETH_SS_STATS]
 432  * @data:      Pointer of read string data.
 433  */
 434 static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
 435                                         u8 *data)
 436 {
 437         u8 *p = data;
 438         int i;
 439 
 440         switch (stringset) {
 441         case (u32) ETH_SS_STATS:
 442                 for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
 443                         memcpy(p, pch_gbe_gstrings_stats[i].string,
 444                                ETH_GSTRING_LEN);
 445                         p += ETH_GSTRING_LEN;
 446                 }
 447                 break;
 448         }
 449 }
 450 
 451 /**
 452  * pch_gbe_get_ethtool_stats - Return statistics about the device
 453  * @netdev: Network interface device structure
 454  * @stats:  Ethtool statue structure
 455  * @data:   Pointer of read status area
 456  */
 457 static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
 458                                   struct ethtool_stats *stats, u64 *data)
 459 {
 460         struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 461         int i;
 462         const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
 463         char *hw_stats = (char *)&adapter->stats;
 464 
 465         pch_gbe_update_stats(adapter);
 466         for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
 467                 char *p = hw_stats + gstats->offset;
 468                 data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
 469                 gstats++;
 470         }
 471 }
 472 
 473 static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
 474 {
 475         switch (sset) {
 476         case ETH_SS_STATS:
 477                 return PCH_GBE_STATS_LEN;
 478         default:
 479                 return -EOPNOTSUPP;
 480         }
 481 }
 482 
 483 static const struct ethtool_ops pch_gbe_ethtool_ops = {
 484         .get_drvinfo = pch_gbe_get_drvinfo,
 485         .get_regs_len = pch_gbe_get_regs_len,
 486         .get_regs = pch_gbe_get_regs,
 487         .get_wol = pch_gbe_get_wol,
 488         .set_wol = pch_gbe_set_wol,
 489         .nway_reset = pch_gbe_nway_reset,
 490         .get_link = ethtool_op_get_link,
 491         .get_ringparam = pch_gbe_get_ringparam,
 492         .set_ringparam = pch_gbe_set_ringparam,
 493         .get_pauseparam = pch_gbe_get_pauseparam,
 494         .set_pauseparam = pch_gbe_set_pauseparam,
 495         .get_strings = pch_gbe_get_strings,
 496         .get_ethtool_stats = pch_gbe_get_ethtool_stats,
 497         .get_sset_count = pch_gbe_get_sset_count,
 498         .get_link_ksettings = pch_gbe_get_link_ksettings,
 499         .set_link_ksettings = pch_gbe_set_link_ksettings,
 500 };
 501 
 502 void pch_gbe_set_ethtool_ops(struct net_device *netdev)
 503 {
 504         netdev->ethtool_ops = &pch_gbe_ethtool_ops;
 505 }

/* [<][>][^][v][top][bottom][index][help] */