Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * AMD 10Gb Ethernet driver
0003  *
0004  * This file is available to you under your choice of the following two
0005  * licenses:
0006  *
0007  * License 1: GPLv2
0008  *
0009  * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
0010  *
0011  * This file is free software; you may copy, redistribute and/or modify
0012  * it under the terms of the GNU General Public License as published by
0013  * the Free Software Foundation, either version 2 of the License, or (at
0014  * your option) any later version.
0015  *
0016  * This file is distributed in the hope that it will be useful, but
0017  * WITHOUT ANY WARRANTY; without even the implied warranty of
0018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0019  * General Public License for more details.
0020  *
0021  * You should have received a copy of the GNU General Public License
0022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0023  *
0024  * This file incorporates work covered by the following copyright and
0025  * permission notice:
0026  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
0027  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
0028  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
0029  *     and you.
0030  *
0031  *     The Software IS NOT an item of Licensed Software or Licensed Product
0032  *     under any End User Software License Agreement or Agreement for Licensed
0033  *     Product with Synopsys or any supplement thereto.  Permission is hereby
0034  *     granted, free of charge, to any person obtaining a copy of this software
0035  *     annotated with this license and the Software, to deal in the Software
0036  *     without restriction, including without limitation the rights to use,
0037  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
0038  *     of the Software, and to permit persons to whom the Software is furnished
0039  *     to do so, subject to the following conditions:
0040  *
0041  *     The above copyright notice and this permission notice shall be included
0042  *     in all copies or substantial portions of the Software.
0043  *
0044  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
0045  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
0046  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0047  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
0048  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0049  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0050  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0051  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0052  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0053  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0054  *     THE POSSIBILITY OF SUCH DAMAGE.
0055  *
0056  *
0057  * License 2: Modified BSD
0058  *
0059  * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
0060  * All rights reserved.
0061  *
0062  * Redistribution and use in source and binary forms, with or without
0063  * modification, are permitted provided that the following conditions are met:
0064  *     * Redistributions of source code must retain the above copyright
0065  *       notice, this list of conditions and the following disclaimer.
0066  *     * Redistributions in binary form must reproduce the above copyright
0067  *       notice, this list of conditions and the following disclaimer in the
0068  *       documentation and/or other materials provided with the distribution.
0069  *     * Neither the name of Advanced Micro Devices, Inc. nor the
0070  *       names of its contributors may be used to endorse or promote products
0071  *       derived from this software without specific prior written permission.
0072  *
0073  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0074  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0075  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0076  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
0077  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0078  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0079  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0080  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0081  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0082  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0083  *
0084  * This file incorporates work covered by the following copyright and
0085  * permission notice:
0086  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
0087  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
0088  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
0089  *     and you.
0090  *
0091  *     The Software IS NOT an item of Licensed Software or Licensed Product
0092  *     under any End User Software License Agreement or Agreement for Licensed
0093  *     Product with Synopsys or any supplement thereto.  Permission is hereby
0094  *     granted, free of charge, to any person obtaining a copy of this software
0095  *     annotated with this license and the Software, to deal in the Software
0096  *     without restriction, including without limitation the rights to use,
0097  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
0098  *     of the Software, and to permit persons to whom the Software is furnished
0099  *     to do so, subject to the following conditions:
0100  *
0101  *     The above copyright notice and this permission notice shall be included
0102  *     in all copies or substantial portions of the Software.
0103  *
0104  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
0105  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
0106  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0107  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
0108  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0109  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0110  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0111  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0112  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0113  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0114  *     THE POSSIBILITY OF SUCH DAMAGE.
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         /* Equivalent to XOR of Asym_Pause */
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     /* Use smallest possible value if conversion resulted in zero */
0460     if (rx_usecs && !rx_riwt)
0461         rx_riwt = 1;
0462 
0463     /* Check the bounds of values for Rx */
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     /* Check the bounds of values for Tx */
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     /* Calculate maximums allowed:
0697      *   - Take into account the number of available IRQs
0698      *   - Do not take into account the number of online CPUs so that
0699      *     the user can over-subscribe if desired
0700      *   - Tx is additionally limited by the number of hardware queues
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     /* Get current settings based on device state */
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     /* Calculate maximums allowed:
0742      *   - Take into account the number of available IRQs
0743      *   - Do not take into account the number of online CPUs so that
0744      *     the user can over-subscribe if desired
0745      *   - Tx is additionally limited by the number of hardware queues
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     /* Should not be setting other count */
0756     if (channels->other_count) {
0757         netdev_err(netdev,
0758                "other channel count must be zero\n");
0759         return -EINVAL;
0760     }
0761 
0762     /* Require at least one Combined (Rx and Tx) channel */
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     /* Check combined channels */
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     /* Can have some Rx-only or Tx-only channels, but not both */
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     /* Check that we don't exceed the maximum number of channels */
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 }