Commit fb6e30a7 authored by Ahmed Zaki's avatar Ahmed Zaki Committed by Jakub Kicinski
Browse files

net: ethtool: pass a pointer to parameters to get/set_rxfh ethtool ops

The get/set_rxfh ethtool ops currently takes the rxfh (RSS) parameters
as direct function arguments. This will force us to change the API (and
all drivers' functions) every time some new parameters are added.

This is part 1/2 of the fix, as suggested in [1]:

- First simplify the code by always providing a pointer to all params
   (indir, key and func); the fact that some of them may be NULL seems
   like a weird historic thing or a premature optimization.
   It will simplify the drivers if all pointers are always present.

 - Then make the functions take a dev pointer, and a pointer to a
   single struct wrapping all arguments. The set_* should also take
   an extack.

Link: https://lore.kernel.org/netdev/20231121152906.2dd5f487@kernel.org/

 [1]
Suggested-by: default avatarJakub Kicinski <kuba@kernel.org>
Suggested-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarAhmed Zaki <ahmed.zaki@intel.com>
Link: https://lore.kernel.org/r/20231213003321.605376-2-ahmed.zaki@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c3f687d8
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -802,15 +802,15 @@ static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir)
	return rc;
}

static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
			u8 *hfunc)
static int ena_get_rxfh(struct net_device *netdev,
			struct ethtool_rxfh_param *rxfh)
{
	struct ena_adapter *adapter = netdev_priv(netdev);
	enum ena_admin_hash_functions ena_func;
	u8 func;
	int rc;

	rc = ena_indirection_table_get(adapter, indir);
	rc = ena_indirection_table_get(adapter, rxfh->indir);
	if (rc)
		return rc;

@@ -825,7 +825,7 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
		return rc;
	}

	rc = ena_com_get_hash_key(adapter->ena_dev, key);
	rc = ena_com_get_hash_key(adapter->ena_dev, rxfh->key);
	if (rc)
		return rc;

@@ -842,27 +842,27 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
		return -EOPNOTSUPP;
	}

	if (hfunc)
		*hfunc = func;
	rxfh->hfunc = func;

	return 0;
}

static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
			const u8 *key, const u8 hfunc)
static int ena_set_rxfh(struct net_device *netdev,
			struct ethtool_rxfh_param *rxfh,
			struct netlink_ext_ack *extack)
{
	struct ena_adapter *adapter = netdev_priv(netdev);
	struct ena_com_dev *ena_dev = adapter->ena_dev;
	enum ena_admin_hash_functions func = 0;
	int rc;

	if (indir) {
		rc = ena_indirection_table_set(adapter, indir);
	if (rxfh->indir) {
		rc = ena_indirection_table_set(adapter, rxfh->indir);
		if (rc)
			return rc;
	}

	switch (hfunc) {
	switch (rxfh->hfunc) {
	case ETH_RSS_HASH_NO_CHANGE:
		func = ena_com_get_current_hash_function(ena_dev);
		break;
@@ -874,12 +874,12 @@ static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
		break;
	default:
		netif_err(adapter, drv, netdev, "Unsupported hfunc %d\n",
			  hfunc);
			  rxfh->hfunc);
		return -EOPNOTSUPP;
	}

	if (key || func) {
		rc = ena_com_fill_hash_function(ena_dev, func, key,
	if (rxfh->key || func) {
		rc = ena_com_fill_hash_function(ena_dev, func, rxfh->key,
						ENA_HASH_KEY_SIZE,
						0xFFFFFFFF);
		if (unlikely(rc)) {
+17 −16
Original line number Diff line number Diff line
@@ -527,47 +527,48 @@ static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev)
	return ARRAY_SIZE(pdata->rss_table);
}

static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
			 u8 *hfunc)
static int xgbe_get_rxfh(struct net_device *netdev,
			 struct ethtool_rxfh_param *rxfh)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	unsigned int i;

	if (indir) {
	if (rxfh->indir) {
		for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++)
			indir[i] = XGMAC_GET_BITS(pdata->rss_table[i],
			rxfh->indir[i] = XGMAC_GET_BITS(pdata->rss_table[i],
							MAC_RSSDR, DMCH);
	}

	if (key)
		memcpy(key, pdata->rss_key, sizeof(pdata->rss_key));
	if (rxfh->key)
		memcpy(rxfh->key, pdata->rss_key, sizeof(pdata->rss_key));

	if (hfunc)
		*hfunc = ETH_RSS_HASH_TOP;
	rxfh->hfunc = ETH_RSS_HASH_TOP;

	return 0;
}

static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
			 const u8 *key, const u8 hfunc)
static int xgbe_set_rxfh(struct net_device *netdev,
			 struct ethtool_rxfh_param *rxfh,
			 struct netlink_ext_ack *extack)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	struct xgbe_hw_if *hw_if = &pdata->hw_if;
	unsigned int ret;

	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
	    rxfh->hfunc != ETH_RSS_HASH_TOP) {
		netdev_err(netdev, "unsupported hash function\n");
		return -EOPNOTSUPP;
	}

	if (indir) {
		ret = hw_if->set_rss_lookup_table(pdata, indir);
	if (rxfh->indir) {
		ret = hw_if->set_rss_lookup_table(pdata, rxfh->indir);
		if (ret)
			return ret;
	}

	if (key) {
		ret = hw_if->set_rss_hash_key(pdata, key);
	if (rxfh->key) {
		ret = hw_if->set_rss_hash_key(pdata, rxfh->key);
		if (ret)
			return ret;
	}
+16 −15
Original line number Diff line number Diff line
@@ -447,8 +447,8 @@ static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
	return sizeof(cfg->aq_rss.hash_secret_key);
}

static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
			      u8 *hfunc)
static int aq_ethtool_get_rss(struct net_device *ndev,
			      struct ethtool_rxfh_param *rxfh)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_cfg_s *cfg;
@@ -456,21 +456,21 @@ static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,

	cfg = aq_nic_get_cfg(aq_nic);

	if (hfunc)
		*hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
	if (indir) {
	rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
	if (rxfh->indir) {
		for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
			indir[i] = cfg->aq_rss.indirection_table[i];
			rxfh->indir[i] = cfg->aq_rss.indirection_table[i];
	}
	if (key)
		memcpy(key, cfg->aq_rss.hash_secret_key,
	if (rxfh->key)
		memcpy(rxfh->key, cfg->aq_rss.hash_secret_key,
		       sizeof(cfg->aq_rss.hash_secret_key));

	return 0;
}

static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
			      const u8 *key, const u8 hfunc)
static int aq_ethtool_set_rss(struct net_device *netdev,
			      struct ethtool_rxfh_param *rxfh,
			      struct netlink_ext_ack *extack)
{
	struct aq_nic_s *aq_nic = netdev_priv(netdev);
	struct aq_nic_cfg_s *cfg;
@@ -482,16 +482,17 @@ static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
	rss_entries = cfg->aq_rss.indirection_table_size;

	/* We do not allow change in unsupported parameters */
	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
	    rxfh->hfunc != ETH_RSS_HASH_TOP)
		return -EOPNOTSUPP;
	/* Fill out the redirection table */
	if (indir)
	if (rxfh->indir)
		for (i = 0; i < rss_entries; i++)
			cfg->aq_rss.indirection_table[i] = indir[i];
			cfg->aq_rss.indirection_table[i] = rxfh->indir[i];

	/* Fill out the rss hash key */
	if (key) {
		memcpy(cfg->aq_rss.hash_secret_key, key,
	if (rxfh->key) {
		memcpy(cfg->aq_rss.hash_secret_key, rxfh->key,
		       sizeof(cfg->aq_rss.hash_secret_key));
		err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
			&cfg->aq_rss);
+13 −12
Original line number Diff line number Diff line
@@ -3486,16 +3486,15 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
	return T_ETH_INDIRECTION_TABLE_SIZE;
}

static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
			  u8 *hfunc)
static int bnx2x_get_rxfh(struct net_device *dev,
			  struct ethtool_rxfh_param *rxfh)
{
	struct bnx2x *bp = netdev_priv(dev);
	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
	size_t i;

	if (hfunc)
		*hfunc = ETH_RSS_HASH_TOP;
	if (!indir)
	rxfh->hfunc = ETH_RSS_HASH_TOP;
	if (!rxfh->indir)
		return 0;

	/* Get the current configuration of the RSS indirection table */
@@ -3511,13 +3510,14 @@ static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
	 * queue.
	 */
	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
		indir[i] = ind_table[i] - bp->fp->cl_id;
		rxfh->indir[i] = ind_table[i] - bp->fp->cl_id;

	return 0;
}

static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
			  const u8 *key, const u8 hfunc)
static int bnx2x_set_rxfh(struct net_device *dev,
			  struct ethtool_rxfh_param *rxfh,
			  struct netlink_ext_ack *extack)
{
	struct bnx2x *bp = netdev_priv(dev);
	size_t i;
@@ -3525,11 +3525,12 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
	/* We require at least one supported parameter to be changed and no
	 * change in any of the unsupported parameters
	 */
	if (key ||
	    (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
	if (rxfh->key ||
	    (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
	     rxfh->hfunc != ETH_RSS_HASH_TOP))
		return -EOPNOTSUPP;

	if (!indir)
	if (!rxfh->indir)
		return 0;

	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
@@ -3542,7 +3543,7 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
		 * align the received table to the Client ID of the leading RSS
		 * queue
		 */
		bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id;
		bp->rss_conf_obj.ind_table[i] = rxfh->indir[i] + bp->fp->cl_id;
	}

	if (bp->state == BNX2X_STATE_OPEN)
+14 −14
Original line number Diff line number Diff line
@@ -1333,49 +1333,49 @@ static u32 bnxt_get_rxfh_key_size(struct net_device *dev)
	return HW_HASH_KEY_SIZE;
}

static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
			 u8 *hfunc)
static int bnxt_get_rxfh(struct net_device *dev,
			 struct ethtool_rxfh_param *rxfh)
{
	struct bnxt *bp = netdev_priv(dev);
	struct bnxt_vnic_info *vnic;
	u32 i, tbl_size;

	if (hfunc)
		*hfunc = ETH_RSS_HASH_TOP;
	rxfh->hfunc = ETH_RSS_HASH_TOP;

	if (!bp->vnic_info)
		return 0;

	vnic = &bp->vnic_info[0];
	if (indir && bp->rss_indir_tbl) {
	if (rxfh->indir && bp->rss_indir_tbl) {
		tbl_size = bnxt_get_rxfh_indir_size(dev);
		for (i = 0; i < tbl_size; i++)
			indir[i] = bp->rss_indir_tbl[i];
			rxfh->indir[i] = bp->rss_indir_tbl[i];
	}

	if (key && vnic->rss_hash_key)
		memcpy(key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);
	if (rxfh->key && vnic->rss_hash_key)
		memcpy(rxfh->key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);

	return 0;
}

static int bnxt_set_rxfh(struct net_device *dev, const u32 *indir,
			 const u8 *key, const u8 hfunc)
static int bnxt_set_rxfh(struct net_device *dev,
			 struct ethtool_rxfh_param *rxfh,
			 struct netlink_ext_ack *extack)
{
	struct bnxt *bp = netdev_priv(dev);
	int rc = 0;

	if (hfunc && hfunc != ETH_RSS_HASH_TOP)
	if (rxfh->hfunc && rxfh->hfunc != ETH_RSS_HASH_TOP)
		return -EOPNOTSUPP;

	if (key)
	if (rxfh->key)
		return -EOPNOTSUPP;

	if (indir) {
	if (rxfh->indir) {
		u32 i, pad, tbl_size = bnxt_get_rxfh_indir_size(dev);

		for (i = 0; i < tbl_size; i++)
			bp->rss_indir_tbl[i] = indir[i];
			bp->rss_indir_tbl[i] = rxfh->indir[i];
		pad = bp->rss_indir_tbl_entries - tbl_size;
		if (pad)
			memset(&bp->rss_indir_tbl[i], 0, pad * sizeof(u16));
Loading