Skip to content

Commit

Permalink
ice: Implement ethtool ops for channels
Browse files Browse the repository at this point in the history
Add code to query and set the number of channels on the primary VSI for a
PF. This is accessed from the 'ethtool -l' and 'ethtool -L' commands,
respectively.  Though the ice driver supports asymmetric queues report an
IRQ vector that has both Rx and Tx queues attached and is counted as a
'combined' channel.

Signed-off-by: Henry Tieman <[email protected]>
Co-developed-by: Maciej Fijalkowski <[email protected]>
Signed-off-by: Maciej Fijalkowski <[email protected]>
Signed-off-by: Tony Nguyen <[email protected]>
Tested-by: Andrew Bowers <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
  • Loading branch information
Henry Tieman authored and Jeff Kirsher committed Nov 22, 2019
1 parent 730fdea commit 87324e7
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 19 deletions.
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ struct ice_vsi {
u16 num_txq; /* Used Tx queues */
u16 alloc_rxq; /* Allocated Rx queues */
u16 num_rxq; /* Used Rx queues */
u16 req_txq; /* User requested Tx queues */
u16 req_rxq; /* User requested Rx queues */
u16 num_rx_desc;
u16 num_tx_desc;
struct ice_tc_cfg tc_cfg;
Expand Down Expand Up @@ -491,6 +493,7 @@ void ice_set_ethtool_ops(struct net_device *netdev);
void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
u16 ice_get_avail_txq_count(struct ice_pf *pf);
u16 ice_get_avail_rxq_count(struct ice_pf *pf);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx);
void ice_update_vsi_stats(struct ice_vsi *vsi);
void ice_update_pf_stats(struct ice_pf *pf);
int ice_up(struct ice_vsi *vsi);
Expand All @@ -505,6 +508,7 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);
int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset);
void ice_print_link_msg(struct ice_vsi *vsi, bool isup);
int ice_open(struct net_device *netdev);
int ice_stop(struct net_device *netdev);
Expand Down
4 changes: 1 addition & 3 deletions drivers/net/ethernet/intel/ice/ice_dcb_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include "ice_dcb_lib.h"
#include "ice_dcb_nl.h"

static void ice_pf_dcb_recfg(struct ice_pf *pf);

/**
* ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration
* @vsi: the VSI being configured
Expand Down Expand Up @@ -535,7 +533,7 @@ static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
* calling this function. Reconfiguring DCB based on
* local_dcbx_cfg.
*/
static void ice_pf_dcb_recfg(struct ice_pf *pf)
void ice_pf_dcb_recfg(struct ice_pf *pf)
{
struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
u8 tc_map = 0;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_dcb_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg);
u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
int
ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);
void ice_pf_dcb_recfg(struct ice_pf *pf);
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
void ice_update_dcb_stats(struct ice_pf *pf);
Expand Down Expand Up @@ -78,6 +79,7 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_ring __always_unused *tx_ring,
}

#define ice_update_dcb_stats(pf) do {} while (0)
#define ice_pf_dcb_recfg(pf) do {} while (0)
#define ice_vsi_cfg_dcb_rings(vsi) do {} while (0)
#define ice_dcb_process_lldp_set_mib_change(pf, event) do {} while (0)
#define ice_set_cgd_num(tlan_ctx, ring) do {} while (0)
Expand Down
185 changes: 185 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -3142,6 +3142,188 @@ ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key,
return 0;
}

/**
* ice_get_max_txq - return the maximum number of Tx queues for in a PF
* @pf: PF structure
*/
static int ice_get_max_txq(struct ice_pf *pf)
{
return min_t(int, num_online_cpus(),
pf->hw.func_caps.common_cap.num_txq);
}

/**
* ice_get_max_rxq - return the maximum number of Rx queues for in a PF
* @pf: PF structure
*/
static int ice_get_max_rxq(struct ice_pf *pf)
{
return min_t(int, num_online_cpus(),
pf->hw.func_caps.common_cap.num_rxq);
}

/**
* ice_get_combined_cnt - return the current number of combined channels
* @vsi: PF VSI pointer
*
* Go through all queue vectors and count ones that have both Rx and Tx ring
* attached
*/
static u32 ice_get_combined_cnt(struct ice_vsi *vsi)
{
u32 combined = 0;
int q_idx;

ice_for_each_q_vector(vsi, q_idx) {
struct ice_q_vector *q_vector = vsi->q_vectors[q_idx];

if (q_vector->rx.ring && q_vector->tx.ring)
combined++;
}

return combined;
}

/**
* ice_get_channels - get the current and max supported channels
* @dev: network interface device structure
* @ch: ethtool channel data structure
*/
static void
ice_get_channels(struct net_device *dev, struct ethtool_channels *ch)
{
struct ice_netdev_priv *np = netdev_priv(dev);
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;

/* check to see if VSI is active */
if (test_bit(__ICE_DOWN, vsi->state))
return;

/* report maximum channels */
ch->max_rx = ice_get_max_rxq(pf);
ch->max_tx = ice_get_max_txq(pf);
ch->max_combined = min_t(int, ch->max_rx, ch->max_tx);

/* report current channels */
ch->combined_count = ice_get_combined_cnt(vsi);
ch->rx_count = vsi->num_rxq - ch->combined_count;
ch->tx_count = vsi->num_txq - ch->combined_count;
}

/**
* ice_vsi_set_dflt_rss_lut - set default RSS LUT with requested RSS size
* @vsi: VSI to reconfigure RSS LUT on
* @req_rss_size: requested range of queue numbers for hashing
*
* Set the VSI's RSS parameters, configure the RSS LUT based on these.
*/
static int ice_vsi_set_dflt_rss_lut(struct ice_vsi *vsi, int req_rss_size)
{
struct ice_pf *pf = vsi->back;
enum ice_status status;
struct device *dev;
struct ice_hw *hw;
int err = 0;
u8 *lut;

dev = ice_pf_to_dev(pf);
hw = &pf->hw;

if (!req_rss_size)
return -EINVAL;

lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
if (!lut)
return -ENOMEM;

/* set RSS LUT parameters */
if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
vsi->rss_size = 1;
} else {
struct ice_hw_common_caps *caps = &hw->func_caps.common_cap;

vsi->rss_size = min_t(int, req_rss_size,
BIT(caps->rss_table_entry_width));
}

/* create/set RSS LUT */
ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size);
status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type, lut,
vsi->rss_table_size);
if (status) {
dev_err(dev, "Cannot set RSS lut, err %d aq_err %d\n",
status, hw->adminq.rq_last_status);
err = -EIO;
}

kfree(lut);
return err;
}

/**
* ice_set_channels - set the number channels
* @dev: network interface device structure
* @ch: ethtool channel data structure
*/
static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
{
struct ice_netdev_priv *np = netdev_priv(dev);
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;
int new_rx = 0, new_tx = 0;
u32 curr_combined;

/* do not support changing channels in Safe Mode */
if (ice_is_safe_mode(pf)) {
netdev_err(dev, "Changing channel in Safe Mode is not supported\n");
return -EOPNOTSUPP;
}
/* do not support changing other_count */
if (ch->other_count)
return -EINVAL;

curr_combined = ice_get_combined_cnt(vsi);

/* these checks are for cases where user didn't specify a particular
* value on cmd line but we get non-zero value anyway via
* get_channels(); look at ethtool.c in ethtool repository (the user
* space part), particularly, do_schannels() routine
*/
if (ch->rx_count == vsi->num_rxq - curr_combined)
ch->rx_count = 0;
if (ch->tx_count == vsi->num_txq - curr_combined)
ch->tx_count = 0;
if (ch->combined_count == curr_combined)
ch->combined_count = 0;

if (!(ch->combined_count || (ch->rx_count && ch->tx_count))) {
netdev_err(dev, "Please specify at least 1 Rx and 1 Tx channel\n");
return -EINVAL;
}

new_rx = ch->combined_count + ch->rx_count;
new_tx = ch->combined_count + ch->tx_count;

if (new_rx > ice_get_max_rxq(pf)) {
netdev_err(dev, "Maximum allowed Rx channels is %d\n",
ice_get_max_rxq(pf));
return -EINVAL;
}
if (new_tx > ice_get_max_txq(pf)) {
netdev_err(dev, "Maximum allowed Tx channels is %d\n",
ice_get_max_txq(pf));
return -EINVAL;
}

ice_vsi_recfg_qs(vsi, new_rx, new_tx);

if (new_rx && !netif_is_rxfh_configured(dev))
return ice_vsi_set_dflt_rss_lut(vsi, new_rx);

return 0;
}

enum ice_container_type {
ICE_RX_CONTAINER,
ICE_TX_CONTAINER,
Expand Down Expand Up @@ -3631,6 +3813,8 @@ static const struct ethtool_ops ice_ethtool_ops = {
.get_rxfh_indir_size = ice_get_rxfh_indir_size,
.get_rxfh = ice_get_rxfh,
.set_rxfh = ice_set_rxfh,
.get_channels = ice_get_channels,
.set_channels = ice_set_channels,
.get_ts_info = ethtool_op_get_ts_info,
.get_per_queue_coalesce = ice_get_per_q_coalesce,
.set_per_queue_coalesce = ice_set_per_q_coalesce,
Expand All @@ -3656,6 +3840,7 @@ static const struct ethtool_ops ice_ethtool_safe_mode_ops = {
.get_ringparam = ice_get_ringparam,
.set_ringparam = ice_set_ringparam,
.nway_reset = ice_nway_reset,
.get_channels = ice_get_channels,
};

/**
Expand Down
Loading

0 comments on commit 87324e7

Please sign in to comment.