Skip to content

Commit

Permalink
igb: Add ethtool support to configure number of channels
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laura Mihaela Vasilescu authored and David S. Miller committed Oct 1, 2013
1 parent a4e979a commit 907b783
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/igb/igb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
84 changes: 84 additions & 0 deletions drivers/net/ethernet/intel/igb/igb_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
Expand Down
22 changes: 22 additions & 0 deletions drivers/net/ethernet/intel/igb/igb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

0 comments on commit 907b783

Please sign in to comment.