Commit 907b7835 authored by Laura Mihaela Vasilescu's avatar Laura Mihaela Vasilescu Committed by David S. Miller

igb: Add ethtool support to configure number of channels

This patch adds the ethtool callbacks necessary to configure the
number of RSS queues.

The maximum number of queues is in accordance with the datasheets.
Signed-off-by: default avatarLaura Mihaela Vasilescu <laura.vasilescu@rosedu.org>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a4e979a2
...@@ -487,6 +487,7 @@ int igb_up(struct igb_adapter *); ...@@ -487,6 +487,7 @@ int igb_up(struct igb_adapter *);
void igb_down(struct igb_adapter *); void igb_down(struct igb_adapter *);
void igb_reinit_locked(struct igb_adapter *); void igb_reinit_locked(struct igb_adapter *);
void igb_reset(struct igb_adapter *); void igb_reset(struct igb_adapter *);
int igb_reinit_queues(struct igb_adapter *);
void igb_write_rss_indir_tbl(struct igb_adapter *); void igb_write_rss_indir_tbl(struct igb_adapter *);
int igb_set_spd_dplx(struct igb_adapter *, u32, u8); int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
int igb_setup_tx_resources(struct igb_ring *); int igb_setup_tx_resources(struct igb_ring *);
......
...@@ -2874,6 +2874,88 @@ static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir) ...@@ -2874,6 +2874,88 @@ static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
return 0; return 0;
} }
static unsigned int igb_max_channels(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
unsigned int max_combined = 0;
switch (hw->mac.type) {
case e1000_i211:
max_combined = IGB_MAX_RX_QUEUES_I211;
break;
case e1000_82575:
case e1000_i210:
max_combined = IGB_MAX_RX_QUEUES_82575;
break;
case e1000_i350:
if (!!adapter->vfs_allocated_count) {
max_combined = 1;
break;
}
/* fall through */
case e1000_82576:
if (!!adapter->vfs_allocated_count) {
max_combined = 2;
break;
}
/* fall through */
case e1000_82580:
case e1000_i354:
default:
max_combined = IGB_MAX_RX_QUEUES;
break;
}
return max_combined;
}
static void igb_get_channels(struct net_device *netdev,
struct ethtool_channels *ch)
{
struct igb_adapter *adapter = netdev_priv(netdev);
/* Report maximum channels */
ch->max_combined = igb_max_channels(adapter);
/* Report info for other vector */
if (adapter->msix_entries) {
ch->max_other = NON_Q_VECTORS;
ch->other_count = NON_Q_VECTORS;
}
ch->combined_count = adapter->rss_queues;
}
static int igb_set_channels(struct net_device *netdev,
struct ethtool_channels *ch)
{
struct igb_adapter *adapter = netdev_priv(netdev);
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 is valid and has not been changed */
if (ch->other_count != NON_Q_VECTORS)
return -EINVAL;
/* Verify the number of channels doesn't exceed hw limits */
if (count > igb_max_channels(adapter))
return -EINVAL;
if (count != adapter->rss_queues) {
adapter->rss_queues = count;
/* Hardware has to reinitialize queues and interrupts to
* match the new configuration.
*/
return igb_reinit_queues(adapter);
}
return 0;
}
static const struct ethtool_ops igb_ethtool_ops = { static const struct ethtool_ops igb_ethtool_ops = {
.get_settings = igb_get_settings, .get_settings = igb_get_settings,
.set_settings = igb_set_settings, .set_settings = igb_set_settings,
...@@ -2910,6 +2992,8 @@ static const struct ethtool_ops igb_ethtool_ops = { ...@@ -2910,6 +2992,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
.get_rxfh_indir_size = igb_get_rxfh_indir_size, .get_rxfh_indir_size = igb_get_rxfh_indir_size,
.get_rxfh_indir = igb_get_rxfh_indir, .get_rxfh_indir = igb_get_rxfh_indir,
.set_rxfh_indir = igb_set_rxfh_indir, .set_rxfh_indir = igb_set_rxfh_indir,
.get_channels = igb_get_channels,
.set_channels = igb_set_channels,
.begin = igb_ethtool_begin, .begin = igb_ethtool_begin,
.complete = igb_ethtool_complete, .complete = igb_ethtool_complete,
}; };
......
...@@ -7838,4 +7838,26 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, ...@@ -7838,4 +7838,26 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
return E1000_SUCCESS; return E1000_SUCCESS;
} }
int igb_reinit_queues(struct igb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
int err = 0;
if (netif_running(netdev))
igb_close(netdev);
igb_clear_interrupt_scheme(adapter);
if (igb_init_interrupt_scheme(adapter, true)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
return -ENOMEM;
}
if (netif_running(netdev))
err = igb_open(netdev);
return err;
}
/* igb_main.c */ /* igb_main.c */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment