|
@@ -2802,6 +2802,43 @@ static void ixgbe_get_channels(struct net_device *dev,
|
|
|
ch->combined_count = adapter->ring_feature[RING_F_FDIR].indices;
|
|
|
}
|
|
|
|
|
|
+static int ixgbe_set_channels(struct net_device *dev,
|
|
|
+ struct ethtool_channels *ch)
|
|
|
+{
|
|
|
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
|
|
|
+ unsigned int count = ch->combined_count;
|
|
|
+
|
|
|
+ /* verify they are not requesting separate vectors */
|
|
|
+ if (!count || ch->rx_count || ch->tx_count)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /* verify other_count has not changed */
|
|
|
+ if (ch->other_count != NON_Q_VECTORS)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /* verify the number of channels does not exceed hardware limits */
|
|
|
+ if (count > ixgbe_max_channels(adapter))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /* update feature limits from largest to smallest supported values */
|
|
|
+ adapter->ring_feature[RING_F_FDIR].limit = count;
|
|
|
+
|
|
|
+ /* cap RSS limit at 16 */
|
|
|
+ if (count > IXGBE_MAX_RSS_INDICES)
|
|
|
+ count = IXGBE_MAX_RSS_INDICES;
|
|
|
+ adapter->ring_feature[RING_F_RSS].limit = count;
|
|
|
+
|
|
|
+#ifdef IXGBE_FCOE
|
|
|
+ /* cap FCoE limit at 8 */
|
|
|
+ if (count > IXGBE_FCRETA_SIZE)
|
|
|
+ count = IXGBE_FCRETA_SIZE;
|
|
|
+ adapter->ring_feature[RING_F_FCOE].limit = count;
|
|
|
+
|
|
|
+#endif
|
|
|
+ /* use setup TC to update any traffic class queue mapping */
|
|
|
+ return ixgbe_setup_tc(dev, netdev_get_num_tc(dev));
|
|
|
+}
|
|
|
+
|
|
|
static const struct ethtool_ops ixgbe_ethtool_ops = {
|
|
|
.get_settings = ixgbe_get_settings,
|
|
|
.set_settings = ixgbe_set_settings,
|
|
@@ -2831,6 +2868,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
|
|
|
.get_rxnfc = ixgbe_get_rxnfc,
|
|
|
.set_rxnfc = ixgbe_set_rxnfc,
|
|
|
.get_channels = ixgbe_get_channels,
|
|
|
+ .set_channels = ixgbe_set_channels,
|
|
|
.get_ts_info = ixgbe_get_ts_info,
|
|
|
};
|
|
|
|