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: Laura Mihaela Vasilescu <laura.vasilescu@rosedu.org>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Laura Mihaela Vasilescu 2013-10-01 04:33:56 -07:00 committed by David S. Miller
parent a4e979a27d
commit 907b783579
3 changed files with 107 additions and 0 deletions

View File

@ -487,6 +487,7 @@ int igb_up(struct igb_adapter *);
void igb_down(struct igb_adapter *);
void igb_reinit_locked(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 *);
int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
int igb_setup_tx_resources(struct igb_ring *);

View File

@ -2874,6 +2874,88 @@ static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
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 = {
.get_settings = igb_get_settings,
.set_settings = igb_set_settings,
@ -2910,6 +2992,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
.get_rxfh_indir_size = igb_get_rxfh_indir_size,
.get_rxfh_indir = igb_get_rxfh_indir,
.set_rxfh_indir = igb_set_rxfh_indir,
.get_channels = igb_get_channels,
.set_channels = igb_set_channels,
.begin = igb_ethtool_begin,
.complete = igb_ethtool_complete,
};

View File

@ -7838,4 +7838,26 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
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 */