Skip to content

Commit

Permalink
Merge branch 'net-wangxun-more-ethtool'
Browse files Browse the repository at this point in the history
Jiawen Wu says:

====================
Implement more ethtool_ops for Wangxun

Provide ethtool functions to operate pause param, ring param, coalesce
channel number and msglevel, for driver txgbe/ngbe.

v6 -> v7:
- Rebase on net-next.

v5 -> v6:
- Minor fixes address on Jakub Kicinski's comments.

v4 -> v5:
- Fix build error reported by kernel test robot.

v3 -> v4:
- Repartition the patches of phylink.
- Handle failure to allocate memory while changing ring parameters.
- Minor fixes about formatting.

v2 -> v3:
- Address comments:
  https://lore.kernel.org/all/ZW2loxTO6oKNYLew@shell.armlinux.org.uk/

v1 -> v2:
- Add phylink support for ngbe.
- Fix issue on interrupts when queue number is changed.
- Add more marco defines.
- Fix return codes.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 4, 2024
2 parents 5403d39 + b746dc6 commit 168882d
Show file tree
Hide file tree
Showing 16 changed files with 1,110 additions and 185 deletions.
236 changes: 236 additions & 0 deletions drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "wx_type.h"
#include "wx_ethtool.h"
#include "wx_hw.h"
#include "wx_lib.h"

struct wx_stats {
char stat_string[ETH_GSTRING_LEN];
Expand Down Expand Up @@ -185,3 +186,238 @@ void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
}
}
EXPORT_SYMBOL(wx_get_drvinfo);

int wx_nway_reset(struct net_device *netdev)
{
struct wx *wx = netdev_priv(netdev);

return phylink_ethtool_nway_reset(wx->phylink);
}
EXPORT_SYMBOL(wx_nway_reset);

int wx_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
struct wx *wx = netdev_priv(netdev);

return phylink_ethtool_ksettings_get(wx->phylink, cmd);
}
EXPORT_SYMBOL(wx_get_link_ksettings);

int wx_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
struct wx *wx = netdev_priv(netdev);

return phylink_ethtool_ksettings_set(wx->phylink, cmd);
}
EXPORT_SYMBOL(wx_set_link_ksettings);

void wx_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct wx *wx = netdev_priv(netdev);

phylink_ethtool_get_pauseparam(wx->phylink, pause);
}
EXPORT_SYMBOL(wx_get_pauseparam);

int wx_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct wx *wx = netdev_priv(netdev);

return phylink_ethtool_set_pauseparam(wx->phylink, pause);
}
EXPORT_SYMBOL(wx_set_pauseparam);

void wx_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);

ring->rx_max_pending = WX_MAX_RXD;
ring->tx_max_pending = WX_MAX_TXD;
ring->rx_mini_max_pending = 0;
ring->rx_jumbo_max_pending = 0;
ring->rx_pending = wx->rx_ring_count;
ring->tx_pending = wx->tx_ring_count;
ring->rx_mini_pending = 0;
ring->rx_jumbo_pending = 0;
}
EXPORT_SYMBOL(wx_get_ringparam);

int wx_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);

ec->tx_max_coalesced_frames_irq = wx->tx_work_limit;
/* only valid if in constant ITR mode */
if (wx->rx_itr_setting <= 1)
ec->rx_coalesce_usecs = wx->rx_itr_setting;
else
ec->rx_coalesce_usecs = wx->rx_itr_setting >> 2;

/* if in mixed tx/rx queues per vector mode, report only rx settings */
if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
return 0;

/* only valid if in constant ITR mode */
if (wx->tx_itr_setting <= 1)
ec->tx_coalesce_usecs = wx->tx_itr_setting;
else
ec->tx_coalesce_usecs = wx->tx_itr_setting >> 2;

return 0;
}
EXPORT_SYMBOL(wx_get_coalesce);

int wx_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);
u16 tx_itr_param, rx_itr_param;
struct wx_q_vector *q_vector;
u16 max_eitr;
int i;

if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count) {
/* reject Tx specific changes in case of mixed RxTx vectors */
if (ec->tx_coalesce_usecs)
return -EOPNOTSUPP;
}

if (ec->tx_max_coalesced_frames_irq)
wx->tx_work_limit = ec->tx_max_coalesced_frames_irq;

if (wx->mac.type == wx_mac_sp)
max_eitr = WX_SP_MAX_EITR;
else
max_eitr = WX_EM_MAX_EITR;

if ((ec->rx_coalesce_usecs > (max_eitr >> 2)) ||
(ec->tx_coalesce_usecs > (max_eitr >> 2)))
return -EINVAL;

if (ec->rx_coalesce_usecs > 1)
wx->rx_itr_setting = ec->rx_coalesce_usecs << 2;
else
wx->rx_itr_setting = ec->rx_coalesce_usecs;

if (wx->rx_itr_setting == 1)
rx_itr_param = WX_20K_ITR;
else
rx_itr_param = wx->rx_itr_setting;

if (ec->tx_coalesce_usecs > 1)
wx->tx_itr_setting = ec->tx_coalesce_usecs << 2;
else
wx->tx_itr_setting = ec->tx_coalesce_usecs;

if (wx->tx_itr_setting == 1) {
if (wx->mac.type == wx_mac_sp)
tx_itr_param = WX_12K_ITR;
else
tx_itr_param = WX_20K_ITR;
} else {
tx_itr_param = wx->tx_itr_setting;
}

/* mixed Rx/Tx */
if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
wx->tx_itr_setting = wx->rx_itr_setting;

for (i = 0; i < wx->num_q_vectors; i++) {
q_vector = wx->q_vector[i];
if (q_vector->tx.count && !q_vector->rx.count)
/* tx only */
q_vector->itr = tx_itr_param;
else
/* rx only or mixed */
q_vector->itr = rx_itr_param;
wx_write_eitr(q_vector);
}

return 0;
}
EXPORT_SYMBOL(wx_set_coalesce);

static unsigned int wx_max_channels(struct wx *wx)
{
unsigned int max_combined;

if (!wx->msix_q_entries) {
/* We only support one q_vector without MSI-X */
max_combined = 1;
} else {
/* support up to max allowed queues with RSS */
if (wx->mac.type == wx_mac_sp)
max_combined = 63;
else
max_combined = 8;
}

return max_combined;
}

void wx_get_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
struct wx *wx = netdev_priv(dev);

/* report maximum channels */
ch->max_combined = wx_max_channels(wx);

/* report info for other vector */
if (wx->msix_q_entries) {
ch->max_other = 1;
ch->other_count = 1;
}

/* record RSS queues */
ch->combined_count = wx->ring_feature[RING_F_RSS].indices;
}
EXPORT_SYMBOL(wx_get_channels);

int wx_set_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
unsigned int count = ch->combined_count;
struct wx *wx = netdev_priv(dev);

/* verify other_count has not changed */
if (ch->other_count != 1)
return -EINVAL;

/* verify the number of channels does not exceed hardware limits */
if (count > wx_max_channels(wx))
return -EINVAL;

wx->ring_feature[RING_F_RSS].limit = count;

return 0;
}
EXPORT_SYMBOL(wx_set_channels);

u32 wx_get_msglevel(struct net_device *netdev)
{
struct wx *wx = netdev_priv(netdev);

return wx->msg_enable;
}
EXPORT_SYMBOL(wx_get_msglevel);

void wx_set_msglevel(struct net_device *netdev, u32 data)
{
struct wx *wx = netdev_priv(netdev);

wx->msg_enable = data;
}
EXPORT_SYMBOL(wx_set_msglevel);
27 changes: 27 additions & 0 deletions drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,31 @@ void wx_get_mac_stats(struct net_device *netdev,
void wx_get_pause_stats(struct net_device *netdev,
struct ethtool_pause_stats *stats);
void wx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info);
int wx_nway_reset(struct net_device *netdev);
int wx_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd);
int wx_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd);
void wx_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause);
int wx_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause);
void wx_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack);
int wx_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack);
int wx_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack);
void wx_get_channels(struct net_device *dev,
struct ethtool_channels *ch);
int wx_set_channels(struct net_device *dev,
struct ethtool_channels *ch);
u32 wx_get_msglevel(struct net_device *netdev);
void wx_set_msglevel(struct net_device *netdev, u32 data);
#endif /* _WX_ETHTOOL_H_ */
Loading

0 comments on commit 168882d

Please sign in to comment.