[PATCH net-next 1/2] igb: Remove unnecessary flag setting in igb_set_flag_queue_pairs()

2015-12-11 Thread Shota Suzuki
If VFs are enabled (max_vfs >= 1), both max_rss_queues and
adapter->rss_queues are set to 2 in the case of e1000_82576.
In this case, IGB_FLAG_QUEUE_PAIRS is always set in the default block as a
result of fall-through, thus setting it in the e1000_82576 block is not
necessary.

Signed-off-by: Shota Suzuki 
---
 drivers/net/ethernet/intel/igb/igb_main.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_main.c 
b/drivers/net/ethernet/intel/igb/igb_main.c
index 3d4b502..340ba4fb 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2922,14 +2922,6 @@ void igb_set_flag_queue_pairs(struct igb_adapter 
*adapter,
/* Device supports enough interrupts without queue pairing. */
break;
case e1000_82576:
-   /* If VFs are going to be allocated with RSS queues then we
-* should pair the queues in order to conserve interrupts due
-* to limited supply.
-*/
-   if ((adapter->rss_queues > 1) &&
-   (adapter->vfs_allocated_count > 6))
-   adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
-   /* fall through */
case e1000_82580:
case e1000_i350:
case e1000_i354:
-- 
1.8.3.1



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH net-next 2/2] igb: Unpair the queues when changing the number of queues

2015-12-11 Thread Shota Suzuki
By the commit 72ddef0506da ("igb: Fix oops caused by missing queue
pairing"), the IGB_FLAG_QUEUE_PAIRS flag can now be set when changing the
number of queues by "ethtool -L", but it is never cleared unless the igb
driver is reloaded.
This patch clears it if queue pairing becomes unnecessary as a result of
"ethtool -L".

Signed-off-by: Shota Suzuki 
---
 drivers/net/ethernet/intel/igb/igb_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/intel/igb/igb_main.c 
b/drivers/net/ethernet/intel/igb/igb_main.c
index 340ba4fb..75ee25e 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2932,6 +2932,8 @@ void igb_set_flag_queue_pairs(struct igb_adapter *adapter,
 */
if (adapter->rss_queues > (max_rss_queues / 2))
adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
+   else
+   adapter->flags &= ~IGB_FLAG_QUEUE_PAIRS;
break;
}
 }
-- 
1.8.3.1



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH net] igb: Fix oops caused by missing queue pairing

2015-06-30 Thread Shota Suzuki
When initializing igb driver (e.g. 82576, I350), IGB_FLAG_QUEUE_PAIRS is
set if adapter->rss_queues exceeds half of max_rss_queues in
igb_init_queue_configuration().
On the other hand, IGB_FLAG_QUEUE_PAIRS is not set even if the number of
queues exceeds half of max_combined in igb_set_channels() when changing
the number of queues by "ethtool -L".
In this case, if numvecs is larger than MAX_MSIX_ENTRIES (10), the size
of adapter->msix_entries[], an overflow can occur in
igb_set_interrupt_capability(), which in turn leads to an oops.

Fix this problem as follows:
 - When changing the number of queues by "ethtool -L", set
   IGB_FLAG_QUEUE_PAIRS in the same way as initializing igb driver.
 - When increasing the size of q_vector, reallocate it appropriately.
   (With IGB_FLAG_QUEUE_PAIRS set, the size of q_vector gets larger.)

Another possible way to fix this problem is to cap the queues at its
initial number, which is the number of the initial online cpus. But this
is not the optimal way because we cannnot increase queues when another
cpu becomes online.

Note that before commit cd14ef54d25b ("igb: Change to use statically
allocated array for MSIx entries"), this problem did not cause oops
but just made the number of queues become 1 because of entering msi_only
mode in igb_set_interrupt_capability().

Fixes: 907b7835799f ("igb: Add ethtool support to configure number of channels")
Signed-off-by: Shota Suzuki 
---
Although we might be able to additionally unset IGB_FLAG_QUEUE_PAIRS
when it is not needed, this patch doesn't change existing behaviour
because such a change is not a bug fix.

 drivers/net/ethernet/intel/igb/igb.h |  1 +
 drivers/net/ethernet/intel/igb/igb_ethtool.c |  5 -
 drivers/net/ethernet/intel/igb/igb_main.c| 16 ++--
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb.h 
b/drivers/net/ethernet/intel/igb/igb.h
index c2bd4f9..212d668 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -540,6 +540,7 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, 
unsigned char *va,
 struct sk_buff *skb);
 int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
 int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
+void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
 #ifdef CONFIG_IGB_HWMON
 void igb_sysfs_exit(struct igb_adapter *adapter);
 int igb_sysfs_init(struct igb_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c 
b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index d5673eb..0afc091 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2991,6 +2991,7 @@ static int igb_set_channels(struct net_device *netdev,
 {
struct igb_adapter *adapter = netdev_priv(netdev);
unsigned int count = ch->combined_count;
+   unsigned int max_combined = 0;
 
/* Verify they are not requesting separate vectors */
if (!count || ch->rx_count || ch->tx_count)
@@ -3001,11 +3002,13 @@ static int igb_set_channels(struct net_device *netdev,
return -EINVAL;
 
/* Verify the number of channels doesn't exceed hw limits */
-   if (count > igb_max_channels(adapter))
+   max_combined = igb_max_channels(adapter);
+   if (count > max_combined)
return -EINVAL;
 
if (count != adapter->rss_queues) {
adapter->rss_queues = count;
+   igb_set_flag_queue_pairs(adapter, max_combined);
 
/* Hardware has to reinitialize queues and interrupts to
 * match the new configuration.
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c 
b/drivers/net/ethernet/intel/igb/igb_main.c
index f287186..59dc2b4 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -1205,10 +1205,14 @@ static int igb_alloc_q_vector(struct igb_adapter 
*adapter,
 
/* allocate q_vector and rings */
q_vector = adapter->q_vector[v_idx];
-   if (!q_vector)
+   if (!q_vector) {
q_vector = kzalloc(size, GFP_KERNEL);
-   else
+   } else if (size > ksize(q_vector)) {
+   kfree_rcu(q_vector, rcu);
+   q_vector = kzalloc(size, GFP_KERNEL);
+   } else {
memset(q_vector, 0, size);
+   }
if (!q_vector)
return -ENOMEM;
 
@@ -2888,6 +2892,14 @@ static void igb_init_queue_configuration(struct 
igb_adapter *adapter)
 
adapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus());
 
+   igb_set_flag_queue_pairs(adapter, max_rss_queues);
+}
+
+void igb_set_flag_queue_pairs(struct igb_adapter *adapter,
+ const u32 max_rss_queues)
+{
+   struct e1000_hw *hw =