@@ -3154,6 +3154,66 @@ ice_get_channels(struct net_device *dev, struct ethtool_channels *ch)
ch->tx_count = vsi->num_txq;
}
+/**
+ * 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, and then
+ * clear the previous vsi->rss_lut_user because it is assumed to be invalid at
+ * this point.
+ */
+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 = &pf->pdev->dev;
+ hw = &pf->hw;
+
+ if (!req_rss_size)
+ return -EINVAL;
+
+ lut = devm_kzalloc(dev, 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.sq_last_status);
+ err = -EIO;
+ }
+
+ /* get rid of invalid user configuration */
+ if (vsi->rss_lut_user) {
+ netdev_info(vsi->netdev,
+ "Rx queue count changed, clearing user modified RSS LUT, re-run ethtool [-x|-X] to [check|set] settings if needed\n");
+ devm_kfree(dev, vsi->rss_lut_user);
+ vsi->rss_lut_user = NULL;
+ }
+
+ devm_kfree(dev, lut);
+ return err;
+}
+
/**
* ice_set_channels - set the number channels
* @dev: network interface device structure
@@ -3189,6 +3249,9 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
ice_vsi_recfg_qs(vsi, new_rx, new_tx);
+ if (new_rx)
+ return ice_vsi_set_dflt_rss_lut(vsi, new_rx);
+
return 0;
}