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/phy.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 "../libwx/wx_hw.h" 12 #include "ngbe_ethtool.h" 13 #include "ngbe_type.h" 14 15 static void ngbe_get_wol(struct net_device *netdev, 16 struct ethtool_wolinfo *wol) 17 { 18 struct wx *wx = netdev_priv(netdev); 19 20 if (!wx->wol_hw_supported) 21 return; 22 wol->supported = WAKE_MAGIC; 23 wol->wolopts = 0; 24 if (wx->wol & WX_PSR_WKUP_CTL_MAG) 25 wol->wolopts |= WAKE_MAGIC; 26 } 27 28 static int ngbe_set_wol(struct net_device *netdev, 29 struct ethtool_wolinfo *wol) 30 { 31 struct wx *wx = netdev_priv(netdev); 32 struct pci_dev *pdev = wx->pdev; 33 34 if (!wx->wol_hw_supported) 35 return -EOPNOTSUPP; 36 37 wx->wol = 0; 38 if (wol->wolopts & WAKE_MAGIC) 39 wx->wol = WX_PSR_WKUP_CTL_MAG; 40 netdev->ethtool->wol_enabled = !!(wx->wol); 41 wr32(wx, WX_PSR_WKUP_CTL, wx->wol); 42 device_set_wakeup_enable(&pdev->dev, netdev->ethtool->wol_enabled); 43 44 return 0; 45 } 46 47 static int ngbe_set_ringparam(struct net_device *netdev, 48 struct ethtool_ringparam *ring, 49 struct kernel_ethtool_ringparam *kernel_ring, 50 struct netlink_ext_ack *extack) 51 { 52 struct wx *wx = netdev_priv(netdev); 53 u32 new_rx_count, new_tx_count; 54 struct wx_ring *temp_ring; 55 int i, err = 0; 56 57 new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD); 58 new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE); 59 60 new_rx_count = clamp_t(u32, ring->rx_pending, WX_MIN_RXD, WX_MAX_RXD); 61 new_rx_count = ALIGN(new_rx_count, WX_REQ_RX_DESCRIPTOR_MULTIPLE); 62 63 if (new_tx_count == wx->tx_ring_count && 64 new_rx_count == wx->rx_ring_count) 65 return 0; 66 67 err = wx_set_state_reset(wx); 68 if (err) 69 return err; 70 71 if (!netif_running(wx->netdev)) { 72 for (i = 0; i < wx->num_tx_queues; i++) 73 wx->tx_ring[i]->count = new_tx_count; 74 for (i = 0; i < wx->num_rx_queues; i++) 75 wx->rx_ring[i]->count = new_rx_count; 76 wx->tx_ring_count = new_tx_count; 77 wx->rx_ring_count = new_rx_count; 78 79 goto clear_reset; 80 } 81 82 /* allocate temporary buffer to store rings in */ 83 i = max_t(int, wx->num_tx_queues, wx->num_rx_queues); 84 temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL); 85 if (!temp_ring) { 86 err = -ENOMEM; 87 goto clear_reset; 88 } 89 90 ngbe_down(wx); 91 92 wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring); 93 kvfree(temp_ring); 94 95 wx_configure(wx); 96 ngbe_up(wx); 97 98 clear_reset: 99 clear_bit(WX_STATE_RESETTING, wx->state); 100 return err; 101 } 102 103 static int ngbe_set_channels(struct net_device *dev, 104 struct ethtool_channels *ch) 105 { 106 int err; 107 108 err = wx_set_channels(dev, ch); 109 if (err < 0) 110 return err; 111 112 /* use setup TC to update any traffic class queue mapping */ 113 return ngbe_setup_tc(dev, netdev_get_num_tc(dev)); 114 } 115 116 static const struct ethtool_ops ngbe_ethtool_ops = { 117 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 118 ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ, 119 .get_drvinfo = wx_get_drvinfo, 120 .get_link = ethtool_op_get_link, 121 .get_link_ksettings = wx_get_link_ksettings, 122 .set_link_ksettings = wx_set_link_ksettings, 123 .nway_reset = wx_nway_reset, 124 .get_wol = ngbe_get_wol, 125 .set_wol = ngbe_set_wol, 126 .get_sset_count = wx_get_sset_count, 127 .get_strings = wx_get_strings, 128 .get_ethtool_stats = wx_get_ethtool_stats, 129 .get_eth_mac_stats = wx_get_mac_stats, 130 .get_pause_stats = wx_get_pause_stats, 131 .get_pauseparam = wx_get_pauseparam, 132 .set_pauseparam = wx_set_pauseparam, 133 .get_ringparam = wx_get_ringparam, 134 .set_ringparam = ngbe_set_ringparam, 135 .get_coalesce = wx_get_coalesce, 136 .set_coalesce = wx_set_coalesce, 137 .get_channels = wx_get_channels, 138 .set_channels = ngbe_set_channels, 139 .get_msglevel = wx_get_msglevel, 140 .set_msglevel = wx_set_msglevel, 141 }; 142 143 void ngbe_set_ethtool_ops(struct net_device *netdev) 144 { 145 netdev->ethtool_ops = &ngbe_ethtool_ops; 146 } 147