@@ -2073,7 +2073,7 @@ static int bnx2x_init_rss(struct bnx2x *bp)
* For 57712 and newer on the other hand it's a per-function
* configuration.
*/
- return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp));
+ return bnx2x_config_rss_eth(bp);
}
int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
@@ -2122,11 +2122,8 @@ int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
memcpy(params.ind_table, rss_obj->ind_table, sizeof(params.ind_table));
- if (config_hash) {
- /* RSS keys */
- netdev_rss_key_fill(params.rss_key, T_ETH_RSS_KEY * 4);
+ if (config_hash)
__set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags);
- }
if (IS_PF(bp))
return bnx2x_config_rss(bp, ¶ms);
@@ -913,8 +913,10 @@ static inline int func_by_vn(struct bnx2x *bp, int vn)
return 2 * vn + BP_PORT(bp);
}
-static inline int bnx2x_config_rss_eth(struct bnx2x *bp, bool config_hash)
+static inline int bnx2x_config_rss_eth(struct bnx2x *bp)
{
+ bool config_hash = bp->port.pmf || !CHIP_IS_E1x(bp);
+
return bnx2x_rss(bp, &bp->rss_conf_obj, config_hash, true);
}
@@ -3419,6 +3419,11 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
return T_ETH_INDIRECTION_TABLE_SIZE;
}
+static u32 bnx2x_get_rxfh_key_size(struct net_device *dev)
+{
+ return T_ETH_RSS_KEY * 4;
+}
+
static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
u8 *hfunc)
{
@@ -3428,24 +3433,25 @@ static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
- if (!indir)
- return 0;
+ if (indir) {
- /* Get the current configuration of the RSS indirection table */
- bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
-
- /*
- * We can't use a memcpy() as an internal storage of an
- * indirection table is a u8 array while indir->ring_index
- * points to an array of u32.
- *
- * Indirection table contains the FW Client IDs, so we need to
- * align the returned table to the Client ID of the leading RSS
- * queue.
- */
- for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
- indir[i] = ind_table[i] - bp->fp->cl_id;
+ /* Get the current configuration of the RSS indirection table */
+ bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
+ /*
+ * We can't use a memcpy() as an internal storage of an
+ * indirection table is a u8 array while indir->ring_index
+ * points to an array of u32.
+ *
+ * Indirection table contains the FW Client IDs, so we need to
+ * align the returned table to the Client ID of the leading RSS
+ * queue.
+ */
+ for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++)
+ indir[i] = ind_table[i] - bp->fp->cl_id;
+ }
+ if (key)
+ memcpy(key, bp->rss_conf_obj.rss_key, T_ETH_RSS_KEY * 4);
return 0;
}
@@ -3453,32 +3459,34 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct bnx2x *bp = netdev_priv(dev);
- size_t i;
/* 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 (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
- if (!indir)
- return 0;
-
- for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
- /*
- * The same as in bnx2x_get_rxfh: we can't use a memcpy()
- * as an internal storage of an indirection table is a u8 array
- * while indir->ring_index points to an array of u32.
- *
- * Indirection table contains the FW Client IDs, so we need to
- * 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;
+ if (indir) {
+ size_t i;
+
+ for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+ /*
+ * The same as in bnx2x_get_rxfh: we can't use a memcpy()
+ * as an internal storage of an indirection table is a u8 array
+ * while indir->ring_index points to an array of u32.
+ *
+ * Indirection table contains the FW Client IDs, so we need to
+ * 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;
+ }
}
- return bnx2x_config_rss_eth(bp, false);
+ if (key)
+ memcpy(bp->rss_conf_obj.rss_key, key, T_ETH_RSS_KEY * 4);
+
+ return bnx2x_config_rss_eth(bp);
}
/**
@@ -3627,6 +3635,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
.get_rxnfc = bnx2x_get_rxnfc,
.set_rxnfc = bnx2x_set_rxnfc,
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
+ .get_rxfh_key_size = bnx2x_get_rxfh_key_size,
.get_rxfh = bnx2x_get_rxfh,
.set_rxfh = bnx2x_set_rxfh,
.get_channels = bnx2x_get_channels,
@@ -4319,8 +4319,14 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
/* RSS keys */
if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
- memcpy(&data->rss_key[0], &p->rss_key[0],
- sizeof(data->rss_key));
+ u8 *dst = (u8 *)(data->rss_key) + sizeof(data->rss_key);
+ const u8 *src = (const u8 *)bp->rss_conf_obj.rss_key;
+ int i;
+
+ /* Apparently, bnx2x reads this array in reverse order */
+ for (i = 0; i < sizeof(data->rss_key); i++)
+ *--dst = *src++;
+
caps |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
}
@@ -4408,6 +4414,7 @@ void bnx2x_init_rss_config_obj(struct bnx2x *bp,
bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
rdata_mapping, state, pstate, type);
+ netdev_rss_key_fill(rss_obj->rss_key, sizeof(rss_obj->rss_key));
rss_obj->engine_id = engine_id;
rss_obj->config_rss = bnx2x_setup_rss;
}
@@ -734,8 +734,6 @@ struct bnx2x_config_rss_params {
/* Indirection table */
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
- /* RSS hash values */
- u32 rss_key[10];
/* valid only iff BNX2X_RSS_UPDATE_TOE is set */
u16 toe_rss_bitmap;
@@ -754,6 +752,9 @@ struct bnx2x_rss_config_obj {
u8 udp_rss_v4;
u8 udp_rss_v6;
+ /* RSS hash values */
+ u32 rss_key[T_ETH_RSS_KEY];
+
int (*config_rss)(struct bnx2x *bp,
struct bnx2x_config_rss_params *p);
};