1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ 3 4 #include <linux/pci.h> 5 #include <linux/phylink.h> 6 #include <linux/netdevice.h> 7 8 #include "../libwx/wx_ethtool.h" 9 #include "../libwx/wx_type.h" 10 #include "../libwx/wx_lib.h" 11 #include "txgbe_type.h" 12 #include "txgbe_ethtool.h" 13 14 static int txgbe_set_ringparam(struct net_device *netdev, 15 struct ethtool_ringparam *ring, 16 struct kernel_ethtool_ringparam *kernel_ring, 17 struct netlink_ext_ack *extack) 18 { 19 struct wx *wx = netdev_priv(netdev); 20 u32 new_rx_count, new_tx_count; 21 struct wx_ring *temp_ring; 22 int i; 23 24 new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD); 25 new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE); 26 27 new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD); 28 new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE); 29 30 if (new_tx_count == wx->tx_ring_count && 31 new_rx_count == wx->rx_ring_count) 32 return 0; 33 34 if (!netif_running(wx->netdev)) { 35 for (i = 0; i < wx->num_tx_queues; i++) 36 wx->tx_ring[i]->count = new_tx_count; 37 for (i = 0; i < wx->num_rx_queues; i++) 38 wx->rx_ring[i]->count = new_rx_count; 39 wx->tx_ring_count = new_tx_count; 40 wx->rx_ring_count = new_rx_count; 41 42 return 0; 43 } 44 45 /* allocate temporary buffer to store rings in */ 46 i = max_t(int, wx->num_tx_queues, wx->num_rx_queues); 47 temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL); 48 if (!temp_ring) 49 return -ENOMEM; 50 51 txgbe_down(wx); 52 53 wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring); 54 kvfree(temp_ring); 55 56 txgbe_up(wx); 57 58 return 0; 59 } 60 61 static int txgbe_set_channels(struct net_device *dev, 62 struct ethtool_channels *ch) 63 { 64 int err; 65 66 err = wx_set_channels(dev, ch); 67 if (err < 0) 68 return err; 69 70 /* use setup TC to update any traffic class queue mapping */ 71 return txgbe_setup_tc(dev, netdev_get_num_tc(dev)); 72 } 73 74 static const struct ethtool_ops txgbe_ethtool_ops = { 75 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 76 ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ, 77 .get_drvinfo = wx_get_drvinfo, 78 .nway_reset = wx_nway_reset, 79 .get_link = ethtool_op_get_link, 80 .get_link_ksettings = wx_get_link_ksettings, 81 .set_link_ksettings = wx_set_link_ksettings, 82 .get_sset_count = wx_get_sset_count, 83 .get_strings = wx_get_strings, 84 .get_ethtool_stats = wx_get_ethtool_stats, 85 .get_eth_mac_stats = wx_get_mac_stats, 86 .get_pause_stats = wx_get_pause_stats, 87 .get_pauseparam = wx_get_pauseparam, 88 .set_pauseparam = wx_set_pauseparam, 89 .get_ringparam = wx_get_ringparam, 90 .set_ringparam = txgbe_set_ringparam, 91 .get_coalesce = wx_get_coalesce, 92 .set_coalesce = wx_set_coalesce, 93 .get_channels = wx_get_channels, 94 .set_channels = txgbe_set_channels, 95 .get_msglevel = wx_get_msglevel, 96 .set_msglevel = wx_set_msglevel, 97 }; 98 99 void txgbe_set_ethtool_ops(struct net_device *netdev) 100 { 101 netdev->ethtool_ops = &txgbe_ethtool_ops; 102 } 103