0001
0002
0003
0004
0005
0006
0007
0008 #include "pch_gbe.h"
0009 #include "pch_gbe_phy.h"
0010
0011 static const char pch_driver_version[] = "1.01";
0012
0013
0014
0015
0016 struct pch_gbe_stats {
0017 char string[ETH_GSTRING_LEN];
0018 size_t size;
0019 size_t offset;
0020 };
0021
0022 #define PCH_GBE_STAT(m) \
0023 { \
0024 .string = #m, \
0025 .size = sizeof_field(struct pch_gbe_hw_stats, m), \
0026 .offset = offsetof(struct pch_gbe_hw_stats, m), \
0027 }
0028
0029
0030
0031
0032 static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
0033 PCH_GBE_STAT(rx_packets),
0034 PCH_GBE_STAT(tx_packets),
0035 PCH_GBE_STAT(rx_bytes),
0036 PCH_GBE_STAT(tx_bytes),
0037 PCH_GBE_STAT(rx_errors),
0038 PCH_GBE_STAT(tx_errors),
0039 PCH_GBE_STAT(rx_dropped),
0040 PCH_GBE_STAT(tx_dropped),
0041 PCH_GBE_STAT(multicast),
0042 PCH_GBE_STAT(collisions),
0043 PCH_GBE_STAT(rx_crc_errors),
0044 PCH_GBE_STAT(rx_frame_errors),
0045 PCH_GBE_STAT(rx_alloc_buff_failed),
0046 PCH_GBE_STAT(tx_length_errors),
0047 PCH_GBE_STAT(tx_aborted_errors),
0048 PCH_GBE_STAT(tx_carrier_errors),
0049 PCH_GBE_STAT(tx_timeout_count),
0050 PCH_GBE_STAT(tx_restart_count),
0051 PCH_GBE_STAT(intr_rx_dsc_empty_count),
0052 PCH_GBE_STAT(intr_rx_frame_err_count),
0053 PCH_GBE_STAT(intr_rx_fifo_err_count),
0054 PCH_GBE_STAT(intr_rx_dma_err_count),
0055 PCH_GBE_STAT(intr_tx_fifo_err_count),
0056 PCH_GBE_STAT(intr_tx_dma_err_count),
0057 PCH_GBE_STAT(intr_tcpip_err_count)
0058 };
0059
0060 #define PCH_GBE_QUEUE_STATS_LEN 0
0061 #define PCH_GBE_GLOBAL_STATS_LEN ARRAY_SIZE(pch_gbe_gstrings_stats)
0062 #define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
0063
0064 #define PCH_GBE_MAC_REGS_LEN (sizeof(struct pch_gbe_regs) / 4)
0065 #define PCH_GBE_REGS_LEN (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
0066
0067
0068
0069
0070
0071
0072
0073
0074 static int pch_gbe_get_link_ksettings(struct net_device *netdev,
0075 struct ethtool_link_ksettings *ecmd)
0076 {
0077 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0078 u32 supported, advertising;
0079
0080 mii_ethtool_get_link_ksettings(&adapter->mii, ecmd);
0081
0082 ethtool_convert_link_mode_to_legacy_u32(&supported,
0083 ecmd->link_modes.supported);
0084 ethtool_convert_link_mode_to_legacy_u32(&advertising,
0085 ecmd->link_modes.advertising);
0086
0087 supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
0088 advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
0089
0090 ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
0091 supported);
0092 ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
0093 advertising);
0094
0095 if (!netif_carrier_ok(adapter->netdev))
0096 ecmd->base.speed = SPEED_UNKNOWN;
0097
0098 return 0;
0099 }
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 static int pch_gbe_set_link_ksettings(struct net_device *netdev,
0110 const struct ethtool_link_ksettings *ecmd)
0111 {
0112 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0113 struct pch_gbe_hw *hw = &adapter->hw;
0114 struct ethtool_link_ksettings copy_ecmd;
0115 u32 speed = ecmd->base.speed;
0116 u32 advertising;
0117 int ret;
0118
0119 pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
0120
0121 memcpy(©_ecmd, ecmd, sizeof(*ecmd));
0122
0123
0124
0125 if (speed == UINT_MAX) {
0126 speed = SPEED_1000;
0127 copy_ecmd.base.speed = speed;
0128 copy_ecmd.base.duplex = DUPLEX_FULL;
0129 }
0130 ret = mii_ethtool_set_link_ksettings(&adapter->mii, ©_ecmd);
0131 if (ret) {
0132 netdev_err(netdev, "Error: mii_ethtool_set_link_ksettings\n");
0133 return ret;
0134 }
0135 hw->mac.link_speed = speed;
0136 hw->mac.link_duplex = copy_ecmd.base.duplex;
0137 ethtool_convert_link_mode_to_legacy_u32(
0138 &advertising, copy_ecmd.link_modes.advertising);
0139 hw->phy.autoneg_advertised = advertising;
0140 hw->mac.autoneg = copy_ecmd.base.autoneg;
0141
0142
0143 if (netif_running(adapter->netdev)) {
0144 pch_gbe_down(adapter);
0145 ret = pch_gbe_up(adapter);
0146 } else {
0147 pch_gbe_reset(adapter);
0148 }
0149 return ret;
0150 }
0151
0152
0153
0154
0155
0156
0157 static int pch_gbe_get_regs_len(struct net_device *netdev)
0158 {
0159 return PCH_GBE_REGS_LEN * (int)sizeof(u32);
0160 }
0161
0162
0163
0164
0165
0166
0167 static void pch_gbe_get_drvinfo(struct net_device *netdev,
0168 struct ethtool_drvinfo *drvinfo)
0169 {
0170 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0171
0172 strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
0173 strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
0174 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
0175 sizeof(drvinfo->bus_info));
0176 }
0177
0178
0179
0180
0181
0182
0183
0184 static void pch_gbe_get_regs(struct net_device *netdev,
0185 struct ethtool_regs *regs, void *p)
0186 {
0187 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0188 struct pch_gbe_hw *hw = &adapter->hw;
0189 struct pci_dev *pdev = adapter->pdev;
0190 u32 *regs_buff = p;
0191 u16 i, tmp;
0192
0193 regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
0194 for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
0195 *regs_buff++ = ioread32(&hw->reg->INT_ST + i);
0196
0197 for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
0198 pch_gbe_phy_read_reg_miic(&adapter->hw, i, &tmp);
0199 *regs_buff++ = tmp;
0200 }
0201 }
0202
0203
0204
0205
0206
0207
0208 static void pch_gbe_get_wol(struct net_device *netdev,
0209 struct ethtool_wolinfo *wol)
0210 {
0211 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0212
0213 wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
0214 wol->wolopts = 0;
0215
0216 if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
0217 wol->wolopts |= WAKE_UCAST;
0218 if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
0219 wol->wolopts |= WAKE_MCAST;
0220 if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
0221 wol->wolopts |= WAKE_BCAST;
0222 if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
0223 wol->wolopts |= WAKE_MAGIC;
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 static int pch_gbe_set_wol(struct net_device *netdev,
0235 struct ethtool_wolinfo *wol)
0236 {
0237 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0238
0239 if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
0240 return -EOPNOTSUPP;
0241
0242 adapter->wake_up_evt = 0;
0243
0244 if ((wol->wolopts & WAKE_UCAST))
0245 adapter->wake_up_evt |= PCH_GBE_WLC_IND;
0246 if ((wol->wolopts & WAKE_MCAST))
0247 adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
0248 if ((wol->wolopts & WAKE_BCAST))
0249 adapter->wake_up_evt |= PCH_GBE_WLC_BR;
0250 if ((wol->wolopts & WAKE_MAGIC))
0251 adapter->wake_up_evt |= PCH_GBE_WLC_MP;
0252 return 0;
0253 }
0254
0255
0256
0257
0258
0259
0260
0261
0262 static int pch_gbe_nway_reset(struct net_device *netdev)
0263 {
0264 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0265
0266 return mii_nway_restart(&adapter->mii);
0267 }
0268
0269
0270
0271
0272
0273
0274
0275
0276 static void pch_gbe_get_ringparam(struct net_device *netdev,
0277 struct ethtool_ringparam *ring,
0278 struct kernel_ethtool_ringparam *kernel_ring,
0279 struct netlink_ext_ack *extack)
0280 {
0281 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0282 struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
0283 struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
0284
0285 ring->rx_max_pending = PCH_GBE_MAX_RXD;
0286 ring->tx_max_pending = PCH_GBE_MAX_TXD;
0287 ring->rx_pending = rxdr->count;
0288 ring->tx_pending = txdr->count;
0289 }
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 static int pch_gbe_set_ringparam(struct net_device *netdev,
0302 struct ethtool_ringparam *ring,
0303 struct kernel_ethtool_ringparam *kernel_ring,
0304 struct netlink_ext_ack *extack)
0305 {
0306 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0307 struct pch_gbe_tx_ring *txdr, *tx_old;
0308 struct pch_gbe_rx_ring *rxdr, *rx_old;
0309 int tx_ring_size, rx_ring_size;
0310 int err = 0;
0311
0312 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
0313 return -EINVAL;
0314 tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
0315 rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
0316
0317 if ((netif_running(adapter->netdev)))
0318 pch_gbe_down(adapter);
0319 tx_old = adapter->tx_ring;
0320 rx_old = adapter->rx_ring;
0321
0322 txdr = kzalloc(tx_ring_size, GFP_KERNEL);
0323 if (!txdr) {
0324 err = -ENOMEM;
0325 goto err_alloc_tx;
0326 }
0327 rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
0328 if (!rxdr) {
0329 err = -ENOMEM;
0330 goto err_alloc_rx;
0331 }
0332 adapter->tx_ring = txdr;
0333 adapter->rx_ring = rxdr;
0334
0335 rxdr->count =
0336 clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
0337 rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
0338
0339 txdr->count =
0340 clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
0341 txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
0342
0343 if ((netif_running(adapter->netdev))) {
0344
0345 err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
0346 if (err)
0347 goto err_setup_rx;
0348 err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
0349 if (err)
0350 goto err_setup_tx;
0351 pch_gbe_free_rx_resources(adapter, rx_old);
0352 pch_gbe_free_tx_resources(adapter, tx_old);
0353 kfree(tx_old);
0354 kfree(rx_old);
0355 adapter->rx_ring = rxdr;
0356 adapter->tx_ring = txdr;
0357 err = pch_gbe_up(adapter);
0358 }
0359 return err;
0360
0361 err_setup_tx:
0362 pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
0363 err_setup_rx:
0364 adapter->rx_ring = rx_old;
0365 adapter->tx_ring = tx_old;
0366 kfree(rxdr);
0367 err_alloc_rx:
0368 kfree(txdr);
0369 err_alloc_tx:
0370 if (netif_running(adapter->netdev))
0371 pch_gbe_up(adapter);
0372 return err;
0373 }
0374
0375
0376
0377
0378
0379
0380 static void pch_gbe_get_pauseparam(struct net_device *netdev,
0381 struct ethtool_pauseparam *pause)
0382 {
0383 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0384 struct pch_gbe_hw *hw = &adapter->hw;
0385
0386 pause->autoneg =
0387 ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
0388
0389 if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
0390 pause->rx_pause = 1;
0391 } else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
0392 pause->tx_pause = 1;
0393 } else if (hw->mac.fc == PCH_GBE_FC_FULL) {
0394 pause->rx_pause = 1;
0395 pause->tx_pause = 1;
0396 }
0397 }
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 static int pch_gbe_set_pauseparam(struct net_device *netdev,
0408 struct ethtool_pauseparam *pause)
0409 {
0410 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0411 struct pch_gbe_hw *hw = &adapter->hw;
0412 int ret = 0;
0413
0414 hw->mac.fc_autoneg = pause->autoneg;
0415 if ((pause->rx_pause) && (pause->tx_pause))
0416 hw->mac.fc = PCH_GBE_FC_FULL;
0417 else if ((pause->rx_pause) && (!pause->tx_pause))
0418 hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
0419 else if ((!pause->rx_pause) && (pause->tx_pause))
0420 hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
0421 else if ((!pause->rx_pause) && (!pause->tx_pause))
0422 hw->mac.fc = PCH_GBE_FC_NONE;
0423
0424 if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
0425 if ((netif_running(adapter->netdev))) {
0426 pch_gbe_down(adapter);
0427 ret = pch_gbe_up(adapter);
0428 } else {
0429 pch_gbe_reset(adapter);
0430 }
0431 } else {
0432 ret = pch_gbe_mac_force_mac_fc(hw);
0433 }
0434 return ret;
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444 static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
0445 u8 *data)
0446 {
0447 u8 *p = data;
0448 int i;
0449
0450 switch (stringset) {
0451 case (u32) ETH_SS_STATS:
0452 for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
0453 memcpy(p, pch_gbe_gstrings_stats[i].string,
0454 ETH_GSTRING_LEN);
0455 p += ETH_GSTRING_LEN;
0456 }
0457 break;
0458 }
0459 }
0460
0461
0462
0463
0464
0465
0466
0467 static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
0468 struct ethtool_stats *stats, u64 *data)
0469 {
0470 struct pch_gbe_adapter *adapter = netdev_priv(netdev);
0471 int i;
0472 const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
0473 char *hw_stats = (char *)&adapter->stats;
0474
0475 pch_gbe_update_stats(adapter);
0476 for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
0477 char *p = hw_stats + gstats->offset;
0478 data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
0479 gstats++;
0480 }
0481 }
0482
0483 static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
0484 {
0485 switch (sset) {
0486 case ETH_SS_STATS:
0487 return PCH_GBE_STATS_LEN;
0488 default:
0489 return -EOPNOTSUPP;
0490 }
0491 }
0492
0493 static const struct ethtool_ops pch_gbe_ethtool_ops = {
0494 .get_drvinfo = pch_gbe_get_drvinfo,
0495 .get_regs_len = pch_gbe_get_regs_len,
0496 .get_regs = pch_gbe_get_regs,
0497 .get_wol = pch_gbe_get_wol,
0498 .set_wol = pch_gbe_set_wol,
0499 .nway_reset = pch_gbe_nway_reset,
0500 .get_link = ethtool_op_get_link,
0501 .get_ringparam = pch_gbe_get_ringparam,
0502 .set_ringparam = pch_gbe_set_ringparam,
0503 .get_pauseparam = pch_gbe_get_pauseparam,
0504 .set_pauseparam = pch_gbe_set_pauseparam,
0505 .get_strings = pch_gbe_get_strings,
0506 .get_ethtool_stats = pch_gbe_get_ethtool_stats,
0507 .get_sset_count = pch_gbe_get_sset_count,
0508 .get_link_ksettings = pch_gbe_get_link_ksettings,
0509 .set_link_ksettings = pch_gbe_set_link_ksettings,
0510 };
0511
0512 void pch_gbe_set_ethtool_ops(struct net_device *netdev)
0513 {
0514 netdev->ethtool_ops = &pch_gbe_ethtool_ops;
0515 }