147 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 15static 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 28static 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 47static 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 98clear_reset:99 clear_bit(WX_STATE_RESETTING, wx->state);100 return err;101}102 103static 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 116static 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 143void ngbe_set_ethtool_ops(struct net_device *netdev)144{145 netdev->ethtool_ops = &ngbe_ethtool_ops;146}147