0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 #include <linux/spinlock.h>
0118 #include <linux/phy.h>
0119 #include <linux/net_tstamp.h>
0120
0121 #include "xgbe.h"
0122 #include "xgbe-common.h"
0123
0124 struct xgbe_stats {
0125 char stat_string[ETH_GSTRING_LEN];
0126 int stat_size;
0127 int stat_offset;
0128 };
0129
0130 #define XGMAC_MMC_STAT(_string, _var) \
0131 { _string, \
0132 sizeof_field(struct xgbe_mmc_stats, _var), \
0133 offsetof(struct xgbe_prv_data, mmc_stats._var), \
0134 }
0135
0136 #define XGMAC_EXT_STAT(_string, _var) \
0137 { _string, \
0138 sizeof_field(struct xgbe_ext_stats, _var), \
0139 offsetof(struct xgbe_prv_data, ext_stats._var), \
0140 }
0141
0142 static const struct xgbe_stats xgbe_gstring_stats[] = {
0143 XGMAC_MMC_STAT("tx_bytes", txoctetcount_gb),
0144 XGMAC_MMC_STAT("tx_packets", txframecount_gb),
0145 XGMAC_MMC_STAT("tx_unicast_packets", txunicastframes_gb),
0146 XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb),
0147 XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb),
0148 XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g),
0149 XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets),
0150 XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets),
0151 XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb),
0152 XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb),
0153 XGMAC_MMC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb),
0154 XGMAC_MMC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb),
0155 XGMAC_MMC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb),
0156 XGMAC_MMC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb),
0157 XGMAC_MMC_STAT("tx_underflow_errors", txunderflowerror),
0158 XGMAC_MMC_STAT("tx_pause_frames", txpauseframes),
0159
0160 XGMAC_MMC_STAT("rx_bytes", rxoctetcount_gb),
0161 XGMAC_MMC_STAT("rx_packets", rxframecount_gb),
0162 XGMAC_MMC_STAT("rx_unicast_packets", rxunicastframes_g),
0163 XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g),
0164 XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g),
0165 XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb),
0166 XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets),
0167 XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb),
0168 XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb),
0169 XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb),
0170 XGMAC_MMC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb),
0171 XGMAC_MMC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb),
0172 XGMAC_MMC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb),
0173 XGMAC_MMC_STAT("rx_undersize_packets", rxundersize_g),
0174 XGMAC_MMC_STAT("rx_oversize_packets", rxoversize_g),
0175 XGMAC_MMC_STAT("rx_crc_errors", rxcrcerror),
0176 XGMAC_MMC_STAT("rx_crc_errors_small_packets", rxrunterror),
0177 XGMAC_MMC_STAT("rx_crc_errors_giant_packets", rxjabbererror),
0178 XGMAC_MMC_STAT("rx_length_errors", rxlengtherror),
0179 XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype),
0180 XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow),
0181 XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
0182 XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors),
0183 XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors),
0184 XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
0185 XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets),
0186 XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
0187 };
0188
0189 #define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats)
0190
0191 static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
0192 {
0193 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0194 int i;
0195
0196 switch (stringset) {
0197 case ETH_SS_STATS:
0198 for (i = 0; i < XGBE_STATS_COUNT; i++) {
0199 memcpy(data, xgbe_gstring_stats[i].stat_string,
0200 ETH_GSTRING_LEN);
0201 data += ETH_GSTRING_LEN;
0202 }
0203 for (i = 0; i < pdata->tx_ring_count; i++) {
0204 sprintf(data, "txq_%u_packets", i);
0205 data += ETH_GSTRING_LEN;
0206 sprintf(data, "txq_%u_bytes", i);
0207 data += ETH_GSTRING_LEN;
0208 }
0209 for (i = 0; i < pdata->rx_ring_count; i++) {
0210 sprintf(data, "rxq_%u_packets", i);
0211 data += ETH_GSTRING_LEN;
0212 sprintf(data, "rxq_%u_bytes", i);
0213 data += ETH_GSTRING_LEN;
0214 }
0215 break;
0216 }
0217 }
0218
0219 static void xgbe_get_ethtool_stats(struct net_device *netdev,
0220 struct ethtool_stats *stats, u64 *data)
0221 {
0222 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0223 u8 *stat;
0224 int i;
0225
0226 pdata->hw_if.read_mmc_stats(pdata);
0227 for (i = 0; i < XGBE_STATS_COUNT; i++) {
0228 stat = (u8 *)pdata + xgbe_gstring_stats[i].stat_offset;
0229 *data++ = *(u64 *)stat;
0230 }
0231 for (i = 0; i < pdata->tx_ring_count; i++) {
0232 *data++ = pdata->ext_stats.txq_packets[i];
0233 *data++ = pdata->ext_stats.txq_bytes[i];
0234 }
0235 for (i = 0; i < pdata->rx_ring_count; i++) {
0236 *data++ = pdata->ext_stats.rxq_packets[i];
0237 *data++ = pdata->ext_stats.rxq_bytes[i];
0238 }
0239 }
0240
0241 static int xgbe_get_sset_count(struct net_device *netdev, int stringset)
0242 {
0243 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0244 int ret;
0245
0246 switch (stringset) {
0247 case ETH_SS_STATS:
0248 ret = XGBE_STATS_COUNT +
0249 (pdata->tx_ring_count * 2) +
0250 (pdata->rx_ring_count * 2);
0251 break;
0252
0253 default:
0254 ret = -EOPNOTSUPP;
0255 }
0256
0257 return ret;
0258 }
0259
0260 static void xgbe_get_pauseparam(struct net_device *netdev,
0261 struct ethtool_pauseparam *pause)
0262 {
0263 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0264
0265 pause->autoneg = pdata->phy.pause_autoneg;
0266 pause->tx_pause = pdata->phy.tx_pause;
0267 pause->rx_pause = pdata->phy.rx_pause;
0268 }
0269
0270 static int xgbe_set_pauseparam(struct net_device *netdev,
0271 struct ethtool_pauseparam *pause)
0272 {
0273 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0274 struct ethtool_link_ksettings *lks = &pdata->phy.lks;
0275 int ret = 0;
0276
0277 if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
0278 netdev_err(netdev,
0279 "autoneg disabled, pause autoneg not available\n");
0280 return -EINVAL;
0281 }
0282
0283 pdata->phy.pause_autoneg = pause->autoneg;
0284 pdata->phy.tx_pause = pause->tx_pause;
0285 pdata->phy.rx_pause = pause->rx_pause;
0286
0287 XGBE_CLR_ADV(lks, Pause);
0288 XGBE_CLR_ADV(lks, Asym_Pause);
0289
0290 if (pause->rx_pause) {
0291 XGBE_SET_ADV(lks, Pause);
0292 XGBE_SET_ADV(lks, Asym_Pause);
0293 }
0294
0295 if (pause->tx_pause) {
0296
0297 if (XGBE_ADV(lks, Asym_Pause))
0298 XGBE_CLR_ADV(lks, Asym_Pause);
0299 else
0300 XGBE_SET_ADV(lks, Asym_Pause);
0301 }
0302
0303 if (netif_running(netdev))
0304 ret = pdata->phy_if.phy_config_aneg(pdata);
0305
0306 return ret;
0307 }
0308
0309 static int xgbe_get_link_ksettings(struct net_device *netdev,
0310 struct ethtool_link_ksettings *cmd)
0311 {
0312 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0313 struct ethtool_link_ksettings *lks = &pdata->phy.lks;
0314
0315 cmd->base.phy_address = pdata->phy.address;
0316
0317 cmd->base.autoneg = pdata->phy.autoneg;
0318 cmd->base.speed = pdata->phy.speed;
0319 cmd->base.duplex = pdata->phy.duplex;
0320
0321 cmd->base.port = PORT_NONE;
0322
0323 XGBE_LM_COPY(cmd, supported, lks, supported);
0324 XGBE_LM_COPY(cmd, advertising, lks, advertising);
0325 XGBE_LM_COPY(cmd, lp_advertising, lks, lp_advertising);
0326
0327 return 0;
0328 }
0329
0330 static int xgbe_set_link_ksettings(struct net_device *netdev,
0331 const struct ethtool_link_ksettings *cmd)
0332 {
0333 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0334 struct ethtool_link_ksettings *lks = &pdata->phy.lks;
0335 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
0336 u32 speed;
0337 int ret;
0338
0339 speed = cmd->base.speed;
0340
0341 if (cmd->base.phy_address != pdata->phy.address) {
0342 netdev_err(netdev, "invalid phy address %hhu\n",
0343 cmd->base.phy_address);
0344 return -EINVAL;
0345 }
0346
0347 if ((cmd->base.autoneg != AUTONEG_ENABLE) &&
0348 (cmd->base.autoneg != AUTONEG_DISABLE)) {
0349 netdev_err(netdev, "unsupported autoneg %hhu\n",
0350 cmd->base.autoneg);
0351 return -EINVAL;
0352 }
0353
0354 if (cmd->base.autoneg == AUTONEG_DISABLE) {
0355 if (!pdata->phy_if.phy_valid_speed(pdata, speed)) {
0356 netdev_err(netdev, "unsupported speed %u\n", speed);
0357 return -EINVAL;
0358 }
0359
0360 if (cmd->base.duplex != DUPLEX_FULL) {
0361 netdev_err(netdev, "unsupported duplex %hhu\n",
0362 cmd->base.duplex);
0363 return -EINVAL;
0364 }
0365 }
0366
0367 netif_dbg(pdata, link, netdev,
0368 "requested advertisement 0x%*pb, phy supported 0x%*pb\n",
0369 __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising,
0370 __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported);
0371
0372 linkmode_and(advertising, cmd->link_modes.advertising,
0373 lks->link_modes.supported);
0374
0375 if ((cmd->base.autoneg == AUTONEG_ENABLE) &&
0376 bitmap_empty(advertising, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
0377 netdev_err(netdev,
0378 "unsupported requested advertisement\n");
0379 return -EINVAL;
0380 }
0381
0382 ret = 0;
0383 pdata->phy.autoneg = cmd->base.autoneg;
0384 pdata->phy.speed = speed;
0385 pdata->phy.duplex = cmd->base.duplex;
0386 linkmode_copy(lks->link_modes.advertising, advertising);
0387
0388 if (cmd->base.autoneg == AUTONEG_ENABLE)
0389 XGBE_SET_ADV(lks, Autoneg);
0390 else
0391 XGBE_CLR_ADV(lks, Autoneg);
0392
0393 if (netif_running(netdev))
0394 ret = pdata->phy_if.phy_config_aneg(pdata);
0395
0396 return ret;
0397 }
0398
0399 static void xgbe_get_drvinfo(struct net_device *netdev,
0400 struct ethtool_drvinfo *drvinfo)
0401 {
0402 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0403 struct xgbe_hw_features *hw_feat = &pdata->hw_feat;
0404
0405 strlcpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver));
0406 strlcpy(drvinfo->bus_info, dev_name(pdata->dev),
0407 sizeof(drvinfo->bus_info));
0408 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d",
0409 XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
0410 XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
0411 XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
0412 }
0413
0414 static u32 xgbe_get_msglevel(struct net_device *netdev)
0415 {
0416 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0417
0418 return pdata->msg_enable;
0419 }
0420
0421 static void xgbe_set_msglevel(struct net_device *netdev, u32 msglevel)
0422 {
0423 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0424
0425 pdata->msg_enable = msglevel;
0426 }
0427
0428 static int xgbe_get_coalesce(struct net_device *netdev,
0429 struct ethtool_coalesce *ec,
0430 struct kernel_ethtool_coalesce *kernel_coal,
0431 struct netlink_ext_ack *extack)
0432 {
0433 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0434
0435 memset(ec, 0, sizeof(struct ethtool_coalesce));
0436
0437 ec->rx_coalesce_usecs = pdata->rx_usecs;
0438 ec->rx_max_coalesced_frames = pdata->rx_frames;
0439
0440 ec->tx_max_coalesced_frames = pdata->tx_frames;
0441
0442 return 0;
0443 }
0444
0445 static int xgbe_set_coalesce(struct net_device *netdev,
0446 struct ethtool_coalesce *ec,
0447 struct kernel_ethtool_coalesce *kernel_coal,
0448 struct netlink_ext_ack *extack)
0449 {
0450 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0451 struct xgbe_hw_if *hw_if = &pdata->hw_if;
0452 unsigned int rx_frames, rx_riwt, rx_usecs;
0453 unsigned int tx_frames;
0454
0455 rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs);
0456 rx_usecs = ec->rx_coalesce_usecs;
0457 rx_frames = ec->rx_max_coalesced_frames;
0458
0459
0460 if (rx_usecs && !rx_riwt)
0461 rx_riwt = 1;
0462
0463
0464 if (rx_riwt > XGMAC_MAX_DMA_RIWT) {
0465 netdev_err(netdev, "rx-usec is limited to %d usecs\n",
0466 hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT));
0467 return -EINVAL;
0468 }
0469 if (rx_frames > pdata->rx_desc_count) {
0470 netdev_err(netdev, "rx-frames is limited to %d frames\n",
0471 pdata->rx_desc_count);
0472 return -EINVAL;
0473 }
0474
0475 tx_frames = ec->tx_max_coalesced_frames;
0476
0477
0478 if (tx_frames > pdata->tx_desc_count) {
0479 netdev_err(netdev, "tx-frames is limited to %d frames\n",
0480 pdata->tx_desc_count);
0481 return -EINVAL;
0482 }
0483
0484 pdata->rx_riwt = rx_riwt;
0485 pdata->rx_usecs = rx_usecs;
0486 pdata->rx_frames = rx_frames;
0487 hw_if->config_rx_coalesce(pdata);
0488
0489 pdata->tx_frames = tx_frames;
0490 hw_if->config_tx_coalesce(pdata);
0491
0492 return 0;
0493 }
0494
0495 static int xgbe_get_rxnfc(struct net_device *netdev,
0496 struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
0497 {
0498 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0499
0500 switch (rxnfc->cmd) {
0501 case ETHTOOL_GRXRINGS:
0502 rxnfc->data = pdata->rx_ring_count;
0503 break;
0504 default:
0505 return -EOPNOTSUPP;
0506 }
0507
0508 return 0;
0509 }
0510
0511 static u32 xgbe_get_rxfh_key_size(struct net_device *netdev)
0512 {
0513 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0514
0515 return sizeof(pdata->rss_key);
0516 }
0517
0518 static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev)
0519 {
0520 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0521
0522 return ARRAY_SIZE(pdata->rss_table);
0523 }
0524
0525 static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
0526 u8 *hfunc)
0527 {
0528 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0529 unsigned int i;
0530
0531 if (indir) {
0532 for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++)
0533 indir[i] = XGMAC_GET_BITS(pdata->rss_table[i],
0534 MAC_RSSDR, DMCH);
0535 }
0536
0537 if (key)
0538 memcpy(key, pdata->rss_key, sizeof(pdata->rss_key));
0539
0540 if (hfunc)
0541 *hfunc = ETH_RSS_HASH_TOP;
0542
0543 return 0;
0544 }
0545
0546 static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
0547 const u8 *key, const u8 hfunc)
0548 {
0549 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0550 struct xgbe_hw_if *hw_if = &pdata->hw_if;
0551 unsigned int ret;
0552
0553 if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
0554 netdev_err(netdev, "unsupported hash function\n");
0555 return -EOPNOTSUPP;
0556 }
0557
0558 if (indir) {
0559 ret = hw_if->set_rss_lookup_table(pdata, indir);
0560 if (ret)
0561 return ret;
0562 }
0563
0564 if (key) {
0565 ret = hw_if->set_rss_hash_key(pdata, key);
0566 if (ret)
0567 return ret;
0568 }
0569
0570 return 0;
0571 }
0572
0573 static int xgbe_get_ts_info(struct net_device *netdev,
0574 struct ethtool_ts_info *ts_info)
0575 {
0576 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0577
0578 ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
0579 SOF_TIMESTAMPING_RX_SOFTWARE |
0580 SOF_TIMESTAMPING_SOFTWARE |
0581 SOF_TIMESTAMPING_TX_HARDWARE |
0582 SOF_TIMESTAMPING_RX_HARDWARE |
0583 SOF_TIMESTAMPING_RAW_HARDWARE;
0584
0585 if (pdata->ptp_clock)
0586 ts_info->phc_index = ptp_clock_index(pdata->ptp_clock);
0587 else
0588 ts_info->phc_index = -1;
0589
0590 ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
0591 ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
0592 (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
0593 (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
0594 (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
0595 (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
0596 (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
0597 (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
0598 (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
0599 (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
0600 (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
0601 (1 << HWTSTAMP_FILTER_ALL);
0602
0603 return 0;
0604 }
0605
0606 static int xgbe_get_module_info(struct net_device *netdev,
0607 struct ethtool_modinfo *modinfo)
0608 {
0609 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0610
0611 return pdata->phy_if.module_info(pdata, modinfo);
0612 }
0613
0614 static int xgbe_get_module_eeprom(struct net_device *netdev,
0615 struct ethtool_eeprom *eeprom, u8 *data)
0616 {
0617 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0618
0619 return pdata->phy_if.module_eeprom(pdata, eeprom, data);
0620 }
0621
0622 static void
0623 xgbe_get_ringparam(struct net_device *netdev,
0624 struct ethtool_ringparam *ringparam,
0625 struct kernel_ethtool_ringparam *kernel_ringparam,
0626 struct netlink_ext_ack *extack)
0627 {
0628 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0629
0630 ringparam->rx_max_pending = XGBE_RX_DESC_CNT_MAX;
0631 ringparam->tx_max_pending = XGBE_TX_DESC_CNT_MAX;
0632 ringparam->rx_pending = pdata->rx_desc_count;
0633 ringparam->tx_pending = pdata->tx_desc_count;
0634 }
0635
0636 static int xgbe_set_ringparam(struct net_device *netdev,
0637 struct ethtool_ringparam *ringparam,
0638 struct kernel_ethtool_ringparam *kernel_ringparam,
0639 struct netlink_ext_ack *extack)
0640 {
0641 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0642 unsigned int rx, tx;
0643
0644 if (ringparam->rx_mini_pending || ringparam->rx_jumbo_pending) {
0645 netdev_err(netdev, "unsupported ring parameter\n");
0646 return -EINVAL;
0647 }
0648
0649 if ((ringparam->rx_pending < XGBE_RX_DESC_CNT_MIN) ||
0650 (ringparam->rx_pending > XGBE_RX_DESC_CNT_MAX)) {
0651 netdev_err(netdev,
0652 "rx ring parameter must be between %u and %u\n",
0653 XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX);
0654 return -EINVAL;
0655 }
0656
0657 if ((ringparam->tx_pending < XGBE_TX_DESC_CNT_MIN) ||
0658 (ringparam->tx_pending > XGBE_TX_DESC_CNT_MAX)) {
0659 netdev_err(netdev,
0660 "tx ring parameter must be between %u and %u\n",
0661 XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX);
0662 return -EINVAL;
0663 }
0664
0665 rx = __rounddown_pow_of_two(ringparam->rx_pending);
0666 if (rx != ringparam->rx_pending)
0667 netdev_notice(netdev,
0668 "rx ring parameter rounded to power of two: %u\n",
0669 rx);
0670
0671 tx = __rounddown_pow_of_two(ringparam->tx_pending);
0672 if (tx != ringparam->tx_pending)
0673 netdev_notice(netdev,
0674 "tx ring parameter rounded to power of two: %u\n",
0675 tx);
0676
0677 if ((rx == pdata->rx_desc_count) &&
0678 (tx == pdata->tx_desc_count))
0679 goto out;
0680
0681 pdata->rx_desc_count = rx;
0682 pdata->tx_desc_count = tx;
0683
0684 xgbe_restart_dev(pdata);
0685
0686 out:
0687 return 0;
0688 }
0689
0690 static void xgbe_get_channels(struct net_device *netdev,
0691 struct ethtool_channels *channels)
0692 {
0693 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0694 unsigned int rx, tx, combined;
0695
0696
0697
0698
0699
0700
0701
0702 rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
0703 rx = min(rx, pdata->channel_irq_count);
0704 tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
0705 tx = min(tx, pdata->channel_irq_count);
0706 tx = min(tx, pdata->tx_max_q_count);
0707
0708 combined = min(rx, tx);
0709
0710 channels->max_combined = combined;
0711 channels->max_rx = rx ? rx - 1 : 0;
0712 channels->max_tx = tx ? tx - 1 : 0;
0713
0714
0715 rx = pdata->new_rx_ring_count ? : pdata->rx_ring_count;
0716 tx = pdata->new_tx_ring_count ? : pdata->tx_ring_count;
0717
0718 combined = min(rx, tx);
0719 rx -= combined;
0720 tx -= combined;
0721
0722 channels->combined_count = combined;
0723 channels->rx_count = rx;
0724 channels->tx_count = tx;
0725 }
0726
0727 static void xgbe_print_set_channels_input(struct net_device *netdev,
0728 struct ethtool_channels *channels)
0729 {
0730 netdev_err(netdev, "channel inputs: combined=%u, rx-only=%u, tx-only=%u\n",
0731 channels->combined_count, channels->rx_count,
0732 channels->tx_count);
0733 }
0734
0735 static int xgbe_set_channels(struct net_device *netdev,
0736 struct ethtool_channels *channels)
0737 {
0738 struct xgbe_prv_data *pdata = netdev_priv(netdev);
0739 unsigned int rx, rx_curr, tx, tx_curr, combined;
0740
0741
0742
0743
0744
0745
0746
0747 rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
0748 rx = min(rx, pdata->channel_irq_count);
0749 tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
0750 tx = min(tx, pdata->tx_max_q_count);
0751 tx = min(tx, pdata->channel_irq_count);
0752
0753 combined = min(rx, tx);
0754
0755
0756 if (channels->other_count) {
0757 netdev_err(netdev,
0758 "other channel count must be zero\n");
0759 return -EINVAL;
0760 }
0761
0762
0763 if (!channels->combined_count) {
0764 netdev_err(netdev,
0765 "at least one combined Rx/Tx channel is required\n");
0766 xgbe_print_set_channels_input(netdev, channels);
0767 return -EINVAL;
0768 }
0769
0770
0771 if (channels->combined_count > combined) {
0772 netdev_err(netdev,
0773 "combined channel count cannot exceed %u\n",
0774 combined);
0775 xgbe_print_set_channels_input(netdev, channels);
0776 return -EINVAL;
0777 }
0778
0779
0780 if (channels->rx_count && channels->tx_count) {
0781 netdev_err(netdev,
0782 "cannot specify both Rx-only and Tx-only channels\n");
0783 xgbe_print_set_channels_input(netdev, channels);
0784 return -EINVAL;
0785 }
0786
0787
0788 if ((channels->combined_count + channels->rx_count) > rx) {
0789 netdev_err(netdev,
0790 "total Rx channels (%u) requested exceeds maximum available (%u)\n",
0791 channels->combined_count + channels->rx_count, rx);
0792 xgbe_print_set_channels_input(netdev, channels);
0793 return -EINVAL;
0794 }
0795
0796 if ((channels->combined_count + channels->tx_count) > tx) {
0797 netdev_err(netdev,
0798 "total Tx channels (%u) requested exceeds maximum available (%u)\n",
0799 channels->combined_count + channels->tx_count, tx);
0800 xgbe_print_set_channels_input(netdev, channels);
0801 return -EINVAL;
0802 }
0803
0804 rx = channels->combined_count + channels->rx_count;
0805 tx = channels->combined_count + channels->tx_count;
0806
0807 rx_curr = pdata->new_rx_ring_count ? : pdata->rx_ring_count;
0808 tx_curr = pdata->new_tx_ring_count ? : pdata->tx_ring_count;
0809
0810 if ((rx == rx_curr) && (tx == tx_curr))
0811 goto out;
0812
0813 pdata->new_rx_ring_count = rx;
0814 pdata->new_tx_ring_count = tx;
0815
0816 xgbe_full_restart_dev(pdata);
0817
0818 out:
0819 return 0;
0820 }
0821
0822 static const struct ethtool_ops xgbe_ethtool_ops = {
0823 .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
0824 ETHTOOL_COALESCE_MAX_FRAMES,
0825 .get_drvinfo = xgbe_get_drvinfo,
0826 .get_msglevel = xgbe_get_msglevel,
0827 .set_msglevel = xgbe_set_msglevel,
0828 .get_link = ethtool_op_get_link,
0829 .get_coalesce = xgbe_get_coalesce,
0830 .set_coalesce = xgbe_set_coalesce,
0831 .get_pauseparam = xgbe_get_pauseparam,
0832 .set_pauseparam = xgbe_set_pauseparam,
0833 .get_strings = xgbe_get_strings,
0834 .get_ethtool_stats = xgbe_get_ethtool_stats,
0835 .get_sset_count = xgbe_get_sset_count,
0836 .get_rxnfc = xgbe_get_rxnfc,
0837 .get_rxfh_key_size = xgbe_get_rxfh_key_size,
0838 .get_rxfh_indir_size = xgbe_get_rxfh_indir_size,
0839 .get_rxfh = xgbe_get_rxfh,
0840 .set_rxfh = xgbe_set_rxfh,
0841 .get_ts_info = xgbe_get_ts_info,
0842 .get_link_ksettings = xgbe_get_link_ksettings,
0843 .set_link_ksettings = xgbe_set_link_ksettings,
0844 .get_module_info = xgbe_get_module_info,
0845 .get_module_eeprom = xgbe_get_module_eeprom,
0846 .get_ringparam = xgbe_get_ringparam,
0847 .set_ringparam = xgbe_set_ringparam,
0848 .get_channels = xgbe_get_channels,
0849 .set_channels = xgbe_set_channels,
0850 };
0851
0852 const struct ethtool_ops *xgbe_get_ethtool_ops(void)
0853 {
0854 return &xgbe_ethtool_ops;
0855 }